[SCM] simplyhtml packaging branch, master, updated. upstream/0.16.05-6-g536db00

Felix Natter fnatter at gmx.net
Mon Jan 21 20:51:24 UTC 2013


The following commit has been merged in the master branch:
commit cc8733fd3572cae5d12d7d189c1b7ee879520b47
Author: Felix Natter <fnatter at gmx.net>
Date:   Mon Jan 21 20:30:58 2013 +0100

    Imported Upstream version 0.16.05

diff --git a/gpl.txt b/gpl.txt
new file mode 100644
index 0000000..1bcc46f
--- /dev/null
+++ b/gpl.txt
@@ -0,0 +1,342 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+
diff --git a/readme.txt b/readme.txt
new file mode 100644
index 0000000..474ddf7
--- /dev/null
+++ b/readme.txt
@@ -0,0 +1,105 @@
+SimplyHTML readme file
+Stage 13, May 24th, 2009
+
+Copyright (c) 2002, 2003 Ulrich Hilger, 2008 Dimitri Polivaev 
+http://simplyhtml.sf.net/
+(see 'License' below)
+
+This file contains
+------------------
+
+  About SimplyHTML
+  Downloads
+  Requirements
+  Installation
+  Usage
+  Compilation
+  License
+
+About SimplyHTML
+----------------
+
+  SimplyHTML is an application for text processing. It
+  stores documents as HTML files in combination with
+  Cascading Style Sheets (CSS).
+
+  SimplyHTML is not intended to be used as an editor for
+  web pages. The application combines text processing
+  features as known from popular word processors with a
+  simple and generic way of storing textual information
+  and styles.
+
+Downloads
+---------
+
+The SimplyHTML offers 3 packages you can download:
+	- SimplyHTML_bin_<Version>.zip - this is the one you need!
+	- SimplyHTML_manual_<Version>.zip - an HTML version of the help
+	  (only for your convenience, the same help is available within
+	  the application)
+	- SimplyHTML_src_<Version>.tar.gz - the source code, if you don't
+	  know what it is, you don't need it!
+
+Requirements
+------------
+
+  To use SimplyHTML, you will need to have a Java JRE
+  (Java Runtime Environment) installed, with a version equal or
+  higher to 1.4.2.
+
+  To compile and run the sources, a Java 2 Standard
+  Edition 1.4 (J2SE) or higher Development Kit (JDK)
+  is required.
+
+  J2SE and/or JRE can be obtained at http://java.sun.com/javase/downloads/
+
+Installation
+------------
+
+  Once you've downloaded the 'bin' and possibly the 'manual' zip
+  files, extract them (keeping the directory structure) into a directory
+  of your choice, e.g. "C:\Program Files\" or "/opt", a directory "SimplyHTML"
+  will be created, with everything you need within it. In the below lines,
+  we'll call this directory <SimplyHTMLDir>.
+  
+Note:
+  Contents of the downloaded zip file can be restored
+  by using one of the many applications capable to
+  extract ZIP files. If you do not have such an
+  application, you can use application Extractor
+  available free at
+
+      http://www.calcom.de/eng/product/xtract.htm
+
+Usage
+-----
+  
+  Starting SimplyHTML can be as easy as double-clicking on the
+  file "<SimplyHTMLDir>/lib/SimplyHTML.jar".
+  If it doesn't work, try to call the following from the command line:
+  	Under Windows:
+  		javaw -jar  "<SimplyHTMLDir>\lib\SimplyHTML.jar"
+  	Under Linux and other UN*X-like OSs:
+  		java -jar  "<SimplyHTMLDir>/lib/SimplyHTML.jar"
+  
+  If you've downloaded the manual, you can see it in your browser by
+  just pointing it to "<SimplyHTMLDir>/manual/index.htm".
+
+Compilation
+-----------
+
+  If you'd like to compile SimplyHTML yourself, we would assume that you
+  know what you're doing, hence only the highlights:
+  - make sure that you have jhall.jar (from JavaHelp2) and gnu-regexp.jar
+    somewhere on your system and adapt the properties 'jhall.jar' and
+    'gnu-regexp.jar' within src/build.xml.
+  - the call of 'ant' within the 'src' sub-directory should then create
+    everything you need one level above.
+
+License
+-------
+
+  This distribution of SimplyHTML is published under the terms
+  and conditions of the GNU General Public License. To read the
+  license, please open file 'gpl.txt' which is part of this
+  package too.
diff --git a/src/MANIFEST.MF b/src/MANIFEST.MF
new file mode 100644
index 0000000..9347bbb
--- /dev/null
+++ b/src/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Main-Class: com.lightdev.app.shtm.App
+Class-Path:  SimplyHTML.jar jhall.jar SimplyHTMLHelp.jar gnu-regexp.jar
+Created-By: Dimitri Polivaev
+
diff --git a/src/build.xml b/src/build.xml
new file mode 100644
index 0000000..2f08058
--- /dev/null
+++ b/src/build.xml
@@ -0,0 +1,129 @@
+<project name="SimplyHTML" default="dist" basedir=".">
+	<property name="version" value="0_16_05" />
+	<property name="src" value="." />
+	<property name="help" value="${src}/com/lightdev/app/shtm/help" />
+	<property name="lib" value="../lib" />
+	<property name="base" value="../" />
+	<property name="build" value="../bin/classes" />
+	<property name="dist" value="../dist" />
+	<property name="dist.api" value="${dist}/api" />
+	<property name="dist.src" value="${dist}/src" />
+	<property name="dist.help" value="${dist}/help" />
+	<property name="dist.lib" value="${dist}/lib" />
+	<property name="SimplyHTML.jar" value="${dist.lib}/SimplyHTML.jar"/>
+	<property name="SimplyHTMLHelp.jar" value="${dist.lib}/SimplyHTMLHelp.jar"/>
+	<property name="post" value="../post" />
+	<property name="debug" value="on" />
+	<property name="java_source_version" value="1.5" />
+	<property name="java_target_version" value="1.5" />
+	<property name="build.compiler" value="modern" />
+	<property name="jhall.jar" value="..\lib\jhall.jar" />
+	<property name="gnu-regexp.jar" value="..\lib\gnu-regexp-1.1.4.jar" />
+	<property name="classpath" value="${jhall.jar}:${gnu-regexp.jar}"/>
+
+	<target name="build" depends="clean">
+		<mkdir dir="${build}"/>
+		<javac	srcdir="${src}"
+			destdir="${build}"
+			classpath="${classpath}"
+			debug="${debug}"
+    	   source="${java_source_version}"
+	       target="${java_target_version}"
+			>
+			<!-- Currently, JUnit tests are only supported inside eclipse due to
+			     classpath problems of the plugins. -->
+			<exclude name="tests/**" />
+			<exclude name="plugins/**" />
+		</javac>
+	</target>
+
+	<target name="dist" depends="jar,help, dist-src"/>
+	<target name="full-dist" depends="dist,javadoc"/>
+	<target name="dist-src">
+		<mkdir dir="${dist.src}" />
+		<copy todir="${dist.src}">
+			<fileset dir="${src}">
+				<include name="**/MANIFEST.MF"/>
+				<include name="**/*.java"/>
+				<include name="**/*.xml"/>
+				<include name="**/*.properties"/>
+				<include name="**/*.gif"/>
+				<include name="**/*.jpg"/>
+				<include name="**/*.htm"/>
+				<include name="**/*.html"/>
+				<include name="**/*.css"/>
+				<include name="**/*.hs"/>
+				<include name="**/*.jhm"/>
+				<include name="**/*.prf"/>
+				<include name="**/*.TAB"/>
+				<include name="**/*.txt"/>
+				<include name="**/*.jar"/>
+				<include name="**/SCHEMA"/>
+				<include name="**/TMAP"/>
+			</fileset>
+		</copy>
+		<tar destfile="${dist}/SimplyHTML_src_${version}.tar.gz" compression="gzip">
+			<tarfileset	dir="${dist.src}" prefix="simplyhtml-${version}/src" 
+				excludes="**/*.jar" />
+			<tarfileset dir="${base}" prefix="simplyhtml-${version}" includes="*.txt" />
+		</tar>
+
+	</target>
+
+	<target name="help">
+		<mkdir dir="${dist.help}" />
+		<copy todir="${dist.help}">
+			<fileset dir="${help}">
+				<include name="**/*"/>
+			</fileset>
+		</copy>
+		<zip destfile="${dist}/SimplyHTML_manual_${version}.zip">
+			<zipfileset dir="${dist.help}" prefix="SimplyHTML/manual" />
+			<zipfileset dir="${base}" prefix="SimplyHTML" includes="*.txt" />
+		</zip>
+	</target>
+	<target name="jar" depends="build">
+		<mkdir dir="${dist.lib}" />
+		<jar jarfile="${SimplyHTML.jar}"
+		     manifest="${src}/MANIFEST.MF"
+			update="true">
+			<fileset dir="${build}">
+			</fileset>
+ 			<fileset dir="${src}">
+ 				<include name="com/lightdev/app/shtm/resources/**"/>
+			</fileset>
+		</jar>
+		<jar jarfile="${SimplyHTMLHelp.jar}"
+			update="true">
+			<fileset dir="${src}">
+				<include name="com/lightdev/app/shtm/help/**"/>
+			</fileset>
+		</jar>
+		<copy file="${jhall.jar}" tofile="${dist.lib}/jhall.jar" />
+		<copy file="${gnu-regexp.jar}" tofile="${dist.lib}/gnu-regexp.jar" />
+		<zip destfile="${dist}/SimplyHTML_bin_${version}.zip">
+			<zipfileset dir="${dist.lib}" prefix="SimplyHTML/lib" />
+			<zipfileset dir="${base}" prefix="SimplyHTML" includes="*.txt" />
+		</zip>
+	</target>
+	<target name="clean">
+		<delete dir="${build}"  quiet="true"/>
+		<delete dir="${dist}"  quiet="true"/>
+		<delete>
+			<fileset defaultexcludes="no" dir="${src}" includes="**/*~"/>
+			<fileset defaultexcludes="no" dir="${src}" includes="**/backup/**"/>
+		</delete>
+
+	</target>
+	<target name="javadoc">
+		<mkdir dir="${dist.api}" />
+		<javadoc
+			sourcepath="${src}"
+			destdir="${dist.api}"
+			packagenames="com.lightdev.*,de.calcom.*"
+			classpath="${classpath}"
+		/>
+	</target>
+
+</project>
+
diff --git a/src/com/lightdev/app/shtm/AboutBox.java b/src/com/lightdev/app/shtm/AboutBox.java
new file mode 100644
index 0000000..8f7afa9
--- /dev/null
+++ b/src/com/lightdev/app/shtm/AboutBox.java
@@ -0,0 +1,166 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.AWTEvent;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowEvent;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.EtchedBorder;
+
+/**
+ * A dialog to display information about application SimplyHTML.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class AboutBox extends JDialog implements ActionListener {
+    /** button to close the dialog */
+    JButton closeButton = new JButton("Close");
+    /** name of the license file */
+    private final String LICENSE = "resources/gpl.txt";
+
+    /**
+     * construct an <code>AboutBox</code>.
+     *
+     * @param parent  the parent frame of the about box
+     */
+    public AboutBox(final Frame parent) {
+        super(parent);
+        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+        closeButton.addActionListener(this);
+        closeButton.setText(Util.getResourceString("closeBtnName"));
+        constructFrame();
+        setTitle(Util.getResourceString("aboutFrameTitle"));
+        pack();
+    }
+
+    /**
+     * construct the dialog contents
+     */
+    private void constructFrame() {
+        /** initialize dialog components */
+        final Container contentPane = getContentPane();
+        final JPanel infoPane = new JPanel();
+        final JPanel imagePane = new JPanel();
+        final JPanel textPane = new JPanel();
+        final JPanel buttonPane = new JPanel();
+        final JPanel northPane = new JPanel();
+        final JPanel emptyPane = new JPanel();
+        final LicensePane licPane = new LicensePane(new Dimension(650, 200), LICENSE);
+        final JLabel imageLabel = new JLabel(new ImageIcon(this.getClass().getResource(
+            Util.getResourceString("splashImage"))));
+        final JLabel emptyLabel = new JLabel("");
+        final JLabel appTitleLabel = new JLabel(FrmMain.APP_NAME);
+        final JLabel appStageLabel = new JLabel(FrmMain.VERSION);
+        final JLabel appCopyrightLabel = new JLabel("Copyright (c) 2002-2008 Ulrich Hilger, Dimitry Polivaev");
+        final JLabel appHomepageLabel = new JLabel("http://simplyhtml.sf.net/");
+        /* set the dialog title */
+        setTitle("About this application");
+        /* highlight the application name with an appropriate font */
+        appTitleLabel.setFont(new Font("SansSerif", Font.BOLD, 12));
+        /* load the application image into a panel */
+        imagePane.setLayout(new FlowLayout());
+        imagePane.add(imageLabel);
+        imagePane.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
+        /**
+         * textPane is the panel where all the application infos are shown.
+         * Infos are shown in a one columns grid of labels, each on one row.
+         */
+        textPane.setLayout(new GridLayout(6, 1, 5, 5));
+        textPane.add(emptyLabel);
+        textPane.add(appTitleLabel);
+        textPane.add(appStageLabel);
+        textPane.add(appCopyrightLabel);
+        textPane.add(appHomepageLabel);
+        /**
+         * infoPane shows the application image and the application info text
+         * in a one row, two column grid.
+         */
+        infoPane.setLayout(new GridLayout(1, 2, 5, 5));
+        infoPane.add(imagePane);
+        infoPane.add(textPane);
+        /**
+         * northPane is a helper pane to show application image and application
+         * info text left aligned in the upper left corner of the dialog.
+         */
+        northPane.setLayout(new BorderLayout());
+        northPane.add(infoPane, BorderLayout.WEST);
+        northPane.add(emptyPane, BorderLayout.CENTER);
+        /* panel for showing the close button at the dialog bottom */
+        buttonPane.setLayout(new FlowLayout());
+        buttonPane.add(closeButton);
+        /**
+         * now put together all parts of above application info and combine them
+         * with license information
+         */
+        contentPane.setLayout(new BorderLayout());
+        contentPane.add(northPane, BorderLayout.NORTH);
+        contentPane.add(licPane, BorderLayout.CENTER);
+        contentPane.add(buttonPane, BorderLayout.SOUTH);
+    }
+
+    /**
+     * dispose the dialog properly in case of window close events
+     */
+    protected void processWindowEvent(final WindowEvent e) {
+        if (e.getID() == WindowEvent.WINDOW_CLOSING) {
+            cancel();
+        }
+        super.processWindowEvent(e);
+    }
+
+    /**
+     * dispose the dialog
+     */
+    private void cancel() {
+        dispose();
+    }
+
+    /**
+     * implements the ActionListener interface to be notified of
+     * clicks onto the ok button. Closes and disposes the dialog in this case.
+     */
+    public void actionPerformed(final ActionEvent e) {
+        if (e.getSource() == closeButton) {
+            cancel();
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/AbstractPlugin.java b/src/com/lightdev/app/shtm/AbstractPlugin.java
new file mode 100644
index 0000000..d991599
--- /dev/null
+++ b/src/com/lightdev/app/shtm/AbstractPlugin.java
@@ -0,0 +1,383 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.prefs.Preferences;
+
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JMenuItem;
+
+/**
+ * Base class for plug-ins of application SimplyHTML.
+ *
+ * <p>Defines some common methods for reuse in plug-ins. All
+ * settings such as dockLocation or activation state
+ * of a plug-in are stored persistently in a preferences file
+ * with the help of class <code>Prefs</code>. The preferences
+ * file is valid for the current user, so each user has own
+ * plug-in settings.</p>
+ *
+ * <p>Menus are constructed with the help of class
+ * <code>DynamicResource</code>. This class needs menu definitions
+ * accessible in a .properties file as described in the API docs
+ * of <code>DynamicResource</code>. I.e., methods of class
+ * <code>AbstractPlugin</code> only work as defined herein when
+ * accompanied by such .properties file accordingly.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ *
+ * @see com.lightdev.app.shtm.DynamicResource
+ */
+public abstract class AbstractPlugin implements SHTMLPlugin {
+    /**
+     * construct an AbstractPlugin
+     *
+     * <p>Constructor may not have parameters so that
+     * java.lang.Class.newInstance can be used on it.</p>
+     */
+    public AbstractPlugin() {
+        //System.out.println("AbstractPlugin constructor");
+        /*SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+          security.
+        }
+        */
+        prefs = Preferences.userNodeForPackage(getClass());
+    }
+
+    /**
+     * init the plug-in
+     *
+     * this is called by the PluginManager directly after instantiating the plug-in
+     */
+    public void initPlugin(final SHTMLPanelImpl owner) {
+        this.owner = owner;
+    }
+
+    /**
+     * create the plug-in menu
+     */
+    protected void createPluginMenu() {
+        if (pluginMenuId != null) {
+            pMenu = owner.dynRes.createMenu(AbstractPlugin.textResources, pluginMenuId);
+        }
+    }
+
+    /**
+     * create the help menu
+     */
+    protected void createHelpMenu() {
+        if (helpMenuId != null) {
+            hMenu = owner.dynRes.createMenu(AbstractPlugin.textResources, helpMenuId);
+            initHelpMenu();
+        }
+    }
+
+    public void initHelpMenu() {
+    }
+
+    /**
+     * create a frame for the component of this plug-in, if it
+     * has a JComponent to display.
+     */
+    protected void createFrame() {
+        if (c != null) {
+            frame = new JFrame(getGUIName());
+            frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
+            frame.setSize(300, 400);
+            frame.getContentPane().add(c);
+        }
+        frame.pack();
+    }
+
+    /**
+     * create, show or hide frame as needed, depending
+     * on a given dock location
+     *
+     * @param location  the dock location of the plug-in, one of
+     * DOCK_LOCATION_TOP, DOCK_LOCATION_BOTTOM,
+     * DOCK_LOCATION.LEFT, DOCK_LOCATION_RIGHT or DOCK_LOCATION_NONE, if the
+     * component shall not dock.
+     */
+    protected void createFrameAsNeeded(final int location) {
+        if (location == SHTMLPlugin.DOCK_LOCATION_NONE) {
+            if ((frame == null) && (c != null)) {
+                createFrame();
+            }
+            if (frame != null) {
+                frame.setVisible(true);
+            }
+        }
+        else {
+            if (frame != null) {
+                frame.setVisible(false);
+            }
+        }
+    }
+
+    /* ----------- SimplyHTML plugin interface implementation start --------- */
+    /**
+     * initialize the plugin
+     *
+     * @param owner  the owner of this plug-in
+     * @param internalName  the internal name this plug-in shall have
+     * @param pluginMenuId  the id of the plug-in menu in the TextResources,
+     * or null if no plugin-in menu is to be created
+     * @param helpMenuId  the id of the help menu for this plug-in in the
+     * TextResources, or null if no help menu is to be created
+     */
+    public void initPlugin(final SHTMLPanel owner, final String internalName, final String pluginMenuId,
+                           final String helpMenuId) {
+        this.owner = (SHTMLPanelImpl) owner;
+        this.internalName = internalName;
+        this.pluginMenuId = pluginMenuId;
+        this.helpMenuId = helpMenuId;
+        try {
+            //System.out.println("AbstractPlugin this.getClass.getName=" + this.getClass().getName());
+            if (SHTMLPanelImpl.pluginManager != null) {
+                final ClassLoader plLoader = SHTMLPanelImpl.pluginManager.getPluginLoader();
+                if (plLoader != null) {
+                    final ResourceBundle resourceBundle = ResourceBundle.getBundle(this.getClass().getName(),
+                        Locale.getDefault(), plLoader);
+                    textResources = new DefaultTextResources(resourceBundle);
+                    //System.out.println("AbstractPlugin plLoader != null, resources=" + resources);
+                }
+                else {
+                    final DefaultTextResources instance = new DefaultTextResources(ResourceBundle.getBundle(this
+                        .getClass().getName(), Locale.getDefault()));
+                    textResources = instance;
+                    //System.out.println("AbstractPlugin plLoader == null, resources=" + resources);
+                }
+            }
+            else {
+                final DefaultTextResources instance = new DefaultTextResources(ResourceBundle.getBundle(this.getClass()
+                    .getName(), Locale.getDefault()));
+                textResources = instance;
+                //System.out.println("AbstractPlugin pluginManager = null, resources=" + resources);
+            }
+            active = prefs.getBoolean(internalName + PREFSID_PLUGIN_ACTIVE, true);
+            dockLocation = prefs.getInt(internalName + PREFSID_PLUGIN_DOCK_LOCATION, SHTMLPlugin.DOCK_LOCATION_LEFT);
+            createFrameAsNeeded(dockLocation);
+        }
+        catch (final MissingResourceException mre) {
+            Util.errMsg(null, this.getClass().getName() + ".properties not found", mre);
+        }
+    }
+
+    /**
+     * set the owner of this plug-in
+     *
+     * @param owner  the main frame of the instance of SimplyHTML creating the plug-in
+     */
+    public void setOwner(final SHTMLPanelImpl owner) {
+        this.owner = owner;
+    }
+
+    /**
+     * get the owner of this plug-in
+     *
+     * @return the owner of this plug-in
+     */
+    public SHTMLPanelImpl getOwner() {
+        return owner;
+    }
+
+    /**
+     * set status of plug-in and persistently store setting in
+     * a preferences file
+     *
+     * @param isActive  indicates whether or not the plug-in shall be activated
+     */
+    public void setStatus(final boolean isActive) {
+        active = isActive;
+        prefs.putBoolean(getInternalName() + PREFSID_PLUGIN_ACTIVE, isActive);
+        try {
+            prefs.flush();
+        }
+        catch (final Exception e) {
+            Util.errMsg(null, e.getMessage(), e);
+        }
+    }
+
+    /**
+     * set the location the component returned by getDockComponent()
+     * shall be docked at. Persistently store setting in
+     * a preferences file.
+     *
+     * @param location the dock location, one of DOCK_LOCATION_TOP, DOCK_LOCATION_BOTTOM,
+     * DOCK_LOCATION.LEFT, DOCK_LOCATION_RIGHT or DOCK_LOCATION_NONE, if the
+     * component shall not dock.
+     */
+    public void setDockLocation(final int location) {
+        dockLocation = location;
+        prefs.putInt(getInternalName() + PREFSID_PLUGIN_DOCK_LOCATION, location);
+        try {
+            prefs.flush();
+        }
+        catch (final Exception e) {
+            Util.errMsg(null, e.getMessage(), e);
+        }
+        createFrameAsNeeded(location);
+    }
+
+    /**
+     * get a menu of actions this plug-in provides.
+     *
+     * <p><code>JMenu</code> is a decendant of <code>JMenuItem</code>
+     * so this method may return a single menu item up to a whole
+     * structure of submenus in its return value.</p>
+     *
+     * @return the plug-in menu
+     */
+    public JMenuItem getPluginMenu() {
+        return pMenu;
+    }
+
+    /**
+     * get a menu item providing documentation about this
+     * plug-in.
+     *
+     * <p><code>JMenu</code> is a decendant of <code>JMenuItem</code>
+     * so this method may return a single menu item up to a whole
+     * structure of submenus in its return value.</p>
+     *
+     * @return a menu item with help for this plug-in
+     */
+    public JMenuItem getHelpMenu() {
+        return hMenu;
+    }
+
+    /**
+     * get the name of the plug-in as it shall appear
+     * on a GUI.
+     *
+     * @return the name of the plug-in
+     */
+    public String getGUIName() {
+        return "AbstractPlugin";
+    }
+
+    /**
+     * get the name used internally for this plug-in
+     *
+     * @return the internal name of this plug-in
+     */
+    public String getInternalName() {
+        return internalName;
+    }
+
+    /**
+     * get the location the component returned by getDockComponent()
+     * shall be docked at.
+     *
+     * @return the dock location, one of DOCK_LOCATION_TOP, DOCK_LOCATION_BOTTOM,
+     * DOCK_LOCATION.LEFT, DOCK_LOCATION_RIGHT or DOCK_LOCATION_NONE, if the
+     * component shall not dock.
+     */
+    public int getDockLocation() {
+        return dockLocation;
+    }
+
+    /**
+     * get the component that this plug-in produces, if any
+     *
+     * @return the component produced by this plug-in, or null if none
+     * is produced
+     */
+    public JComponent getComponent() {
+        return c;
+    }
+
+    /**
+     * get the status of the plug-in
+     *
+     * @return true, if activated, false if not
+     */
+    public boolean isActive() {
+        return active;
+    }
+
+    /**
+     * get a string from the resource bundle of the owner of this plug-in
+     *
+     * @param nm  the name of the string resource to get
+     *
+     * @return the string with the given name or null, if none is found
+     */
+    public String getOwnerResString(final String nm) {
+        return Util.getResourceString(SHTMLPanelImpl.getResources(), nm);
+    }
+
+    /**
+     * get an action from the resource bundle of the owner of this plug-in
+     *
+     * @param cmd  the name of the action to get
+     *
+     * @return the action with the given name or null, if none is found
+     */
+    public Action getOwnerAction(final String cmd) {
+        return owner.getDynRes().getAction(cmd);
+    }
+
+    /* ----------- SimplyHTML plugin interface implementation end --------- */
+    /* --------------- class fields start --------------------- */
+    /** TextResources of plug-in */
+    public static TextResources textResources;
+    /** constant for active setting in preferences file */
+    public static final String PREFSID_PLUGIN_ACTIVE = "Active";
+    /** constant for dock location setting in preferences file */
+    public static final String PREFSID_PLUGIN_DOCK_LOCATION = "DockLocation";
+    /** the internal name of this plug-in */
+    protected String internalName;
+    /** the id in the ResourceFile for the menu of this plug-in */
+    protected String pluginMenuId;
+    /** the id in the ResourceFile for the help menu of this plug-in */
+    protected String helpMenuId;
+    /** the plug-in menu provided by this plug-in */
+    protected JMenuItem pMenu = null;
+    /** the help menu provided by this plug-in */
+    protected JMenuItem hMenu = null;
+    /** status of plug-in */
+    protected boolean active = true;
+    /** current dock location */
+    protected int dockLocation = SHTMLPlugin.DOCK_LOCATION_LEFT;
+    /** component of this plug-in */
+    protected JComponent c = null;
+    /** JFrame for dockLocation=none */
+    protected JFrame frame = null;
+    /** reference for user preferences for this class */
+    protected Preferences prefs;
+    /** the owner of this plug in */
+    protected SHTMLPanelImpl owner;
+    /* ------------- class fields end ------------------ */
+}
diff --git a/src/com/lightdev/app/shtm/ActionBuilder.java b/src/com/lightdev/app/shtm/ActionBuilder.java
new file mode 100644
index 0000000..6fc6e12
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ActionBuilder.java
@@ -0,0 +1,5 @@
+package com.lightdev.app.shtm;
+
+public interface ActionBuilder {
+	void initActions(SHTMLPanel panel);
+}
diff --git a/src/com/lightdev/app/shtm/AnchorDialog.java b/src/com/lightdev/app/shtm/AnchorDialog.java
new file mode 100644
index 0000000..cb58447
--- /dev/null
+++ b/src/com/lightdev/app/shtm/AnchorDialog.java
@@ -0,0 +1,383 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.URL;
+import java.util.Hashtable;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultHighlighter;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.ElementIterator;
+import javax.swing.text.Highlighter;
+import javax.swing.text.html.HTML;
+
+/**
+ * Dialog to create and edit link anchors.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ *
+ */
+class AnchorDialog extends DialogShell implements ActionListener, CaretListener, ListSelectionListener,
+        DocumentListener {
+    /** dialog components */
+    private JList anchorList;
+    private JButton addAnchor;
+    private JButton delAnchor;
+    private SHTMLEditorPane editor;
+    private DocumentPane dp;
+    /** the document this dialog was constructed with */
+    private Document doc = null;
+    /** the URL this document was loaded from (if loaded from this dialog) */
+    private URL url = null;
+    /** table for document anchors */
+    private final Hashtable anchorTable = new Hashtable();
+    /** indicates whether or not changes to the document need to be saved */
+    private boolean needsSaving = true;
+    /** the help id for this dialog */
+    private static final String helpTopicId = "item165";
+
+    //private int renderMode;
+    /**
+     * create an <code>AnchorDialog</code>
+     *
+     * @param parent  the parent dialog of this dialog
+     * @param title  the dialog title
+     * @param doc  the document to edit anchors of
+     */
+    public AnchorDialog(final Dialog parent, final String title, final Document doc) {
+        super(parent, title, helpTopicId);
+        initDialog(doc, null/*, renderMode*/);
+    }
+
+    /**
+     * create an <code>AnchorDialog</code>
+     *
+     * @param parent  the parent frame of this dialog
+     * @param title  the dialog title
+     * @param doc  the document to edit anchors of
+     */
+    public AnchorDialog(final Frame parent, final String title, final Document doc) {
+        super(parent, title, helpTopicId);
+        initDialog(doc, null/*, renderMode*/);
+    }
+
+    /**
+     * create an <code>AnchorDialog</code>
+     *
+     * @param parent  the parent frame of this dialog
+     * @param title  the dialog title
+     * @param url  the document url
+     */
+    public AnchorDialog(final Dialog parent, final String title, final URL url) {
+        super(parent, title, helpTopicId);
+        initDialog(null, url/*, renderMode*/);
+    }
+
+    /**
+     * create an <code>AnchorDialog</code>
+     *
+     * @param parent  the parent frame of this dialog
+     * @param title  the dialog title
+     * @param url  the document url
+     */
+    public AnchorDialog(final Frame parent, final String title, final URL url) {
+        super(parent, title, helpTopicId);
+        initDialog(null, url/*, renderMode*/);
+    }
+
+    /**
+     * initialize this <code>AnchorDialog</code>
+     *
+     * <p>If a document is passed, anchors of this document
+     * are edited. If doc is null and a url is passed, this
+     * document is loaded (and saved).</p>
+     *
+     * @param doc  the document to edit anchors of, or null
+     * @param url  the url to load a document from, or null
+     */
+    private void initDialog(final Document doc, final URL url) {
+        this.url = url;
+        //this.renderMode = renderMode;
+        // create anchor panel
+        final JPanel anchorPanel = new JPanel(new BorderLayout());
+        anchorPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("anchorPanelLabel")));
+        //getAnchors(doc);
+        anchorList = new JList(/*anchorTable.keySet().toArray()*/);
+        anchorPanel.add(new JScrollPane(anchorList), BorderLayout.CENTER);
+        anchorList.addListSelectionListener(this);
+        addAnchor = new JButton(Util.getResourceString("addImgBtnTitle"));
+        addAnchor.addActionListener(this);
+        delAnchor = new JButton(Util.getResourceString("delImgBtnTitle"));
+        delAnchor.addActionListener(this);
+        // use a help panel to add add/del buttons
+        JPanel helpPanel = new JPanel();
+        helpPanel.add(addAnchor);
+        helpPanel.add(delAnchor);
+        anchorPanel.add(helpPanel, BorderLayout.SOUTH);
+        // init DocumentPane
+        if (doc != null) {
+            needsSaving = false;
+            dp = new DocumentPane(/*renderMode*/);
+            doc.addDocumentListener(this);
+            dp.setDocument(doc);
+            this.doc = doc;
+        }
+        else {
+            needsSaving = true;
+            dp = new DocumentPane(url, 1/*, renderMode*/);
+            this.doc = dp.getDocument();
+        }
+        // init editor to our needs
+        editor = dp.getEditor();
+        editor.setEditable(false);
+        editor.addCaretListener(this);
+        // create document panel
+        final JPanel docPanel = new JPanel(new BorderLayout());
+        docPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("docPanelLabel")));
+        docPanel.add(editor, BorderLayout.CENTER);
+        // use a help panel to properly align anchorPanel and docPanel
+        helpPanel = new JPanel(new BorderLayout());
+        helpPanel.add(anchorPanel, BorderLayout.WEST);
+        helpPanel.add(docPanel, BorderLayout.CENTER);
+        // get content pane of DialogShell to add components to
+        final Container contentPane = super.getContentPane();
+        ((JComponent) contentPane).setPreferredSize(new Dimension(600, 500));
+        contentPane.add(helpPanel, BorderLayout.CENTER);
+        // add help button
+        // cause optimal placement of all elements
+        pack();
+        updateAnchorList();
+        addAnchor.setEnabled(false);
+        delAnchor.setEnabled(false);
+    }
+
+    /**
+     * overridden to addd some custom cleanup upon closing of dialog
+     */
+    public void dispose() {
+        editor.removeCaretListener(this);
+        doc.removeDocumentListener(this);
+        super.dispose();
+    }
+
+    /**
+     * re-display the list of anchors of the document
+     */
+    private void updateAnchorList() {
+        getAnchors(doc);
+        anchorList.setListData(anchorTable.keySet().toArray());
+    }
+
+    /**
+     * get the anchors of a given document
+     *
+     * @param doc the document to get anchors from
+     */
+    private void getAnchors(final Document doc) {
+        HTML.Tag.A.toString();
+        Object nameAttr;
+        Object link;
+        anchorTable.clear();
+        final ElementIterator eli = new ElementIterator(doc);
+        Element elem = eli.first();
+        while (elem != null) {
+            link = elem.getAttributes().getAttribute(HTML.Tag.A);
+            if (link != null) {
+                nameAttr = ((AttributeSet) link).getAttribute(HTML.Attribute.NAME);
+                if (nameAttr != null) {
+                    //model.addElement(nameAttr);
+                    anchorTable.put(nameAttr, elem);
+                }
+            }
+            elem = eli.next();
+        }
+    }
+
+    /**
+     * get an anchor name and add it at the current editor location
+     */
+    private void doAddAnchor() {
+        final String anchorName = Util.nameInput(null, "", ".*", "addAnchorTitle", "addAnchorText");
+        if (anchorName != null) {
+            editor.insertAnchor(anchorName);
+            saveChanges();
+            updateAnchorList();
+        }
+    }
+
+    /**
+     * save changes to the document
+     */
+    private void saveChanges() {
+        if (needsSaving) {
+            if (url != null) {
+                try {
+                    dp.saveDocument(/*renderMode*/);
+                }
+                catch (final Exception e) {
+                    Util.errMsg(this, e.getMessage(), e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the anchor currently selected in the list of anchors.
+     *
+     * @return  the anchor name, or null if none is selected
+     */
+    public String getAnchor() {
+        String anchorName = null;
+        if (anchorList.getSelectedIndex() > -1) {
+            anchorName = anchorList.getSelectedValue().toString();
+        }
+        return anchorName;
+    }
+
+    /**
+     * remove an anchor from the document
+     */
+    private void doDelAnchor() {
+        final String anchorName = anchorList.getSelectedValue().toString();
+        dp.getEditor().removeAnchor(anchorName);
+        saveChanges();
+        updateAnchorList();
+    }
+
+    /**
+     * ActionListener implementatin for proper handling of
+     * buttons
+     */
+    public void actionPerformed(final ActionEvent e) {
+        final Object src = e.getSource();
+        if (src.equals(addAnchor)) {
+            doAddAnchor();
+        }
+        else if (src.equals(delAnchor)) {
+            doDelAnchor();
+        }
+        else {
+            super.actionPerformed(e);
+        }
+    }
+
+    /**
+     * ListSelectionListener implementation to properly react to
+     * changes in the list of anchors
+     */
+    public void valueChanged(final ListSelectionEvent e) {
+        final Object src = e.getSource();
+        if (src.equals(anchorList)) {
+            //if(!ignoreAnchorListChanges) {
+            final Highlighter h = editor.getHighlighter();
+            final Highlighter.HighlightPainter p = new DefaultHighlighter.DefaultHighlightPainter(Color.yellow);
+            final Object o = anchorList.getSelectedValue();
+            if (o != null) {
+                final Element elem = (Element) anchorTable.get(anchorList.getSelectedValue());
+                final int start = elem.getStartOffset();
+                int end = elem.getEndOffset();
+                try {
+                    if (end == start) {
+                        end = start + 3;
+                    }
+                    editor.select(start, end);
+                    h.removeAllHighlights();
+                    h.addHighlight(start, end, p);
+                }
+                catch (final BadLocationException ble) {
+                    ble.printStackTrace();
+                }
+            }
+            //}
+        }
+    }
+
+    /**
+     * CaretListener implementation to adjust 'add anchor' button
+     * according to whether or not a selection is present in the document
+     * to possibly add an anchor to
+     */
+    public void caretUpdate(final CaretEvent e) {
+        final Object src = e.getSource();
+        if (src.equals(editor)) {
+            addAnchor.setEnabled(editor.getSelectionStart() != editor.getSelectionEnd());
+            delAnchor.setEnabled(anchorList.getSelectedIndex() > -1);
+        }
+    }
+
+    /* -------- DocumentListener implementation start ------------*/
+    /**
+     * listens to inserts into the document to track whether or not the document
+     * needs to be saved.
+     */
+    public void insertUpdate(final DocumentEvent e) {
+        updateAnchorList();
+    }
+
+    /**
+     * listens to removes into the document to track whether or not the document
+     * needs to be saved.
+     */
+    public void removeUpdate(final DocumentEvent e) {
+        updateAnchorList();
+    }
+
+    /**
+     * listens to changes on the document to track whether or not the document
+     * needs to be saved.
+     */
+    public void changedUpdate(final DocumentEvent e) {
+        updateAnchorList();
+    }
+    /* -------- DocumentListener implementation end ------------*/
+}
diff --git a/src/com/lightdev/app/shtm/App.java b/src/com/lightdev/app/shtm/App.java
new file mode 100644
index 0000000..ec954e6
--- /dev/null
+++ b/src/com/lightdev/app/shtm/App.java
@@ -0,0 +1,69 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.util.prefs.Preferences;
+
+import javax.swing.UIManager;
+
+/**
+ * Main class of application SimplyHTML.
+ *
+ * <p>This class contains method main and opens the application's main
+ * frame.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+public class App {
+    //Main method
+    public static void main(final String[] args) {
+        try {
+            final Preferences prefs = Preferences
+                .userNodeForPackage(Class.forName("com.lightdev.app.shtm.PrefsDialog"));
+            UIManager.setLookAndFeel(prefs.get(PrefsDialog.PREFSID_LOOK_AND_FEEL,
+                UIManager.getCrossPlatformLookAndFeelClassName()));
+            /*
+            The following line causes UIManager to correctly handle alignments
+            of menu items when they do not have an icon.
+
+            At the Java Developer Connection, SKelvin writes:
+            "If the UI class does not find an icon it can't calculate its width :-)
+            It won't work if you just set the property to null (don't ask me
+            why), but setting to any type other than icon works."
+
+            (see http://forum.java.sun.com/thread.jsp?forum=57&thread=126150)
+            */
+            //UIManager.put("Menu.checkIcon", new ImageIcon("") );
+            UIManager.put("Menu.checkIcon", UIManager.get("MenuItem.checkIcon"));
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+        }
+        FrmMain.run(); // create an instance of the app's main window
+    }
+}
diff --git a/src/com/lightdev/app/shtm/AttributeComboBox.java b/src/com/lightdev/app/shtm/AttributeComboBox.java
new file mode 100644
index 0000000..d9efe0c
--- /dev/null
+++ b/src/com/lightdev/app/shtm/AttributeComboBox.java
@@ -0,0 +1,201 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import javax.swing.JComboBox;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+
+/**
+ * ComboBox to show and manipulate an attribute out
+ * of a given set of attribute values.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class AttributeComboBox extends JComboBox implements AttributeComponent {
+    /** CSS attribute key associated with this component */
+    private final Object attributeKey;
+    /** HTML attribute key associated with this component */
+    private final Object htmlAttributeKey;
+    /** attribute names associated with the items of this component */
+    private final String[] names;
+    /** indicates wether or not a call to setValue is the initial one */
+    private int setValCount = 0;
+    /** stores the initial value for tracking changes */
+    private int originalIndex = -2;
+
+    /**
+     * construct an <code>AttributeComboBox</code>
+     *
+     * @param items  the items to appear in the list of this component
+     * @param names  the attributes to associate with items
+     *        (in the same order)
+     * @param key  the CSS attribute key this component represents
+     * @param htmlKey  the HTL attribute key this component represents
+     *
+     * @see getValue
+     */
+    public AttributeComboBox(final String[] items, final String[] names, final Object key, final Object htmlKey) {
+        super(items);
+        this.names = names;
+        attributeKey = key;
+        htmlAttributeKey = htmlKey;
+    }
+
+    /**
+     * set the value of this <code>AttributeComponent</code>
+     *
+     * @param a  the set of attributes possibly having an
+     *          attribute this component can display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(final AttributeSet a) {
+        //System.out.println("AttributeComboBox setValue");
+        //de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
+        //hd.listAttributes(a, 2);
+        boolean success = false;
+        Object valObj;
+        if (attributeKey != null) {
+            valObj = a.getAttribute(attributeKey);
+            if (valObj == null && htmlAttributeKey != null) {
+                valObj = a.getAttribute(htmlAttributeKey);
+                if (valObj != null) {
+                	success = setValue(valObj);
+                }
+            }
+            /*
+             correction start: missing list-style-type attribute from style sheet
+             */
+            else if (valObj == null && attributeKey.equals(CSS.Attribute.LIST_STYLE_TYPE)) {
+                final Object name = a.getAttribute(StyleConstants.NameAttribute);
+                if (name != null && name.toString().equalsIgnoreCase(HTML.Tag.UL.toString())) {
+                	success = setValue("disc");
+                }
+                else if (name != null && name.toString().equalsIgnoreCase(HTML.Tag.OL.toString())) {
+                	success = setValue("decimal");
+                }
+            }
+            if (valObj == null && htmlAttributeKey != null) {
+                if (htmlAttributeKey.equals(HTML.Attribute.ALIGN) || htmlAttributeKey.equals(HTML.Attribute.VALIGN)) {
+                	success = setValue(names[0]);
+                }
+            }
+            /*
+             correction end: missing list-style-type attribute from style sheet
+             */
+            else {
+                //System.out.println("AttributeComboBox setValue value=" + valObj);
+            	success = setValue(valObj);
+            }
+        }
+        else {
+            if (htmlAttributeKey != null) {
+                valObj = a.getAttribute(htmlAttributeKey);
+                if (valObj != null) {
+                	success = setValue(valObj);
+                }
+            }
+        }
+        return success;
+    }
+
+    public void reset() {
+        setValCount = 0;
+        originalIndex = -2;
+    }
+
+    private boolean setValue(final Object valObj) {
+        if (valObj != null) {
+            final String valStr = valObj.toString();
+            int i = 0;
+            while (!valStr.equalsIgnoreCase(names[i])) {
+                i++;
+                if(i >= names.length)
+                	return false;
+            }
+            setSelectedIndex(i);
+            if (++setValCount < 2) {
+                originalIndex = i;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * <p>If one an attribute key is not set, the value will not
+     * be returned for that attribute key. If both attribute keys are
+     * set, two attributes with identical value are returned. Up
+     * to J2SE 1.4, the Java language does not render
+     * CSS.Attribute.VERTICAL_ALIGN but it does render HTML.Attribute.VALIGN.
+     * Some browsers handle it vice versa, so it is useful to
+     * store both attributes.</p>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        final SimpleAttributeSet a = new SimpleAttributeSet();
+        final int value = getSelectedIndex();
+        //System.out.println("AttributeComboBox getValue originalIndex=" + originalIndex + " value=" + value);
+        if (originalIndex != value) {
+            //System.out.println("changed " + attributeKey + " originalIndex=" + originalIndex + " value=" + value);
+            if (attributeKey != null) {
+                Util.styleSheet().addCSSAttribute(a, (CSS.Attribute) attributeKey, names[value]);
+                //a.addAttribute(attributeKey, names[value]);
+            }
+            if (htmlAttributeKey != null) {
+                a.addAttribute(htmlAttributeKey, names[value]);
+            }
+        }
+        return a;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            final SimpleAttributeSet a = new SimpleAttributeSet();
+            final int value = getSelectedIndex();
+            if (attributeKey != null) {
+                Util.styleSheet().addCSSAttribute(a, (CSS.Attribute) attributeKey, names[value]);
+            }
+            if (htmlAttributeKey != null) {
+                a.addAttribute(htmlAttributeKey, names[value]);
+            }
+            return a;
+        }
+        else {
+            return getValue();
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/AttributeComponent.java b/src/com/lightdev/app/shtm/AttributeComponent.java
new file mode 100644
index 0000000..7ff6e75
--- /dev/null
+++ b/src/com/lightdev/app/shtm/AttributeComponent.java
@@ -0,0 +1,57 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import javax.swing.text.AttributeSet;
+
+/**
+ * Defines a set of methods common to components bound to AttributeSets.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+interface AttributeComponent {
+    /**
+     * set the value of this <code>AttributeComponent</code>
+     *
+     * @param a  the set of attributes possibly having an
+     *          attribute this component can display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(AttributeSet a);
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue();
+
+    public AttributeSet getValue(boolean includeUnchanged);
+}
diff --git a/src/com/lightdev/app/shtm/AttributeMapper.java b/src/com/lightdev/app/shtm/AttributeMapper.java
new file mode 100644
index 0000000..1f2fabe
--- /dev/null
+++ b/src/com/lightdev/app/shtm/AttributeMapper.java
@@ -0,0 +1,138 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+
+/**
+ * <p>Maps HTML and CSS attributes to their equivalents to
+ * compensate discrepancies in HTML and CSS rendering of
+ * various different view environments.</p>
+ *
+ * <p>Introduced in stage 5 this class only contains hard wired
+ * fixes to certain discrepancies. Should there come up an increased
+ * number of necessary fixes in future stages, a more generic way
+ * of mapping (such as through a Hashtable of from/to values), etc.
+ * will be done.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class AttributeMapper extends SimpleAttributeSet {
+    public static final int toCSS = 0;
+    public static final int toHTML = 1;
+    public static final int toJava = 2;
+
+    public AttributeMapper() {
+        super();
+    }
+
+    public AttributeMapper(final AttributeSet a) {
+        super(a);
+    }
+
+    public AttributeSet getMappedAttributes(final int direction) {
+        switch (direction) {
+            case toCSS:
+                mapToCSSAttributes();
+                break;
+            case toHTML:
+                mapToHTMLAttributes();
+                break;
+            case toJava:
+                mapToJavaAttributes();
+                break;
+        }
+        //System.out.println("AttributeMapper transformed attributes=");
+        //de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
+        //hd.listAttributes(this, 2);
+        return this;
+    }
+
+    private void mapToCSSAttributes() {
+        final Object cssFontSize = getAttribute(CSS.Attribute.FONT_SIZE);
+        if (cssFontSize != null) {
+            final int fontNumber = Integer.parseInt(cssFontSize.toString());
+            addAttribute(CSS.Attribute.FONT_SIZE, SHTMLPanelImpl.FONT_SIZES[fontNumber - 1] + "pt");
+        }
+        mapToHTMLAttributes();
+    }
+
+    private void mapToHTMLAttributes() {
+        final Object cssFontFamily = getAttribute(CSS.Attribute.FONT_FAMILY);
+        if (cssFontFamily != null) {
+            if (cssFontFamily.toString().equalsIgnoreCase("SansSerif")) {
+                addAttribute(CSS.Attribute.FONT_FAMILY, "SansSerif, Sans-Serif");
+                //System.out.println("mapToHTMLAttributes SansSerif, Sans-Serif");
+            }
+            else if (cssFontFamily.toString().indexOf("Monospaced") > -1) {
+                addAttribute(CSS.Attribute.FONT_FAMILY, "Monospace, Monospaced");
+            }
+        }
+    }
+
+    private void mapToJavaAttributes() {
+        final Object htmlFontFace = getAttribute(HTML.Attribute.FACE);
+        final Object cssFontFamily = getAttribute(CSS.Attribute.FONT_FAMILY);
+        if (htmlFontFace != null) {
+            if (cssFontFamily != null) {
+                removeAttribute(HTML.Attribute.FACE);
+                if (cssFontFamily.toString().indexOf("Sans-Serif") > -1) {
+                    Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "SansSerif");
+                }
+                else if (cssFontFamily.toString().indexOf("Monospace") > -1) {
+                    Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "Monospaced");
+                }
+            }
+            else {
+                removeAttribute(HTML.Attribute.FACE);
+                if (htmlFontFace.toString().indexOf("Sans-Serif") > -1) {
+                    Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "SansSerif");
+                }
+                else if (htmlFontFace.toString().indexOf("Monospace") > -1) {
+                    Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "Monospaced");
+                }
+                else {
+                    Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, htmlFontFace.toString());
+                }
+            }
+        }
+        else {
+            if (cssFontFamily != null) {
+                if (cssFontFamily.toString().indexOf("Sans-Serif") > -1) {
+                    Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "SansSerif");
+                }
+                else if (cssFontFamily.toString().indexOf("Monospace") > -1) {
+                    Util.styleSheet().addCSSAttribute(this, CSS.Attribute.FONT_FAMILY, "Monospaced");
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/AttributePanel.java b/src/com/lightdev/app/shtm/AttributePanel.java
new file mode 100644
index 0000000..db2a83e
--- /dev/null
+++ b/src/com/lightdev/app/shtm/AttributePanel.java
@@ -0,0 +1,131 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.event.ContainerEvent;
+import java.awt.event.ContainerListener;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.JPanel;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+
+/**
+ * Panel set a group of attributes.
+ *
+ * <p>Abstract base class for other panels such as margin or style panel.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+abstract class AttributePanel extends JPanel implements AttributeComponent, ContainerListener {
+    /** container for all AttributeComponents shown on this AttributePanel */
+    private final Vector components = new Vector();
+
+    /**
+     * construct a new AttributePanel
+     */
+    public AttributePanel() {
+        super();
+        this.addContainerListener(this);
+    }
+
+    /**
+     * set the value of this <code>AttributeComponent</code>
+     *
+     * @param a  the set of attributes possibly having an
+     *          attribute this component can display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(final AttributeSet a) {
+        /*
+        System.out.println("AttributePanel setValue");
+        de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
+        hd.listAttributes(a, 4);
+        System.out.println("\r\n");
+        */
+        boolean result = true;
+        final Enumeration elements = components.elements();
+        AttributeComponent ac;
+        while (elements.hasMoreElements()) {
+            ac = (AttributeComponent) elements.nextElement();
+            if (!ac.setValue(a)) {
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        final SimpleAttributeSet attributes = new SimpleAttributeSet();
+        final Enumeration elements = components.elements();
+        AttributeComponent ac;
+        while (elements.hasMoreElements()) {
+            ac = (AttributeComponent) elements.nextElement();
+            attributes.addAttributes(ac.getValue());
+        }
+        return attributes;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            final SimpleAttributeSet attributes = new SimpleAttributeSet();
+            final Enumeration elements = components.elements();
+            AttributeComponent ac;
+            while (elements.hasMoreElements()) {
+                ac = (AttributeComponent) elements.nextElement();
+                attributes.addAttributes(ac.getValue(includeUnchanged));
+            }
+            return attributes;
+        }
+        else {
+            return getValue();
+        }
+    }
+
+    public void componentAdded(final ContainerEvent e) {
+        final Object component = e.getChild();
+        if (component instanceof AttributeComponent) {
+            components.add(component);
+        }
+    }
+
+    public void componentRemoved(final ContainerEvent e) {
+        final Object component = e.getChild();
+        if (component instanceof AttributeComponent) {
+            components.remove(component);
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/BorderPanel.java b/src/com/lightdev/app/shtm/BorderPanel.java
new file mode 100644
index 0000000..bbfb853
--- /dev/null
+++ b/src/com/lightdev/app/shtm/BorderPanel.java
@@ -0,0 +1,219 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.CSS;
+
+/**
+ * Panel to show and manipulate border settings for a rectangular
+ * object such as a table cell
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class BorderPanel extends JPanel implements AttributeComponent {
+    private final Vector components = new Vector();
+    /** the attributes for border width */
+    private CombinedAttribute bWidth;
+    /** the attributes for border color */
+    private CombinedAttribute bColor;
+    /** the color value to compare to for determining changes */
+    private String oColor;
+    /** the width value to compare to for determining changes */
+    private String oWidth;
+    /** indicates if a call to setValue is for initial setting or for changes */
+    private int setValueCalls = 0;
+
+    public BorderPanel() {
+        super();
+        // set layout
+        final GridBagLayout g = new GridBagLayout();
+        setLayout(g);
+        // constraints to use on our GridBagLayout
+        final GridBagConstraints c = new GridBagConstraints();
+        addSettings(g, c, Util.getResourceString("topLabel"), CombinedAttribute.ATTR_TOP, 0, 0);
+        addSettings(g, c, Util.getResourceString("rightLabel"), CombinedAttribute.ATTR_RIGHT, 1, 1);
+        addSettings(g, c, Util.getResourceString("bottomLabel"), CombinedAttribute.ATTR_BOTTOM, 1, 0);
+        addSettings(g, c, Util.getResourceString("leftLabel"), CombinedAttribute.ATTR_LEFT, 0, 1);
+    }
+
+    private void addSettings(final GridBagLayout g, final GridBagConstraints c, final String title, final int side,
+                             final int x, final int y) {
+        final BorderSettings bs = new BorderSettings(title, side);
+        Util.addGridBagComponent(this, bs, g, c, x, y, GridBagConstraints.WEST);
+        components.addElement(bs);
+    }
+
+    /**
+     * set the value of this <code>AttributeComponent</code>
+     *
+     * @param a  the set of attributes possibly having an
+     *          attribute this component can display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(final AttributeSet a) {
+        final boolean success = true;
+        final Enumeration e = components.elements();
+        bWidth = new CombinedAttribute(CSS.Attribute.BORDER_WIDTH, a, true);
+        bColor = new CombinedAttribute(CSS.Attribute.BORDER_COLOR, a, true);
+        if (++setValueCalls < 2) {
+            oColor = bColor.getAttribute();
+            oWidth = bWidth.getAttribute();
+        }
+        while (e.hasMoreElements()) {
+            ((BorderSettings) e.nextElement()).setValue(bWidth, bColor);
+        }
+        return success;
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        BorderSettings bs;
+        for (int i = 0; i < components.size(); i++) {
+            bs = (BorderSettings) components.elementAt(i);
+            bColor.setAttribute(i, bs.getBorderColor());
+            bWidth.setAttribute(i, bs.getBorderWidth());
+        }
+        String newValue = bColor.getAttribute();
+        newValue = bWidth.getAttribute(CombinedAttribute.ATTR_TOP);
+        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_TOP_WIDTH, newValue);
+        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_RIGHT_WIDTH, newValue);
+        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_BOTTOM_WIDTH, newValue);
+        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_LEFT_WIDTH, newValue);
+        return set;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            BorderSettings bs;
+            for (int i = 0; i < components.size(); i++) {
+                bs = (BorderSettings) components.elementAt(i);
+                bColor.setAttribute(i, bs.getBorderColor());
+                bWidth.setAttribute(i, bs.getBorderWidth());
+            }
+            String newValue = bColor.getAttribute();
+            newValue = bWidth.getAttribute(CombinedAttribute.ATTR_TOP);
+            Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_TOP_WIDTH, newValue);
+            Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_RIGHT_WIDTH, newValue);
+            Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_BOTTOM_WIDTH, newValue);
+            Util.styleSheet().addCSSAttribute(set, CSS.Attribute.BORDER_LEFT_WIDTH, newValue);
+            return set;
+        }
+        else {
+            return getValue();
+        }
+    }
+
+    /**
+     * Panel to show and manipulate border settings
+     */
+    private class BorderSettings extends JPanel {
+        /** the border side */
+        private final int side;
+        /** selector for border width */
+        private final SizeSelectorPanel bWidth;
+        /** selector for border color */
+        private final ColorPanel bColor;
+
+        /**
+         * construct a <code>BorderSettings</code> panel
+         *
+         * @param title  the title of this object
+         * @param borderKey  the attribute key for the border width this
+         * object represents
+         * @param colorKey  the attribute key for the border color this
+         * object represents
+         */
+        public BorderSettings(final String title, final int side) {
+            super();
+            this.side = side;
+            // set layout
+            final GridBagLayout g = new GridBagLayout();
+            setLayout(g);
+            // constraints to use on our GridBagLayout
+            final GridBagConstraints c = new GridBagConstraints();
+            // set border and title
+            setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), title));
+            // add the width control and label
+            Util.addGridBagComponent(this, new JLabel(Util.getResourceString("borderWidthLabel")), g, c, 0, 0,
+                GridBagConstraints.EAST);
+            bWidth = new SizeSelectorPanel(CSS.Attribute.BORDER_WIDTH, null, false, SizeSelectorPanel.TYPE_LABEL);
+            Util.addGridBagComponent(this, bWidth, g, c, 1, 0, GridBagConstraints.WEST);
+            // add the color control and label
+            Util.addGridBagComponent(this, new JLabel(Util.getResourceString("borderColorLabel")), g, c, 0, 1,
+                GridBagConstraints.EAST);
+            bColor = new ColorPanel(null, Color.black, CSS.Attribute.BORDER_COLOR);
+            Util.addGridBagComponent(this, bColor, g, c, 1, 1, GridBagConstraints.WEST);
+        }
+
+        public String getBorderColor() {
+            return bColor.getAttr();
+        }
+
+        public String getBorderWidth() {
+            return bWidth.getAttr();
+        }
+
+        /**
+         * set the value of this <code>AttributeComponent</code>
+         *
+         * @param color  the <code>CombinedAttribute</code> to take the color from
+         *
+         */
+        public void setValue(final CombinedAttribute borderWidths, final CombinedAttribute borderColors) {
+            String attr = borderColors.getAttribute(side);
+            //System.out.println("BorderSettings setValue attr='" + attr + "'");
+            if (attr != null) {
+                bColor.setValue(attr);
+            }
+            attr = borderWidths.getAttribute(side);
+            if (attr != null) {
+                bWidth.setValue(attr);
+            }
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/BoundariesPanel.java b/src/com/lightdev/app/shtm/BoundariesPanel.java
new file mode 100644
index 0000000..0ac19cb
--- /dev/null
+++ b/src/com/lightdev/app/shtm/BoundariesPanel.java
@@ -0,0 +1,157 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.Vector;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.CSS;
+
+/**
+ * Panel to show and manipulate boundaries of a rectangular object
+ * such as a table cell.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class BoundariesPanel extends JPanel implements AttributeComponent {
+    /** the components used for single attributes */
+    private final Vector components = new Vector();
+    /** the attributes represented by this compoent */
+    private CombinedAttribute ca;
+    /** the value to compare to determine changes */
+    private String originalValue;
+    /** indicates if a call to setValue is for initial setting or for changes */
+    private int setValueCalls = 0;
+    /** the attribute key this component represents */
+    private final Object key;
+
+    /**
+     * construct a <code>BoundariesPanel</code>.
+     */
+    public BoundariesPanel(final Object attrKey) {
+        super();
+        key = attrKey;
+        // set layout
+        final GridBagLayout g = new GridBagLayout();
+        setLayout(g);
+        // constraints to use on our GridBagLayout
+        final GridBagConstraints c = new GridBagConstraints();
+        Util.addGridBagComponent(this, new JLabel(Util.getResourceString("topLabel")), g, c, 0, 0,
+            GridBagConstraints.EAST);
+        Util.addGridBagComponent(this, new JLabel(Util.getResourceString("rightLabel")), g, c, 2, 0,
+            GridBagConstraints.EAST);
+        Util.addGridBagComponent(this, new JLabel(Util.getResourceString("bottomLabel")), g, c, 0, 1,
+            GridBagConstraints.EAST);
+        Util.addGridBagComponent(this, new JLabel(Util.getResourceString("leftLabel")), g, c, 2, 1,
+            GridBagConstraints.EAST);
+        addSizeSelector(g, c, attrKey, 1, 0); // top
+        addSizeSelector(g, c, attrKey, 3, 0); // right
+        addSizeSelector(g, c, attrKey, 1, 1); // bottom
+        addSizeSelector(g, c, attrKey, 3, 1); // left
+    }
+
+    private void addSizeSelector(final GridBagLayout g, final GridBagConstraints c, final Object attr, final int x,
+                                 final int y) {
+        final SizeSelectorPanel ssp = new SizeSelectorPanel(attr, null, false, SizeSelectorPanel.TYPE_LABEL);
+        Util.addGridBagComponent(this, ssp, g, c, x, y, GridBagConstraints.WEST);
+        components.addElement(ssp);
+    }
+
+    /**
+     * set the value of this <code>AttributeComponent</code>
+     *
+     * @param a  the set of attributes possibly having an
+     *          attribute this component can display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(final AttributeSet a) {
+        final boolean success = true;
+        ca = new CombinedAttribute(key, a, true);
+        if (++setValueCalls < 2) {
+            originalValue = ca.getAttribute();
+        }
+        SizeSelectorPanel ssp;
+        for (int i = 0; i < components.size(); i++) {
+            ssp = (SizeSelectorPanel) components.elementAt(i);
+            ssp.setValue(ca.getAttribute(i));
+        }
+        return success;
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        SizeSelectorPanel ssp;
+        for (int i = 0; i < components.size(); i++) {
+            ssp = (SizeSelectorPanel) components.elementAt(i);
+            if (ssp.valueChanged()) {
+                ca.setAttribute(i, ssp.getAttr());
+            }
+        }
+        final String newValue = ca.getAttribute();
+        if (!originalValue.equalsIgnoreCase(newValue)) {
+            set.addAttribute(key, newValue);
+            Util.styleSheet().addCSSAttribute(set, (CSS.Attribute) key, newValue);
+        }
+        return set;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            SizeSelectorPanel ssp;
+            for (int i = 0; i < components.size(); i++) {
+                ssp = (SizeSelectorPanel) components.elementAt(i);
+                ca.setAttribute(i, ssp.getAttr());
+            }
+            final String newValue = ca.getAttribute();
+            set.addAttribute(key, newValue);
+            Util.styleSheet().addCSSAttribute(set, (CSS.Attribute) key, newValue);
+            return set;
+        }
+        else {
+            return getValue();
+        }
+    }
+
+    public void reset() {
+        setValueCalls = 0;
+        originalValue = null;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/CSSWriter.java b/src/com/lightdev/app/shtm/CSSWriter.java
new file mode 100644
index 0000000..0549e14
--- /dev/null
+++ b/src/com/lightdev/app/shtm/CSSWriter.java
@@ -0,0 +1,180 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Enumeration;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+import javax.swing.text.html.StyleSheet;
+
+/**
+ * A writer for writing a <code>StyleSheet</code> into a CSS file.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ * 
+ */
+class CSSWriter {
+    /** spaces for indent */
+    private char[] indentChars;
+    /** new line character sequence */
+    private final String newLine = System.getProperty("line.separator");
+    /** the writer to write to */
+    private final Writer writer;
+    /** the style sheet to write */
+    private final StyleSheet styleSheet;
+    /** indent length */
+    private int indentLen;
+
+    /**
+     * construct a new CSSWriter
+     *
+     * @param writer  the writer to write to
+     * @param styleSheet  the StyleSheet to write
+     */
+    public CSSWriter(final Writer writer, final StyleSheet styleSheet) {
+        this.writer = writer;
+        this.styleSheet = styleSheet;
+    }
+
+    /** write the style sheet to the given writer */
+    public void write() throws IOException {
+        final Enumeration rules = styleSheet.getStyleNames();
+        while (rules.hasMoreElements()) {
+            writeRule((String) rules.nextElement());
+            try {
+                Thread.currentThread();
+                Thread.sleep(0, 1);
+            }
+            catch (final Exception e) {
+            }
+        }
+    }
+
+    /**
+     * write out a rule with a given name
+     *
+     * <p>Takes the style with the given name from the style sheet passed in the
+     * constructor and writes it to the writer passed in the constructor.</p>.
+     *
+     * @param ruleName  the name of the rule to write out
+     *
+     * @exception IOException if i/o fails
+     */
+    private void writeRule(final String ruleName) throws IOException {
+        writeRule(ruleName, styleSheet.getStyle(ruleName));
+    }
+
+    /**
+     * write out a rule with a given name and style
+     *
+     * <p>Takes the style passed in paramter 'rule' and writes it under
+     * the given name to the writer passed in the constructor.</p>.
+
+     * @param ruleName  the name of the rule to write out
+     * @apram rule  the style to write out
+     *
+     * @exception IOException if i/o fails
+     */
+    public void writeRule(final String ruleName, final AttributeSet rule) throws IOException {
+        //System.out.println("CSSWriter writeRule ruleName=" + ruleName);
+        indentLen = ruleName.length() + 3;
+        if (!ruleName.equalsIgnoreCase(StyleContext.DEFAULT_STYLE)) {
+            writer.write(ruleName);
+            writer.write(" { ");
+            writeStyle(rule);
+            writer.write(newLine);
+        }
+    }
+
+    /**
+     * write a given style
+     *
+     * <p>A style is an AttributeSet which can have other
+     * AttributeSets in the value field of one of its Attributes.
+     * Therefore this is recursively called whenever an Attribute
+     * contains another AttributeSet.</p>
+     *
+     * @param style the <code>Style</code> to write
+     *
+     * @return true, if the style was closed in this run of recursion,
+     *      false if not
+     */
+    private boolean writeStyle(final AttributeSet style) throws IOException {
+        boolean closed = false;
+        final Enumeration names = style.getAttributeNames();
+        Object value;
+        Object key;
+        int count = 0;
+        while (names.hasMoreElements()) {
+            key = names.nextElement();
+            value = style.getAttribute(key);
+            if ((!key.equals(StyleConstants.NameAttribute)) && (!key.equals(StyleConstants.ResolveAttribute))) {
+                if (count > 0) {
+                    writer.write(newLine);
+                    indent(indentLen);
+                }
+                else {
+                    count++;
+                }
+                writer.write(key.toString());
+                writer.write(":");
+                writer.write(value.toString());
+                writer.write(";");
+            }
+            else {
+                if (key.equals(StyleConstants.ResolveAttribute)) {
+                    closed = writeStyle((Style) value);
+                }
+            }
+        }
+        if (!closed) {
+            writer.write(" }");
+            writer.write(newLine);
+            closed = true;
+        }
+        return closed;
+    }
+
+    /**
+     * indent by a given number of characters
+     *
+     * @param len the number of characters to indent
+     */
+    private void indent(final int len) throws IOException {
+        if (indentChars == null || len > indentChars.length) {
+            indentChars = new char[len];
+            for (int i = 0; i < len; i++) {
+                indentChars[i] = ' ';
+            }
+        }
+        writer.write(indentChars, 0, len);
+    }
+}
diff --git a/src/com/lightdev/app/shtm/ColorPanel.java b/src/com/lightdev/app/shtm/ColorPanel.java
new file mode 100644
index 0000000..ff4e9c6
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ColorPanel.java
@@ -0,0 +1,314 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.SystemColor;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.EventObject;
+import java.util.Vector;
+
+import javax.swing.JButton;
+import javax.swing.JColorChooser;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.UIManager;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+
+/**
+ * a panel to display and change a color setting
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class ColorPanel extends JPanel implements ActionListener, AttributeComponent {
+    /** the component showing the chosen color */
+    JTextField colorDisplay = new JTextField();
+    /** default color */
+    private final Color defaultColor;
+    /** the attribute key, this component returns values for */
+    private final Object attributeKey;
+    /** value to compare for determining changes */
+    private Color originalColor;
+    /** indicates if setValue is called initially */
+    private int setValCount = 0;
+    private final JColorChooser colorChooserPane = new JColorChooser();
+
+    /**
+    * construct a color panel
+    *
+    * @param title  the title of the color panel
+    * @param col  the color to be displayed first
+    * @param titleFont  font for title
+    * @param key  the attribute key this component shall return color values for
+    */
+    public ColorPanel(final String title, final Color col, final Object key) {
+        super(new BorderLayout(5, 5));
+        defaultColor = col;
+        attributeKey = key;
+        /** adjust the color display */
+        colorDisplay.setBackground(col);
+        Dimension dim = new Dimension(20, 15);
+        colorDisplay.setMinimumSize(dim);
+        colorDisplay.setMaximumSize(dim);
+        colorDisplay.setPreferredSize(dim);
+        colorDisplay.setEditable(false);
+        /** a button to open a color chooser window */
+        final JButton browseButton = new JButton();
+        browseButton.setText("...");
+        dim = new Dimension(20, 15);
+        browseButton.setMinimumSize(dim);
+        browseButton.setMaximumSize(dim);
+        browseButton.setPreferredSize(dim);
+        browseButton.addActionListener(this);
+        /** a helper panel for proper component placement */
+        final JPanel eastPanel = new JPanel(new FlowLayout());
+        eastPanel.add(colorDisplay);
+        eastPanel.add(browseButton);
+        /** set the title */
+        if ((title != null) && (title.length() > 0)) {
+            final JLabel titleLabel = new JLabel(title);
+            titleLabel.setFont(UIManager.getFont("TextField.font"));
+            add(titleLabel, BorderLayout.WEST);
+            add(eastPanel, BorderLayout.EAST);
+        }
+        else {
+            add(eastPanel, BorderLayout.WEST);
+        }
+    }
+
+    /**
+     * get the selected color
+     *
+     * @return the selected color
+     */
+    public Color getColor() {
+        return colorDisplay.getBackground();
+    }
+
+    /**
+     * set the selected color
+     *
+     * @param color the selected color
+     */
+    private void setColor(final Color color) {
+        //System.out.println("ColorPanel setColor attributeKey=" + attributeKey + ", color=" + color);
+        colorDisplay.setBackground(color);
+        if (++setValCount < 2) {
+            originalColor = color;
+        }
+        fireColorChanged();
+    }
+
+    /**
+     * open a color chooser when a 'Browse' button
+     * is clicked and change the associated color
+     * display accordingly, when another color
+     * is selected from the color chooser
+     */
+    public void actionPerformed(final ActionEvent e) {
+        final Color color = showColorChooserDialog();
+        if (color != null) {
+            setValCount++;
+            setColor(color);
+        }
+    }
+
+    private Color showColorChooserDialog() {
+        // the listener for OK button of the Color Choose Dialog:
+        class ColorTracker implements ActionListener {
+            JColorChooser chooser;
+            Color color;
+
+            public ColorTracker(final JColorChooser c) {
+                chooser = c;
+            }
+
+            public void actionPerformed(final ActionEvent e) {
+                color = chooser.getColor();
+            }
+        }
+        colorChooserPane.setColor(colorDisplay.getBackground()); // setting up the current text color
+        final ColorTracker ok = new ColorTracker(colorChooserPane);
+        final JDialog dialog = JColorChooser.createDialog(this, "Select Color", true, colorChooserPane, ok, null);
+        dialog.setVisible(true); // blocks until user brings dialog down...
+        dialog.dispose();
+        return ok.color;
+    }
+
+    /**
+    * set the value of this <code>AttributeComponent</code>
+    *
+    * @param a  the set of attributes possibly having an
+    *          attribute this component can display
+    *
+    * @return true, if the set of attributes had a matching attribute,
+    *            false if not
+    */
+    public boolean setValue(final AttributeSet a) {
+        Color newSelection = null;
+        if (getAttributeKey() == CSS.Attribute.COLOR) {
+            newSelection = Util.styleSheet().getForeground(a);
+        }
+        if (getAttributeKey() == CSS.Attribute.BACKGROUND_COLOR) {
+            newSelection = Util.styleSheet().getBackground(a);
+            if (newSelection == null) {
+                newSelection = SystemColor.text;
+            }
+        }
+        if (newSelection != null) {
+            setColor(newSelection);
+            return true;
+        }
+        return false;
+    }
+
+    public void setValue(final String value) {
+        //System.out.println("ColorPanel setValue value=" + value);
+        try {
+            setColor(new Color(Integer.parseInt(value.toString().substring(1).toUpperCase(), 16)));
+        }
+        catch (final Exception e) {
+            try {
+                //setColor(Util.styleSheet().getForeground(a));
+                //System.out.println("ColorPanel setValue value=" + value + "=" + Color.getColor(value));
+                setColor(Color.getColor(value));
+            }
+            catch (final Exception e2) {
+                Util.errMsg(null, null, e2);
+            }
+        }
+    }
+
+    public String getAttr() {
+        final String color = "#" + Integer.toHexString(getColor().getRGB()).substring(2);
+        return color;
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        final Color value = getColor();
+        if (value != originalColor) {
+            final String color = "#" + Integer.toHexString(value.getRGB()).substring(2);
+            Util.styleSheet().addCSSAttribute(set, (CSS.Attribute) getAttributeKey(), color);
+            if (getAttributeKey() == CSS.Attribute.COLOR) {
+                set.addAttribute(HTML.Attribute.COLOR, color);
+            }
+            else if (getAttributeKey() == CSS.Attribute.BACKGROUND_COLOR) {
+                set.addAttribute(HTML.Attribute.BGCOLOR, color);
+            }
+        }
+        return set;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            final Color value = getColor();
+            final String color = "#" + Integer.toHexString(value.getRGB()).substring(2);
+            try {
+                Util.styleSheet().addCSSAttribute(set, (CSS.Attribute) getAttributeKey(), color);
+            }
+            catch (final Exception e) {
+                set.addAttribute(getAttributeKey(), color);
+            }
+            //System.out.println("ColorPanel getValue color=" + color);
+            return set;
+        }
+        else {
+            return getValue();
+        }
+    }
+
+    /**
+     * get the attribute key this object was created for
+     *
+     * @return the attribute key this ColorPanel returns values for
+     */
+    public Object getAttributeKey() {
+        return attributeKey;
+    }
+
+    /* -------------- event listener implementation start ----------- */
+    /** the listeners for ColorPanelEvents */
+    private final Vector listeners = new Vector(0);
+
+    /**
+     * add an event listener.
+     *
+     * @param  listener  the event listener to add
+     */
+    public void addColorPanelListener(final ColorPanelListener listener) {
+        listeners.addElement(listener);
+    }
+
+    /**
+     * remove an event listener.
+     *
+     * @param  listener  the event listener to remove
+     */
+    public void removeColorPanelListener(final ColorPanelListener listener) {
+        listeners.removeElement(listener);
+    }
+
+    /** fire a color changed event to all registered listeners */
+    void fireColorChanged() {
+        final Enumeration listenerList = listeners.elements();
+        while (listenerList.hasMoreElements()) {
+            ((ColorPanelListener) listenerList.nextElement()).colorChanged(new ColorPanelEvent(this));
+        }
+    }
+
+    /** the event object definition for ColorPanels */
+    class ColorPanelEvent extends EventObject {
+        public ColorPanelEvent(final Object source) {
+            super(source);
+        }
+    }
+
+    /** the event listener definition for ColorPanels */
+    interface ColorPanelListener extends EventListener {
+        public void colorChanged(ColorPanelEvent e);
+    }
+    /* -------------- event listener implementation end ----------- */
+}
diff --git a/src/com/lightdev/app/shtm/CombinedAttribute.java b/src/com/lightdev/app/shtm/CombinedAttribute.java
new file mode 100644
index 0000000..2e9dd8e
--- /dev/null
+++ b/src/com/lightdev/app/shtm/CombinedAttribute.java
@@ -0,0 +1,341 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.html.CSS;
+
+/**
+ * A class to represent an attribute combining several other attributes.
+ *
+ * <p>The <a href="http://www.w3.org/TR/REC-CSS1">CSS 1.0 specification</a>
+ * defines 'shorthand properties' which can hold more than
+ * one value separated by blanks. Depending on the number of values inside
+ * the property the values are applied following a fixed ratio.</p>
+ *
+ * <p>Following is an excerpt of the spec for CSS property
+ * <code>border-width</code></p>
+ * <pre>
+ * There can be from one to four values, with the following interpretation:
+ *     one value: all four border widths are set to that value
+ *     two values: top and bottom border widths are set to the
+ *                    first value, right and left are set to the second
+ *     three values: top is set to the first, right and left are set to
+ *                    the second, bottom is set to the third
+ *     four values: top, right, bottom and left, respectively
+ * </pre>
+ *
+ * <p>In SimplyHTML this spec is used on properties margin,
+ * padding, border-width and border-color</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class CombinedAttribute {
+    /** index of top value */
+    public static final int ATTR_TOP = 0;
+    /** index of right value */
+    public static final int ATTR_RIGHT = 1;
+    /** index of bottom value */
+    public static final int ATTR_BOTTOM = 2;
+    /** index of left value */
+    public static final int ATTR_LEFT = 3;
+    /** the values of this <code>CombinedAttribute</code> */
+    private final String[] values = new String[4];
+    /**
+     * the attribute key the values of this
+     * <code>CombinedAttribute</code> belong to
+     */
+    private final Object attributeKey;
+    /** indicates which sides were present in the attribute set */
+    private final boolean[] present = new boolean[4];
+    /** table with attribute names from the source attribute set */
+    private final Vector aNames = new Vector();
+    /** indicates if attributes of parent elements shall be used */
+    private final boolean includeParents;
+
+    /**
+     * construct a <code>CombinedAttribute</code> for a certain
+     * attribute out of a given set of attributes
+     *
+     * @param key  the attribute key to get single attribute values from
+     * @param a  the set of attributes to get the attribute of type 'key'
+     */
+    public CombinedAttribute(final Object key, final AttributeSet a, final boolean includeParents) {
+        attributeKey = key;
+        this.includeParents = includeParents;
+        // get names in this attribute set to filter out parent attributes later
+        final Enumeration names = a.getAttributeNames();
+        while (names.hasMoreElements()) {
+            aNames.addElement(names.nextElement());
+        }
+        // now load attributes into this object
+        final Object attr = a.getAttribute(key);
+        if (attr != null) {
+            //System.out.println("  construct CombinedAttribute attr=" + attr);
+            copyValues(Util.tokenize(attr.toString(), " "));
+        }
+        else {
+            copyValues(key, a);
+        }
+    }
+
+    /**
+     * copy the values for individual border settings from a given
+     * set of attributes into the structure top, right, bottom, left of
+     * this <code>CombinedAttribute</code>
+     *
+     * <p>Used in cases where attributes are not found for a 'shorthand
+     * property' such as PADDING or MARGIN.</p>
+     *
+     * @param key  the 'shorthand property' to copy individual attributes for
+     * @param a  the set of attributes to copy from
+     */
+    private void copyValues(final Object key, final AttributeSet a) {
+        if (key.equals(CSS.Attribute.BORDER_WIDTH)) {
+            setValue(ATTR_TOP, CSS.Attribute.BORDER_TOP_WIDTH, a);
+            setValue(ATTR_RIGHT, CSS.Attribute.BORDER_RIGHT_WIDTH, a);
+            setValue(ATTR_BOTTOM, CSS.Attribute.BORDER_BOTTOM_WIDTH, a);
+            setValue(ATTR_LEFT, CSS.Attribute.BORDER_LEFT_WIDTH, a);
+        }
+        else if (key.equals(CSS.Attribute.PADDING)) {
+            setValue(ATTR_TOP, CSS.Attribute.PADDING_TOP, a);
+            setValue(ATTR_RIGHT, CSS.Attribute.PADDING_RIGHT, a);
+            setValue(ATTR_BOTTOM, CSS.Attribute.PADDING_BOTTOM, a);
+            setValue(ATTR_LEFT, CSS.Attribute.PADDING_LEFT, a);
+        }
+        else if (key.equals(CSS.Attribute.MARGIN)) {
+            setValue(ATTR_TOP, CSS.Attribute.MARGIN_TOP, a);
+            setValue(ATTR_RIGHT, CSS.Attribute.MARGIN_RIGHT, a);
+            setValue(ATTR_BOTTOM, CSS.Attribute.MARGIN_BOTTOM, a);
+            setValue(ATTR_LEFT, CSS.Attribute.MARGIN_LEFT, a);
+        }
+    }
+
+    /**
+     * set the value of a certain side from a given attribute key and
+     * set of attributes.
+     *
+     * @param side  the side to set the value for, one of ATTR_TOP,
+     *    ATTR_RIGHT, ATTR_BOTTOM and ATTR_LEFT
+     * @param key  the attribute key to get the value from
+     * @param a  the set of attributes to get the value from
+     */
+    private void setValue(final int side, final Object key, final AttributeSet a) {
+        if ((includeParents) || ((!includeParents) && (aNames.contains(key)))) { // filter out parent attributes
+            final Object attr = a.getAttribute(key);
+            if (attr != null) {
+                values[side] = attr.toString();
+                present[side] = true;
+            }
+            else {
+                values[side] = defaultValue(attributeKey);
+                present[side] = true;
+            }
+        }
+        else { // key not present, set default value
+            values[side] = defaultValue(attributeKey);
+            present[side] = false;
+        }
+    }
+
+    /**
+     * determine whether or not the set of attributes this
+     * <code>CombinedAttribute</code> was created from contained any
+     * of the attributes in this <code>CombinedAttribute</code>
+     *
+     * <p>Can be used for instance to determine whether or not this
+     * <code>CombinedAttribute</code> should be written</p>
+     *
+     * @return true, if this <code>CombinedAttribute</code> contains
+     * default values only, false if not
+     */
+    public boolean isEmpty() {
+        boolean notEmpty = false;
+        int i = 0;
+        while (!notEmpty && i < present.length) {
+            notEmpty = present[i];
+            i++;
+        }
+        return !notEmpty;
+    }
+
+    /**
+     * get the default value for a given key
+     *
+     * @param key  the attribute key to get the default value for
+     *
+     * @return the default value for the given key
+     */
+    private String defaultValue(final Object key) {
+        String value = "0";
+        if (key.equals(CSS.Attribute.BORDER_COLOR)) {
+            value = "#000000";
+        }
+        return value;
+    }
+
+    /**
+     * get the side opposite of a given side
+     *
+     * @param side  the side to get the opposite of
+     *
+     * @return the opposite side of the given side
+     */
+    public int getOppositeSide(final int side) {
+        int oppositeSide = -1;
+        switch (side) {
+            case ATTR_TOP:
+                oppositeSide = ATTR_BOTTOM;
+                break;
+            case ATTR_RIGHT:
+                oppositeSide = ATTR_LEFT;
+                break;
+            case ATTR_BOTTOM:
+                oppositeSide = ATTR_TOP;
+                break;
+            case ATTR_LEFT:
+                oppositeSide = ATTR_RIGHT;
+                break;
+        }
+        return oppositeSide;
+    }
+
+    /**
+     * copy the atribute value(s) found in a 'shorthand property' such
+     * as PADDING or MARGIN into the structure top, right, bottom, left of
+     * this <code>CombinedAttribute</code>
+     *
+     * @param v  the array of Strings holding the found values
+     */
+    private void copyValues(final String[] v) {
+        switch (v.length) {
+            case 1:
+                for (int i = 0; i < values.length; i++) {
+                    values[i] = v[0];
+                }
+                break;
+            case 2:
+                values[ATTR_TOP] = v[ATTR_TOP];
+                values[ATTR_RIGHT] = v[ATTR_RIGHT];
+                values[ATTR_BOTTOM] = v[ATTR_TOP];
+                values[ATTR_LEFT] = v[ATTR_RIGHT];
+                break;
+            case 3:
+                values[ATTR_TOP] = v[ATTR_TOP];
+                values[ATTR_RIGHT] = v[ATTR_RIGHT];
+                values[ATTR_BOTTOM] = v[ATTR_BOTTOM];
+                values[ATTR_LEFT] = v[ATTR_RIGHT];
+                break;
+            case 4:
+                for (int i = 0; i < values.length; i++) {
+                    values[i] = v[i];
+                }
+                break;
+        }
+    }
+
+    /**
+     * set one attribute of this <code>CombinedAttribute</code>
+     *
+     * @param side  the side to set the attribute for, one of ATTR_TOP,
+     *   ATTR_RIGHT, ATTR_BOTTOM, ATTR_LEFT
+     * @param value  the attribute value to set
+     */
+    public void setAttribute(final int side, final String value) {
+        values[side] = value;
+    }
+
+    /**
+     * get one attribute of this <code>CombinedAttribute</code>
+     *
+     * @param side  the side to get the attribute for, one of ATTR_TOP,
+     *   ATTR_RIGHT, ATTR_BOTTOM, ATTR_LEFT
+     *
+     * @return  the attribute value for the specified side or null, if the
+     *    attribute key provided in the constructor was not found
+     */
+    public String getAttribute(final int side) {
+        return values[side];
+    }
+
+    /**
+     * get the attribute key this <code>CombinedAttribute</code> represents
+     *
+     * @return the attribute key
+     */
+    public Object getAttributeKey() {
+        return attributeKey;
+    }
+
+    /**
+     * get all values of this <code>CombinedAttribute</code>
+     * as one attribute.
+     *
+     * @return a String having all values delimited by blanks
+     *     in the order top right, bottom, left or null if no
+     *     attributes were found
+     */
+    public String getAttribute() {
+        String result = null;
+        final StringBuffer buf = new StringBuffer();
+        if (values[0] != null) {
+            buf.append(values[0]);
+            int additionalValueCount = 3;
+            if (values[ATTR_RIGHT].equalsIgnoreCase(values[ATTR_LEFT])) {
+                --additionalValueCount; // total 3
+                if (values[ATTR_TOP].equalsIgnoreCase(values[ATTR_BOTTOM])) {
+                    --additionalValueCount; // total 2
+                    if (values[ATTR_TOP].equalsIgnoreCase(values[ATTR_RIGHT])) {
+                        --additionalValueCount; // total 1
+                    }
+                }
+            }
+            appendValues(buf, additionalValueCount);
+            result = buf.toString();
+        }
+        return result;
+    }
+
+    /**
+     * append a given number of values to a given output buffer
+     * starting with ATTR_RIGHT and necessarily continuing
+     * with ATTR_BOTTOM and ATTR_LEFT ( helper method to getAttribute() )
+     *
+     * @param buf  the output buffer to append to
+     * @param count  the number of values to append
+     */
+    private void appendValues(final StringBuffer buf, final int count) {
+        for (int i = 1; i < count + 1; i++) {
+            buf.append(' ');
+            buf.append(values[i]);
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/DefaultTextResources.java b/src/com/lightdev/app/shtm/DefaultTextResources.java
new file mode 100644
index 0000000..a34c31a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/DefaultTextResources.java
@@ -0,0 +1,57 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Created on 23.11.2006
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.ResourceBundle;
+
+/**
+ * Default implementation of TextResources based on java.util.ResourceBundle
+ * 
+ * @author Dimitri Polivaev
+ * 14.01.2007
+ */
+public class DefaultTextResources implements TextResources {
+    private final Properties properties;
+    private final ResourceBundle resources;
+
+    public DefaultTextResources(final ResourceBundle languageResources) {
+        this(languageResources, null);
+    }
+
+    public DefaultTextResources(final ResourceBundle languageResources, final Properties properties) {
+        super();
+        resources = languageResources;
+        this.properties = properties;
+    }
+
+    public String getString(final String pKey) {
+        try {
+            return resources.getString(pKey);
+        }
+        catch (final MissingResourceException ex) {
+            if (properties != null) {
+                return properties.getProperty(pKey);
+            }
+            throw ex;
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/DialogShell.java b/src/com/lightdev/app/shtm/DialogShell.java
new file mode 100644
index 0000000..a39beee
--- /dev/null
+++ b/src/com/lightdev/app/shtm/DialogShell.java
@@ -0,0 +1,220 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.AWTEvent;
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dialog;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.WindowEvent;
+
+import javax.swing.AbstractButton;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+
+/**
+ * Base class for other dialogs of application SimplyHTML.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class DialogShell extends JDialog implements ActionListener {
+    /** panel containing dialog buttons */
+    protected JPanel buttonPanel;
+    /** button to confirm the operation */
+    protected AbstractButton okButton;
+    /** button to cancel the operation */
+    protected AbstractButton cancelButton;
+    /** button to display context sensitive help */
+    protected AbstractButton helpButton;
+    /**
+     * the result of the operation, one of RESULT_CANCEL and RESULT_OK
+     */
+    private int result;
+    /** result value for a cancelled operation */
+    public static int RESULT_CANCEL = 1;
+    /** result value for a confirmed operation */
+    public static int RESULT_OK = 0;
+    /** id of associated help topic (if any) */
+    protected String helpTopicId = null;
+    /** Listens to enter and cancel. */
+    private KeyListener completionKeyListener = null;
+
+    /**
+     * constructor
+     *
+     * @param parent  the parent dialog
+     * @param title  the title for this dialog
+     */
+    public DialogShell(final Dialog parent, final String title) {
+        super(parent, title);
+        buildDialog();
+    }
+
+    /**
+     * constructor
+     *
+     * @param parent  the parent frame
+     * @param title  the title for this dialog
+     */
+    public DialogShell(final Frame parent, final String title) {
+        super(parent, title);
+        buildDialog();
+    }
+
+    /**
+     * constructor
+     *
+     * @param parent  the parent frame
+     * @param title  the title for this dialog
+     * @param helpTopicId  the id of the help topic to display for this dialog
+     */
+    public DialogShell(final Frame parent, final String title, final String helpTopicId) {
+        super(parent, title);
+        this.helpTopicId = helpTopicId;
+        buildDialog();
+    }
+
+    /**
+     * constructor
+     *
+     * @param parent  the parent dialog
+     * @param title  the title for this dialog
+     * @param helpTopicId  the id of the help topic to display for this dialog
+     */
+    public DialogShell(final Dialog parent, final String title, final String helpTopicId) {
+        super(parent, title);
+        this.helpTopicId = helpTopicId;
+        buildDialog();
+    }
+
+    /**
+     * create dialog components
+     */
+    private void buildDialog() {
+        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+        // construct dialog buttons
+        okButton = new JButton(Util.getResourceString("okBtnName"));
+        cancelButton = new JButton(Util.getResourceString("cancelBtnName"));
+        cancelButton.addActionListener(this);
+        okButton.addActionListener(this);
+        // construct button panel
+        buttonPanel = new JPanel(new FlowLayout());
+        buttonPanel.add(okButton);
+        buttonPanel.add(cancelButton);
+        // construct help button
+        if (helpTopicId != null) {
+            try {
+                helpButton = SHTMLHelpBroker.createHelpButton(helpTopicId);
+                helpButton.setText(Util.getResourceString("helpLabel"));
+                buttonPanel.add(helpButton);
+            }
+            catch (final NoClassDefFoundError e) {
+                helpTopicId = null;
+            }
+        }
+        // add all to content pane of dialog
+        final Container contentPane = getContentPane();
+        contentPane.setLayout(new BorderLayout(5, 5));
+        contentPane.add(buttonPanel, BorderLayout.SOUTH);
+    }
+
+    /**
+     * dispose the dialog properly in case of window close events
+     */
+    protected void processWindowEvent(final WindowEvent e) {
+        if (e.getID() == WindowEvent.WINDOW_CLOSING) {
+            cancel();
+        }
+        super.processWindowEvent(e);
+    }
+
+    /**
+     * cancel the operation
+     */
+    protected void cancel() {
+        result = RESULT_CANCEL;
+        dispose();
+    }
+
+    /**
+     * confirm the operation
+     */
+    protected void confirm() {
+        result = RESULT_OK;
+        dispose();
+    }
+
+    /**
+     * get the result of the operation performed in this dialog
+     *
+     * @return the result, one of RESULT_OK and RESULT_CANCEL
+     */
+    public int getResult() {
+        return result;
+    }
+
+    /**
+     * implements the ActionListener interface to be notified of
+     * clicks onto the ok and cancel button.
+     */
+    public void actionPerformed(final ActionEvent e) {
+        final Object src = e.getSource();
+        if (src == cancelButton) {
+            cancel();
+        }
+        else if (src == okButton) {
+            confirm();
+        }
+    }
+
+    protected KeyListener getCompletionKeyListener() {
+        if (completionKeyListener == null) {
+            completionKeyListener = new KeyAdapter() {
+                public void keyPressed(final KeyEvent e) {
+                    if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                        e.consume();
+                        cancel();
+                    }
+                    else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+                        e.consume();
+                        confirm();
+                    }
+                }
+            };
+        }
+        return completionKeyListener;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/DocNameMissingException.java b/src/com/lightdev/app/shtm/DocNameMissingException.java
new file mode 100644
index 0000000..d8d52c9
--- /dev/null
+++ b/src/com/lightdev/app/shtm/DocNameMissingException.java
@@ -0,0 +1,55 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+/**
+ * Signals that the name of a document in SimplyHTML is not yet set.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class DocNameMissingException extends Exception {
+    /**
+     * Constructs a <code>DocNameMissingException</code> with <code>null</code>
+     * as its error detail message.
+     */
+    public DocNameMissingException() {
+        super();
+    }
+
+    /**
+     * Constructs an <code>IOException</code> with the specified detail
+     * message. The error message string <code>s</code> can later be
+     * retrieved by the <code>{@link java.lang.Throwable#getMessage}</code>
+     * method of class <code>java.lang.Throwable</code>.
+     *
+     * @param   s   the detail message.
+     */
+    public DocNameMissingException(final String s) {
+        super(s);
+    }
+}
diff --git a/src/com/lightdev/app/shtm/DocumentPane.java b/src/com/lightdev/app/shtm/DocumentPane.java
new file mode 100644
index 0000000..b4b0339
--- /dev/null
+++ b/src/com/lightdev/app/shtm/DocumentPane.java
@@ -0,0 +1,954 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.EventObject;
+import java.util.Vector;
+
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.Document;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.StyleSheet;
+
+import com.sun.demo.ExampleFileFilter;
+
+/**
+ * GUI representation of a document.
+ *
+ * <p>Swing already uses three types of classes to implement a model, view,
+ * controller (MVC) approach for a document:</p>
+ *
+ * <p>JTextComponent - the view implementation<br>
+ * Document - the model implementation<br>
+ * EditorKit - the controller implementation</p>
+ *
+ * <p>For a GUI representation of a document, additional parts are needed, such
+ * as a JScrollPane as well as listeners and fields to track the state of
+ * the document while it is represented on a GUI.</p>
+ *
+ * <p><code>DocumentPane</code> wraps all those elements to implement a single
+ * document centric external view to all elements.</p>
+ *
+ * <p>If for instance an application wants to create a new document, it simply
+ * creates an instance of this class instead of having to implement own
+ * methods for instatiating each element (editor pane, scroll pane, etc.)
+ * separately.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class DocumentPane extends JPanel implements DocumentListener, ChangeListener {
+    /** the editor displaying the document in layout view */
+    private final SHTMLEditorPane editorPane;
+    /** the editor displaying the document in HTML code view */
+    private final SyntaxPane sourceEditorPane;
+    /** temporary storage location for this document */
+    private File docTempDir = null;
+    /** the save thread, if a save operation is in progress */
+    public Thread saveThread = null;
+    /** indicator if a save operation was succesful */
+    public boolean saveSuccessful = false;
+    /** indicates if the document text has changed */
+    private boolean documentChanged = false;
+
+    /**
+     * @param documentChanged The documentChanged to set.
+     */
+    private void setDocumentChanged(final boolean documentChanged) {
+        this.documentChanged = documentChanged;
+    }
+
+    /**
+     * @return Returns the documentChanged.
+     */
+    private boolean isDocumentChanged() {
+        return documentChanged;
+    }
+
+    /** indicates if the document text has changed */
+    private boolean htmlChanged = true;
+
+    /**
+     * @param htmlChanged The htmlChanged to set.
+     */
+    private void setHtmlChanged(final boolean htmlChanged) {
+        this.htmlChanged = htmlChanged;
+    }
+
+    /**
+     * @return Returns the htmlChanged.
+     */
+    private boolean isHtmlChanged() {
+        return htmlChanged;
+    }
+
+    /** the name of the document */
+    private String docName;
+    /** the file the current style sheet was loaded from, if any */
+    private final File loadedStyleSheet = null;
+    /** the URL the document was loaded from (if applicable)*/
+    private URL sourceUrl = null;
+    /** JTabbedPane for our views */
+    private JComponent paneHoldingScrollPanes;
+    private final JScrollPane richViewScrollPane;
+    private final JScrollPane sourceViewScrollPane;
+    public static final int VIEW_TAB_LAYOUT = 0;
+    public static final int VIEW_TAB_HTML = 1;
+    /**
+     * a save place for sourceUrl, when a document is to be saved
+     * under a new name and this fails
+     */
+    private URL savedUrl = null;
+    /** indicates if this document was loaded froma file */
+    private boolean loadedFromFile = false;
+    /** default document name */
+    private String DEFAULT_DOC_NAME = "Untitled";
+    /** default name for style sheet, when saved */
+    public static String DEFAULT_STYLE_SHEET_NAME = "style.css";
+    /** number for title of a new document */
+    private int newDocNo;
+    private int activeView;
+
+    //private int renderMode;
+    /**
+     * construct a new <code>DocumentPane</code>.
+     *
+     * <p>A document still has to be either created or loaded after using
+     * this constructor, so it is better to use the constructor doing this
+     * right away instead.</p>
+     */
+    public DocumentPane(/*int renderMode*/) {
+        super();
+        // EditorPane and ScrollPane for layout view
+        editorPane = new SHTMLEditorPane();
+        final SHTMLEditorKit kit = new SHTMLEditorKit(/*renderMode*/);
+        //kit.resetStyleSheet();
+        editorPane.setEditorKit(kit);
+        richViewScrollPane = new JScrollPane(); // create a new JScrollPane,
+        richViewScrollPane.getViewport().setView(editorPane); // ..add the editor pane to it
+        // EditorPane and ScrollPane for html view
+        sourceEditorPane = new SyntaxPane();
+        sourceEditorPane.setFont(new Font("Monospaced", Font.PLAIN, 12));
+        //sourceEditorPane.addKeyListener(rkw);
+        sourceViewScrollPane = new JScrollPane();
+        sourceViewScrollPane.getViewport().setView(sourceEditorPane);
+        // Tabbed pane for HTML and layout views
+        if (Util.showViewsInTabs()) {
+            paneHoldingScrollPanes = new JTabbedPane();
+            paneHoldingScrollPanes.add(richViewScrollPane, VIEW_TAB_LAYOUT);
+            paneHoldingScrollPanes.add(sourceViewScrollPane, VIEW_TAB_HTML);
+            final JTabbedPane tabbedPane = (JTabbedPane) paneHoldingScrollPanes;
+            tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
+            tabbedPane.setTitleAt(VIEW_TAB_LAYOUT, Util.getResourceString("layoutTabTitle"));
+            tabbedPane.setTitleAt(VIEW_TAB_HTML, Util.getResourceString("htmlTabTitle"));
+            tabbedPane.addChangeListener(this);
+            setLayout(new BorderLayout());
+            add(paneHoldingScrollPanes, BorderLayout.CENTER);
+        }
+        else {
+            paneHoldingScrollPanes = new JPanel(new BorderLayout());
+            paneHoldingScrollPanes.add(richViewScrollPane, BorderLayout.CENTER);
+            activeView = VIEW_TAB_LAYOUT;
+            //BorderLayout DOES NOT allow two parts with ..CENTER.
+            //paneHoldingScrollPanes.add(sourceViewScrollPane, BorderLayout.CENTER);
+            //sourceViewScrollPane.setVisible(false);
+            //paneHoldingScrollPanes.addChangeListener(this);
+            setLayout(new BorderLayout());
+            add(paneHoldingScrollPanes, BorderLayout.CENTER);
+        }
+        setDocumentChanged(false); // no changes so far
+        setPreferredSize(new Dimension(550, 550));
+    }
+
+    /**
+     * construct a new DocumentPane with either a new Document or an exisiting
+     * Document that is to be loaded into the DocumentPane upon construction.
+     *
+     * @param docToLoad the document to be loaded. If this is null, a new
+     *      Document is created upon construction of the DocumentPane
+     * @param newDocNo  the number a new document shall have in the
+     * title as long as it is not saved (such as in 'Untitled1'). If an
+     * existing document shall be loaded, this number is ignored
+     */
+    public DocumentPane(final URL docToLoad, final int newDocNo/*, int renderMode*/) {
+        this(/*renderMode*/);
+        DEFAULT_DOC_NAME = Util.getResourceString("defaultDocName");
+        if (docToLoad != null) {
+            loadDocument(docToLoad);
+        }
+        else {
+            this.newDocNo = newDocNo;
+            createNewDocument();
+        }
+    }
+
+    /**
+     * get the <code>JEditorPane</code> of this <code>DocumentPane</code>
+     *
+     * @return the JEditorPane of this DocumentPane
+     */
+    public SHTMLEditorPane getEditor() {
+        return editorPane;
+    }
+
+    /**
+     * get the <code>SyntaxPane</code> of this <code>DocumentPane</code>
+     *
+     * @return the SyntaxPane of this DocumentPane
+     */
+    public SyntaxPane getHtmlEditor() {
+        return sourceEditorPane;
+    }
+
+    /**
+     * @return the selected tab index
+     */
+    public int getSelectedTab() {
+        if (paneHoldingScrollPanes instanceof JTabbedPane) {
+            return ((JTabbedPane) paneHoldingScrollPanes).getSelectedIndex();
+        }
+        return activeView;
+    }
+
+    /**
+     * create a new HTMLDocument and attach it to the editor
+     */
+    public void createNewDocument() {
+        try {
+            final SHTMLEditorKit kit = (SHTMLEditorKit) editorPane.getEditorKit();
+            final SHTMLDocument doc = (SHTMLDocument) kit.createDefaultDocument();
+            //insertStyleRef(doc); // create style sheet reference in HTML header tag
+            //styles = kit.getStyleSheet();
+            doc.addDocumentListener(this); // listen to changes
+            doc.setBase(createTempDir());
+            editorPane.setDocument(doc); // let the document be edited in our editor
+            //doc.putProperty(Document.TitleProperty, getDocumentName());
+            final boolean useStyle = Util.useSteStyleSheet();
+            if (useStyle) {
+                doc.insertStyleRef();
+            }
+        }
+        catch (final Exception e) {
+            Util.errMsg(this, e.getMessage(), e);
+        }
+    }
+
+    public void setDocument(final Document docToSet) {
+        try {
+            editorPane.getEditorKit();
+            final HTMLDocument doc = (HTMLDocument) getDocument();
+            if (doc != null) {
+                doc.removeDocumentListener(this);
+            }
+            docToSet.addDocumentListener(this); // listen to changes
+            editorPane.setDocument(docToSet); // let the document be edited in our editor
+        }
+        catch (final Exception e) {
+            Util.errMsg(this, e.getMessage(), e);
+        }
+    }
+
+    /**
+     * create temporary directory for a newly created document
+     * so that images can be stored and referenced until the document
+     * is saved.
+     *
+     * @return URL of created temporary document directoy
+     */
+    private URL createTempDir() throws MalformedURLException {
+        docTempDir = new File(SHTMLPanelImpl.getAppTempDir().getAbsolutePath() + File.separator + getDocumentName()
+                + File.separator);
+        return docTempDir.toURI().toURL();
+    }
+
+    /**
+     * remove the temporary storage created for this <code>DocumentPane</code>
+     */
+    public void deleteTempDir() {
+        if (docTempDir != null) {
+            Util.deleteDir(docTempDir);
+            docTempDir = null;
+        }
+    }
+
+    /**
+     * load a document found at a certain URL.
+     *
+     * @param url the URL to look for the document
+     */
+    public void loadDocument(final URL url) {
+        try {
+            final SHTMLEditorKit kit = (SHTMLEditorKit) editorPane.getEditorKit();
+            final SHTMLDocument doc = (SHTMLDocument) kit.createEmptyDocument();
+            doc.putProperty("IgnoreCharsetDirective", new Boolean(true));
+            doc.setBase(new File(url.getPath()).getParentFile().toURI().toURL()); // set the doc base
+            final InputStream in = url.openStream(); // get an input stream
+            kit.read(in, doc, 0); // ..and read the document contents from it
+            in.close(); // .. then properly close the stream
+            doc.addDocumentListener(this); // listen to changes
+            editorPane.setDocument(doc); // let the document be edited in our editor
+            setSource(url); // remember where the document came from
+            loadedFromFile = true;
+        }
+        catch (final Exception ex) {
+            Util.errMsg(this, "An exception occurred while loading the file", ex);
+            ex.printStackTrace();
+        }
+    }
+
+    /**
+     * load the rules from a given style sheet file into a new <code>StyleSheet</code> object.
+     *
+     * @param  cssFile  the file object referring to the style sheet to load from
+     *
+     * @return the style sheet with rules loaded
+     */
+    private StyleSheet loadStyleSheet(final File cssFile) throws MalformedURLException, IOException {
+        final StyleSheet s = new StyleSheet();
+        s.importStyleSheet(cssFile.toURI().toURL());
+        return s;
+    }
+
+    /**
+     * saves the document to the file specified in the source of the
+     * <code>DocumentPane</code> and creates the associated style sheet.
+     *
+     * The actual save process only is done, when there is a name to save
+     * to. The class(es) calling this method have to make sure that a
+     * name for new documents is requested from the user, for instance.
+     *
+     * The desired name and location for the save need then to be set using method
+     * setSource prior to a call to this method
+     *
+     * @throws DocNameMissingException to ensure the caller gets notified
+     *        that a save did not take place because of a missing name
+     *        and location
+     */
+    public void saveDocument() throws DocNameMissingException {
+        if (!saveInProgress()) {
+            saveThread = Thread.currentThread(); // store thread for saveInProgress
+            saveSuccessful = false; // if something goes wrong, this remains false
+            File file = null;
+            try {
+                if (sourceUrl != null) {
+                    /* write the HTML document */
+                    if (getSelectedTab() == VIEW_TAB_HTML) {
+                        editorPane.setText(sourceEditorPane.getText());
+                    }
+                    final SHTMLDocument doc = (SHTMLDocument) getDocument();
+                    final OutputStream os = new FileOutputStream(sourceUrl.getPath());
+                    final OutputStreamWriter osw = new OutputStreamWriter(os);
+                    final SHTMLWriter hw = new SHTMLWriter(osw, doc);
+                    hw.write();
+                    osw.flush();
+                    osw.close();
+                    os.flush();
+                    os.close();
+                    /* write the style sheet */
+                    if (doc.hasStyleRef()) {
+                        saveStyleSheet();
+                    }
+                    /*
+                      copy image directory,
+                      if new document or saved from different location
+                    */
+                    saveImages();
+                    /* clean up */
+                    //System.out.println("DocumentPane textChanged = false");
+                    setDocumentChanged(false); // indicate no changes pending anymore after the save
+                    file = new File(sourceUrl.getPath()).getParentFile();
+                    ((HTMLDocument) getDocument()).setBase(file.toURI().toURL()); // set the doc base
+                    deleteTempDir();
+                    //System.out.println("DocumentPane saveSuccessful = true");
+                    saveSuccessful = true; // signal that saving was successful
+                }
+                else {
+                    saveThread = null;
+                    throw new DocNameMissingException();
+                }
+            }
+            catch (final MalformedURLException mue) {
+                if (file != null) {
+                    Util.errMsg(this, "Can not create a valid URL for\n" + file.getAbsolutePath(), mue);
+                }
+                else {
+                    Util.errMsg(this, mue.getMessage(), mue);
+                }
+            }
+            catch (final Exception e) {
+                if (savedUrl != null) {
+                    sourceUrl = savedUrl;
+                }
+                Util.errMsg(this, "An exception occurred while saving the file", e);
+            }
+            saveThread = null;
+            savedUrl = sourceUrl;
+        }
+    }
+
+    /**
+     * determine the directory this <code>DocumentPane</code> references image
+     * files from
+     *
+     * @return the directory image files referenced by this
+     * <code>DocumentPane</code> are found
+     */
+    public File getImageDir() {
+        File srcDir = null;
+        if (savedUrl == null && newDocNo > 0) {
+            // new Document: use temp dir as source
+            srcDir = new File(docTempDir + File.separator + SHTMLPanelImpl.IMAGE_DIR + File.separator);
+        }
+        else {
+            if (savedUrl == null) {
+                // document has been saved before: source is 'sourceUrl'
+                srcDir = new File(new File(sourceUrl.getPath()).getParent() + File.separator + SHTMLPanelImpl.IMAGE_DIR
+                        + File.separator);
+            }
+            else {
+                /*
+                   document has been saved before but now is
+                   to be saved under new name: source is 'old' url
+                */
+                srcDir = new File(new File(savedUrl.getPath()).getParent() + File.separator + SHTMLPanelImpl.IMAGE_DIR
+                        + File.separator);
+            }
+        }
+        return srcDir;
+    }
+
+    /**
+     * save image files
+     */
+    private void saveImages() {
+        final File srcDir = getImageDir();
+        final File destDir = new File(new File(sourceUrl.getPath()).getParent() + File.separator
+                + SHTMLPanelImpl.IMAGE_DIR + File.separator);
+        try {
+            if (srcDir.exists()) {
+                final ExampleFileFilter filter = new ExampleFileFilter();
+                filter.addExtension("gif");
+                filter.addExtension("jpg");
+                filter.addExtension("jpeg");
+                final File[] imgFiles = srcDir.listFiles();
+                for (int i = 0; i < imgFiles.length; i++) {
+                    Util.copyFile(imgFiles[i],
+                        new File(destDir.getAbsolutePath() + File.separator + imgFiles[i].getName()));
+                }
+            }
+        }
+        catch (final Exception e) {
+            Util.errMsg(this, e.getMessage(), e);
+        }
+    }
+
+    /**
+     * indicates whether or not a save process is in progress
+     *
+     * @return true, if a save process is going on, else false
+     */
+    public boolean saveInProgress() {
+        //System.out.println("DocumentPane.saveInProgress=" + (saveThread != null) + " for document " + getDocumentName());
+        return saveThread != null;
+    }
+
+    /**
+     * Saves the style sheet of this document to a CSS file.
+     *
+     * <p>With stage 8, saves a style sheet by merging it with the existing
+     * one with the same name/location. Styles in this style sheet overwrite
+     * styles in the already existing style sheet.</p>
+     */
+    public void saveStyleSheet() throws IOException {
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        final StyleSheet styles = doc.getStyleSheet();
+        final String styleSheetName = getStyleSheetName();
+        if (styleSheetName != null) {
+            final File styleSheetFile = new File(new URL(styleSheetName).getFile());
+            if (!styleSheetFile.exists()) {
+                // no styles present at save location, create new style sheet
+                styleSheetFile.createNewFile();
+            }
+            else {
+                if (loadedFromFile) {
+                    if ((savedUrl == null) || (!savedUrl.getPath().equals(sourceUrl.getPath()))) {
+                        /*
+                            this style sheet was loaded from somewhere else and now is
+                            being saved at a new location where a style sheet exists
+                            havig the same name --> merge
+                        */
+                        mergeStyleSheets(loadStyleSheet(styleSheetFile), styles);
+                    }
+                    else {
+                        /*
+                            same location where styles originally came
+                            from, overwrite existing styles with new version
+                        */
+                        styleSheetFile.delete();
+                        styleSheetFile.createNewFile();
+                    }
+                }
+                else {
+                    /*
+                        this style sheet was newly created and now is
+                        being saved at a location where a style sheet exists
+                        havig the same name --> merge
+                    */
+                    mergeStyleSheets(loadStyleSheet(styleSheetFile), styles);
+                }
+            }
+            final OutputStream os = new FileOutputStream(styleSheetFile);
+            final OutputStreamWriter osw = new OutputStreamWriter(os);
+            CSSWriter cssWriter;
+            cssWriter = new CSSWriter(osw, styles);
+            cssWriter.write();
+            osw.close();
+            os.close();
+        }
+    }
+
+    /**
+     * Merges two style sheets by adding all the rules found
+     * in the source style sheet that are not contained
+     * in the destination style sheet. Assumes the rules
+     * of src and dest are already loaded.
+     *
+     * @param sourceStyleSheet  the source StyleSheet
+     * @param destinationStyleSheet  the destination StyleSheet
+     */
+    private void mergeStyleSheets(final StyleSheet sourceStyleSheet, final StyleSheet destinationStyleSheet)
+            throws IOException {
+        String name;
+        Object elem;
+        final Vector srcNames = Util.getStyleNames(sourceStyleSheet);
+        final Vector destNames = Util.getStyleNames(destinationStyleSheet);
+        final StringWriter sw = new StringWriter();
+        final StringBuffer buf = sw.getBuffer();
+        final CSSWriter cssWriter = new CSSWriter(sw, null);
+        for (int i = 0; i < srcNames.size(); i++) {
+            elem = srcNames.get(i);
+            name = elem.toString();
+            if (destNames.indexOf(elem) < 0) {
+                buf.delete(0, buf.length());
+                cssWriter.writeRule(name, sourceStyleSheet.getStyle(name));
+                destinationStyleSheet.removeStyle(name);
+                destinationStyleSheet.addRule(buf.toString());
+            }
+        }
+    }
+
+    /**
+     * get the URL of the style sheet of this document
+     *
+     * <p>The name is built by<ol>
+     * <li>get the style sheet reference, if none, use default style
+     * sheet name</li>
+     * <li>get the document base</li>
+     * <li>if the style sheet reference is a relative path, resolve base
+     * and relative path</li>
+     * <li>else simply concatenate doc base and style sheet reference</li>
+     * </ol></p>
+     *
+     * @return the URL of the style sheet
+     */
+    private String getStyleSheetName() throws MalformedURLException {
+        String name = DEFAULT_STYLE_SHEET_NAME; //SHTMLEditorKit.DEFAULT_CSS;
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        final String styleRef = doc.getStyleRef();
+        final File file = new File(sourceUrl.getPath()).getParentFile();
+        String newDocBase = null;
+        try {
+            newDocBase = file.toURI().toURL().toString();
+        }
+        catch (final Exception e) {
+            if (file != null) {
+                Util.errMsg(this, "Can not create a valid URL for\n" + file.getAbsolutePath(), e);
+            }
+            else {
+                Util.errMsg(this, e.getMessage(), e);
+            }
+        }
+        if (styleRef != null) {
+            name = Util.resolveRelativePath(styleRef, newDocBase);
+        }
+        else {
+            name = null; // Util.resolveRelativePath(name, newDocBase);
+        }
+        //System.out.println("DocumentPane.getStyleSheetName=" + name);
+        return name;
+    }
+
+    /**
+     * get the name of the document of this pane.
+     *
+     * @return  the name of the document
+     */
+    public String getDocumentName() {
+        String theName;
+        if (docName == null || docName.length() < 1) {
+            theName = DEFAULT_DOC_NAME + " " + Integer.toString(newDocNo);
+        }
+        else {
+            theName = docName;
+        }
+        return theName;
+    }
+
+    /**
+     * indicates whether or not the document needs to be saved.
+     *
+     * @return  true, if changes need to be saved
+     */
+    public boolean needsSaving() {
+        //System.out.println("DocumentPane.needsSaving=" + textChanged + " for document " + getDocumentName());
+        return isDocumentChanged();
+    }
+
+    /**
+     * set the source this document is to be loaded from
+     *
+     * <p>This is only to be used when it is made sure,
+     * that the document is saved at the location specified
+     * by 'source'.</p>
+     *
+     * @param the URL of the source this document is to be loaded from
+     */
+    public void setSource(final URL source) {
+        savedUrl = sourceUrl;
+        sourceUrl = source;
+        final String fName = source.getFile();
+        docName = fName.substring(fName.lastIndexOf("/") + 1);
+        fireNameChanged();
+    }
+
+    /**
+     * get the source, this document was having before its current sourceUrl
+     * was set.
+     *
+     * @return the source URL before a name change
+     */
+    public URL getOldSource() {
+        if (savedUrl == null) {
+            return sourceUrl;
+        }
+        else {
+            return savedUrl;
+        }
+    }
+
+    /**
+     * get the source this document can be loaded from
+     *
+     * @return the URL this document can be loaded from
+     */
+    public URL getSource() {
+        return sourceUrl;
+    }
+
+    /**
+     * indicates whether or not this document was newly created and not saved so
+     * far.
+     *
+     * @return true, if this is a new document that has not been saved so far
+     */
+    public boolean isNewDoc() {
+        return sourceUrl == null;
+    }
+
+    /**
+     * get the document of this <code>DocumentPane</code>
+     *
+     * @return the <code>Document</code> of this <code>DocumentPane</code>
+     */
+    public Document getDocument() {
+        return editorPane.getDocument();
+    }
+
+    HTMLDocument getHTMLDocument() {
+        return (HTMLDocument) sourceEditorPane.getDocument();
+    }
+
+    /**
+     * Switches between the rich text view and the source view, given
+     * tabbed panes are not used. Has no corresponding action; calling
+     * this method is up to the caller application of SimplyHTML; the
+     * application should call the method of the same name available at
+     * SHTMLPanel.
+     */
+    public void switchViews() {
+        if (paneHoldingScrollPanes instanceof JTabbedPane) {
+            return;
+        }
+        // [ Tabbed pane not used ]
+        if (activeView == VIEW_TAB_LAYOUT) {
+            setHTMLView();
+            paneHoldingScrollPanes.remove(richViewScrollPane);
+            paneHoldingScrollPanes.add(sourceViewScrollPane);
+            activeView = VIEW_TAB_HTML;
+        }
+        else {
+            setLayoutView();
+            paneHoldingScrollPanes.remove(sourceViewScrollPane);
+            paneHoldingScrollPanes.add(richViewScrollPane);
+            activeView = VIEW_TAB_LAYOUT;
+        }
+    }
+
+    /**
+     * Switches the DocumentPane to HTML view.
+     */
+    private void setHTMLView() {
+        try {
+            editorPane.getDocument().removeDocumentListener(this);
+            final StringWriter stringWriter = new StringWriter();
+            if (isHtmlChanged()) {
+                editorPane.getEditorKit().write(stringWriter, editorPane.getDocument(), 0,
+                    editorPane.getDocument().getLength());
+                stringWriter.close();
+                String newText = stringWriter.toString();
+                if (!Util.preferenceIsTrue("writeHead", "true")) {
+                    newText = newText.replaceAll("(?ims)<head>.*?(<body)", "$1");
+                }
+                sourceEditorPane.setText(newText);
+                setHtmlChanged(false);
+            }
+            sourceEditorPane.getDocument().addDocumentListener(this);
+            sourceEditorPane.addCaretListener(sourceEditorPane);
+            setHtmlChanged(false);
+        }
+        catch (final Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    /**
+     * Switches the DocumentPane to layout view.
+     */
+    private void setLayoutView() {
+        sourceEditorPane.getDocument().removeDocumentListener(this);
+        sourceEditorPane.removeCaretListener(sourceEditorPane);
+        if (isHtmlChanged()) {
+            editorPane.setText(sourceEditorPane.getText());
+            setHtmlChanged(false);
+        }
+        editorPane.setCaretPosition(0);
+        editorPane.getDocument().addDocumentListener(this);
+        editorPane.requestFocus();
+    }
+
+    /**
+     * Convenience method for obtaining the document text
+     * @return returns the document text as string.
+     */
+    String getDocumentText() {
+        if (getSelectedTab() == VIEW_TAB_HTML) {
+            editorPane.setText(sourceEditorPane.getText());
+        }
+        return editorPane.getText();
+    }
+
+    /**
+     * Convenience method for setting the document text
+     */
+    void setDocumentText(final String sText) {
+        switch (getSelectedTab()) {
+            case VIEW_TAB_LAYOUT:
+                editorPane.setText(sText);
+                break;
+            case VIEW_TAB_HTML:
+                sourceEditorPane.setText(sText);
+                break;
+        }
+        EventQueue.invokeLater(new Runnable() {
+            public void run() {
+                setHtmlChanged(true);
+                setDocumentChanged(false);
+            }
+        });
+    }
+
+    /* ----------------- changeListener implementation start ---------------------- */
+    public void stateChanged(final ChangeEvent e) {
+        final Object src = e.getSource();
+        if (src.equals(paneHoldingScrollPanes)) {
+            switch (getSelectedTab()) {
+                case VIEW_TAB_LAYOUT:
+                    setLayoutView();
+                    break;
+                case VIEW_TAB_HTML:
+                    setHTMLView();
+                    break;
+            }
+        }
+        SHTMLPanelImpl.getOwnerSHTMLPanel(this).updateActions();
+    }
+
+    /* ----------------- changeListener implementation end ------------------------ */
+    /* -------- DocumentListener implementation start ------------*/
+    /**
+     * listens to inserts into the document to track whether or not the document
+     * needs to be saved.
+     */
+    public void insertUpdate(final DocumentEvent e) {
+        setHtmlChanged(true);
+        setDocumentChanged(true);
+    }
+
+    /**
+     * listens to removes from the document to track whether or not the document
+     * needs to be saved.
+     */
+    public void removeUpdate(final DocumentEvent e) {
+        setHtmlChanged(true);
+        setDocumentChanged(true);
+    }
+
+    /**
+     * listens to changes on the document to track whether or not the document
+     * needs to be saved.
+     */
+    public void changedUpdate(final DocumentEvent e) {
+        //System.out.println("changedUpdate setting textChanged=true for " + getDocumentName());
+        if (getSelectedTab() == VIEW_TAB_LAYOUT) {
+            editorPane.updateInputAttributes();
+            setDocumentChanged(true);
+        }
+    }
+
+    /* -------- DocumentListener implementation end ------------*/
+    /* -------- DocumentPaneListener definition start --------------- */
+    /**
+     * interface to be implemented for being notified of
+     * changes to the name of this document
+     */
+    public interface DocumentPaneListener {
+        public void nameChanged(DocumentPaneEvent e);
+
+        public void activated(DocumentPaneEvent e);
+    }
+
+    /** the event object definition for DocumentPaneEvents */
+    class DocumentPaneEvent extends EventObject {
+        public DocumentPaneEvent(final Object source) {
+            super(source);
+        }
+    }
+
+    /** listeners for DocumentPaneEvents */
+    private final Vector dpListeners = new Vector();
+
+    /**
+     * add a DocumentPaneListener to this Document
+     *
+     * @param listener the listener object to add
+     */
+    public void addDocumentPaneListener(final DocumentPaneListener listener) {
+        if (!dpListeners.contains(listener)) {
+            dpListeners.addElement(listener);
+        }
+        //System.out.println("DocumentPane.addDocumentPaneListener docName=" + getDocumentName() + ", listener.count=" + dpListeners.size());
+    }
+
+    /**
+     * remove a DocumentPaneListener from this Document
+     *
+     * @param listener  the listener object to remove
+     */
+    public void removeDocumentPaneListener(final DocumentPaneListener listener) {
+        dpListeners.remove(listener);
+    }
+
+    /**
+     * fire a DocumentPaneEvent to all registered DocumentPaneListeners
+     */
+    public void fireNameChanged() {
+        final Enumeration listenerList = dpListeners.elements();
+        while (listenerList.hasMoreElements()) {
+            ((DocumentPaneListener) listenerList.nextElement()).nameChanged(new DocumentPaneEvent(this));
+        }
+    }
+
+    /**
+     * fire a DocumentPaneEvent to all registered DocumentPaneListeners
+     */
+    public void fireActivated() {
+        final Enumeration listenerList = dpListeners.elements();
+        while (listenerList.hasMoreElements()) {
+            ((DocumentPaneListener) listenerList.nextElement()).activated(new DocumentPaneEvent(this));
+        }
+    }
+
+    /**
+     * remove all listeners
+     */
+    public void removeAllListeners() {
+        dpListeners.clear();
+    }
+
+    public JEditorPane getMostRecentFocusOwner() {
+        switch (getSelectedTab()) {
+            case VIEW_TAB_LAYOUT:
+                return editorPane;
+            case VIEW_TAB_HTML:
+                return sourceEditorPane;
+        }
+        return null;
+    }
+
+    public void setContentPanePreferredSize(final Dimension prefSize) {
+        setPreferredSize(null);
+        paneHoldingScrollPanes.setPreferredSize(null);
+        for (int i = 0; i < paneHoldingScrollPanes.getComponentCount(); i++) {
+            final JScrollPane scrollPane = (JScrollPane) paneHoldingScrollPanes.getComponent(i);
+            scrollPane.setPreferredSize(prefSize);
+            scrollPane.invalidate();
+        }
+    }
+    /* -------- DocumentPaneListener definition end --------------- */
+}
diff --git a/src/com/lightdev/app/shtm/DynamicResource.java b/src/com/lightdev/app/shtm/DynamicResource.java
new file mode 100644
index 0000000..9460781
--- /dev/null
+++ b/src/com/lightdev/app/shtm/DynamicResource.java
@@ -0,0 +1,506 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Component;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.MissingResourceException;
+
+import javax.swing.AbstractAction;
+import javax.swing.AbstractButton;
+import javax.swing.Action;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JSeparator;
+import javax.swing.JToolBar;
+import javax.swing.KeyStroke;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
+
+/**
+ * Provides methods to dynamically combine components and resource bundles.
+ *
+ * <p>The actions, menus and menuitems created by this object are
+ * stored privately inside this object. This allows for later
+ * access to one of the stored items through the action command name.</p>
+ *
+ * <p><b>IMPORTANT:</b> Action command names must be unique, if actions
+ * or menus are added to an instance of this class and if the actions or
+ * menus are defined in different TextResourcess, the action names
+ * must be unique over all TextResourcess involved, because the action
+ * names are used as identifiers for connection of actions to compnents
+ * such as menus and menu items.</p>
+ *
+ * <p>Component creation methods such as createMenu or createMenuItem
+ * expect definitions coming from a TextResources, typically a
+ * text file ending with '.properties'.</p>
+ *
+ * <p>
+ * Inside the .properties file, a menu definition is looking similar to
+ * <pre>
+ *   # plugin menu definition
+ *   plugin=test1 test2 test3
+ *   pluginLabel=Test Plug-In
+ *
+ *   # plugin menu items
+ *   test1Label=Test 1
+ *   test1Image=images/test1.gif
+ *   test1Tip=test menu item 1
+ *   test2Label=Test 2
+ *   test3Label=Test 3
+ * </pre>
+ * </p>
+ *
+ * <p>
+ * The calling class has to define actions named accordingly, e.g.
+ * <pre>
+ *    DynamicResource dynRes = new DynamicResource("com.foo.bar.myPlugin");
+ *    dynRes.addAction("test1", new MyAction("test1");
+ *    dynRes.addAction("test2", new MyAction("test2");
+ *    dynRes.addAction("test3", new MyAction("test3");
+ * </pre>
+ * </p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class DynamicResource {
+    /** name constant for labels in the resource file */
+    public static final String labelSuffix = "Label";
+    /** name constant for action commands in the resource file */
+    private static final String actionSuffix = "Action";
+    /** name constant for indicating image resources in the resource file */
+    public static final String imageSuffix = "Image";
+    /** name constant for tool tip strings in the resource file */
+    public static final String toolTipSuffix = "Tip";
+    /** name constant for selected icon names in the resource file */
+    public static final String selectedIconSuffix = "SelectedIcon";
+    /** indicator for menu separators */
+    public static final String menuSeparatorKey = "-";
+    /** dynamic storage for menu items */
+    private final Hashtable menuItems = new Hashtable();
+    /** dynamic storage for actions */
+    private final Hashtable commands = new Hashtable();
+    /** dynamic storage for menus */
+    private final Hashtable menus = new Hashtable();
+    public static final String IMAGE_EMPTY = "empty.gif";
+
+    /**
+     * construct a new DynamicResource.
+     */
+    public DynamicResource() {
+    }
+
+    /**
+     * add an action to this <code>DynamicResource</code>
+     *
+     * @param cmd  the internal identifier for the action
+     * @param action  the action to associate with actionCommand
+     */
+    public void addAction(final String cmd, final Action action) {
+        commands.put(cmd, action);
+    }
+
+    /**
+     * Create a menu bar.  This reads the
+     * definition of the menu from the associated resource file.
+     *
+     * @param resources  the TextResources to get the menu definition from
+     * @param name  name of the menu bar definition
+     *
+     * @return the created menu bar
+     */
+    public SHTMLMenuBar createMenubar(final TextResources resources, final String name) {
+        final SHTMLMenuBar mb = new SHTMLMenuBar();
+        final String[] menuKeys = Util.tokenize(Util.getResourceString(resources, name), " ");
+        for (int i = 0; i < menuKeys.length; i++) {
+            final JMenu m = createMenu(resources, menuKeys[i]);
+            if (m != null) {
+                mb.add(m);
+            }
+        }
+        return mb;
+    }
+
+    /**
+     * Create a menu for the app.  This reads the
+     * definition of the menu from the associated resource file.
+     *
+     * @param resources  the TextResources to get the menu definition from
+     * @param key  the key of the menu definition in the resource file
+     * @return the created menu
+     */
+    public JMenu createMenu(final TextResources resources, final String key) {
+        JMenu menu = null;
+        String def = Util.getResourceString(resources, key);
+        if (def == null) {
+            def = "";
+        }
+        final String[] itemKeys = Util.tokenize(def, " ");
+        menu = new JMenu(Util.getResourceString(resources, key + labelSuffix));
+        for (int i = 0; i < itemKeys.length; i++) {
+            if (itemKeys[i].equals(menuSeparatorKey)) {
+                menu.addSeparator();
+            }
+            else {
+                final JMenuItem mi = createMenuItem(resources, itemKeys[i]);
+                menu.add(mi);
+            }
+        }
+        menu.addMenuListener(new DynamicMenuListener());
+        /**
+         * store the menu in the menus hashtable for possible later use
+         */
+        menus.put(key, menu);
+        return menu;
+    }
+
+    /**
+     * Create a menu for the app.  This reads the
+     * definition of the menu from the associated resource file.
+     *
+     * @param resources  the TextResources to get the menu definition from
+     * @param key  the key of the menu definition in the resource file
+     * @return the created menu
+     */
+    public JPopupMenu createPopupMenu(final TextResources resources, final String key) {
+        JPopupMenu menu = null;
+        String def = Util.getResourceString(resources, key);
+        if (def == null) {
+            def = "";
+        }
+        final String[] itemKeys = Util.tokenize(def, " ");
+        menu = new JPopupMenu();
+        for (int i = 0; i < itemKeys.length; i++) {
+            if (itemKeys[i].equals(menuSeparatorKey)) {
+                menu.addSeparator();
+            }
+            else {
+                final JMenuItem mi = createMenuItem(resources, itemKeys[i]);
+                menu.add(mi);
+            }
+        }
+        return menu;
+    }
+
+    public JMenu getMenu(final String cmd) {
+        return (JMenu) menus.get(cmd);
+    }
+
+    /**
+     * create a menu item
+     *
+     * @param resources  the TextResources to get the item definition from
+     * @param cmd the action command to be associated
+     *      with the new menu item
+     * @return the created menu item
+     */
+    public JMenuItem createMenuItem(final TextResources resources, final String cmd) {
+        /**
+         * create a new menu item with the appropriate label from the
+         * resource file. This label later is set from the action this
+         * menu item is associated to (see below).
+         */
+        JMenuItem mi;
+        mi = new JMenuItem();
+        String astr = Util.getResourceString(resources, cmd + actionSuffix);
+        if (astr == null) {
+            astr = cmd;
+        }
+        mi.setActionCommand(astr);
+        /**
+         * connect action and menu item with appropriate listeners
+         */
+        final Action a = getAction(astr);
+        if (a != null) {
+            final Object aKey = a.getValue(AbstractAction.ACCELERATOR_KEY);
+            if (aKey != null) {
+                mi.setAccelerator((KeyStroke) aKey);
+            }
+            /**
+             * add Action 'a' as the listener to action events
+             * fired from this menu, i.e. execute action 'a' with
+             * menu item 'mi'
+             */
+            mi.addActionListener(a);
+            /**
+             * cause an instance of inner class ActionChangeListener
+             * to listen to property changes of Action 'a' and to apply
+             * changed properties of Action 'a' to menu item 'mi'
+             */
+            a.addPropertyChangeListener(createActionChangeListener(mi));
+            /**
+             * if the action has an image,
+             * associate it with the menu item
+             */
+            final Icon icon = (Icon) a.getValue(Action.SMALL_ICON);
+            if (icon != null) {
+                mi.setHorizontalTextPosition(JButton.RIGHT);
+                mi.setIcon(icon);
+            }
+            String name = (String) a.getValue(Action.NAME);
+            if(name == null)
+            	name = Util.getResourceString(resources, cmd + labelSuffix);
+			mi.setText(name);
+            /**
+             * initially set the enabled state of the menu item
+             * according to its action's enabled state
+             */
+            mi.setEnabled(a.isEnabled());
+        }
+        else {
+        	mi.setText(Util.getResourceString(resources, cmd + labelSuffix));
+            mi.setEnabled(false);
+        }
+        /**
+         * store the menu item in the menuItems hashtable for possible later use
+         */
+        menuItems.put(cmd, mi);
+        return mi;
+    }
+
+    /**
+     * get a string from the resources file
+     *
+     * @param resources  the TextResources to get the string from
+     * @param nm  the key of the string
+     * @return the string for the given key or null if not found
+     */
+    static public String getResourceString(final TextResources resources, final String key) {
+        try {
+            //System.out.println("getResourceString nm=" + nm);
+            if (resources != null) {
+                return resources.getString(key);
+            }
+            System.err.println("SimplyHTML : Warning : resources are null.");
+            new Throwable("Dummy").printStackTrace();
+            return key;
+        }
+        catch (final MissingResourceException mre) {
+            System.err.println("SimplyHTML : Warning : resource is missing: " + key);
+            return key;
+        }
+    }
+
+    /**
+     * listen to menu select events for proper updating of menu items
+     *
+     * whenever a menu is selected, its menu items are iterated and the
+     * update method of the item's action is called causing
+     * the menu item to reflect the correct enabled state.
+     *
+     * As each menu item is connected with a PropertyChangeListener
+     * listening to property changes on it'Saction, the menu item is
+     * updated by the PropertyChangeListener whenever the enabledState
+     * of the action changes.
+     */
+    private class DynamicMenuListener implements MenuListener {
+        public DynamicMenuListener() {
+        }
+
+        public void menuSelected(final MenuEvent e) {
+            final Component[] items = ((JMenu) e.getSource()).getMenuComponents();
+            Action action;
+            for (int i = 0; i < items.length; i++) {
+                if (items[i] instanceof JPopupMenu.Separator) {
+                }
+                else if (items[i] instanceof JMenuItem) {
+                    action = getAction(((JMenuItem) items[i]).getActionCommand());
+                    if (action instanceof SHTMLAction) {
+                        ((SHTMLAction) action).update();
+                    }
+                }
+            }
+        }
+
+        public void menuDeselected(final MenuEvent e) {
+        }
+
+        public void menuCanceled(final MenuEvent e) {
+        }
+    }
+
+    /**
+     * get an action from the commands table
+     *
+     * @param cmd  the name of the action the get
+     * @return the action found for the given name
+     */
+    public Action getAction(final String cmd) {
+        return (Action) commands.get(cmd);
+    }
+
+    /**
+     * get all actions registered in this <code>DynamicResource</code>
+     *
+     * @return all actions
+     */
+    public Enumeration getActions() {
+        return commands.elements();
+    }
+
+    /** create our PropertyChangeListener implementation */
+    private PropertyChangeListener createActionChangeListener(final AbstractButton b) {
+        return new ActionChangedListener(b);
+    }
+
+    /**
+     * associate a menu item to an action.
+     *
+     * When registering this
+     * action listener with an action, it gets informed by
+     * property changes of that particular action.
+     *
+     * By passing a menu item to the constructor of ActionChangedListener,
+     * an instance of ActionChangedListener 'remembers' the menu item
+     * its property are associated to.
+     */
+    private class ActionChangedListener implements PropertyChangeListener {
+        AbstractButton menuItem;
+
+        ActionChangedListener(final AbstractButton mi) {
+            super();
+            menuItem = mi;
+        }
+
+        public void propertyChange(final PropertyChangeEvent e) {
+            final String propertyName = e.getPropertyName();
+            if (e.getPropertyName().equals(Action.NAME)) {
+                final String text = (String) e.getNewValue();
+                menuItem.setText(text);
+            }
+            else if (propertyName.equals("enabled")) {
+                final Boolean enabledState = (Boolean) e.getNewValue();
+                menuItem.setEnabled(enabledState.booleanValue());
+            }
+        }
+    }
+
+    /**
+     * get the menu item that was created for the given
+     * command.
+     *
+     * @param cmd  name of the action.
+     * @return item created for the given command or null
+     *  if one wasn't created.
+     */
+    public JMenuItem getMenuItem(final String cmd) {
+        return (JMenuItem) menuItems.get(cmd);
+    }
+
+    /**
+     * get the icon for a given command.
+     *
+     * <p>If the resource bundle has a reference to an icon for the
+     * given commamd, an icon is created for the respective image resource.
+     * otherwise, null is returned.</p>
+     *
+     * @param resources  the TextResources to get the icon from
+     * @param cmd  the command an icon is requested for
+     *
+     * @return the icon for that command or null, if none is present
+     *        for this command
+     */
+    static public Icon getIconForCommand(final TextResources resources, final String cmd) {
+        return DynamicResource.getIconForName(resources, cmd + imageSuffix);
+    }
+
+    static public Icon getIconForName(final TextResources resources, final String name) {
+        Icon icon = null;
+        final URL url = DynamicResource.getResource(resources, name);
+        //System.out.println("getIconForName name=" + name + ", url=" + url);
+        if (url != null) {
+            icon = new ImageIcon(url);
+        }
+        return icon;
+    }
+
+    /**
+     * get the location of a resource.
+     *
+     * <p>Resources such as images are delivered with the application in
+     * the path containing the application's classes. The resources file
+     * coming with SimplyHTML has a key for every resource pointing to
+     * the subdirectory relative to the class path.</p>
+     *
+     * @param resources  the TextResources to get the resource from
+     * @param key  the key of the resource in the resource file
+     * @return the resource location as a URL
+     */
+    static public URL getResource(final TextResources resources, final String key) {
+        final String name = Util.getResourceString(resources, key);
+        if (name != null/* && !name.endsWith(IMAGE_EMPTY)*/) {
+            final URL url = DynamicResource.class.getResource(name);
+            return url;
+        }
+        return null;
+    }
+
+    /**
+     * Create a tool bar.  This reads the definition of a tool bar
+     * from the associated resource file.
+     *
+     * @param resources  the TextResources to get the tool bar definition from
+     * @param nm  the name of the tool bar definition in the resource file
+     *
+     * @return the created tool bar
+     */
+    public JToolBar createToolBar(final TextResources resources, final String nm) {
+        Action action;
+        AbstractButton newButton;
+        final java.awt.Dimension buttonSize = new java.awt.Dimension(24, 24);
+        new java.awt.Dimension(3, 20);
+        JSeparator separator;
+        final String[] itemKeys = Util.tokenize(Util.getResourceString(resources, nm), " ");
+        final JToolBar toolBar = new JToolBar();
+        toolBar.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
+        for (int i = 0; i < itemKeys.length; i++) {
+            /** special handling for separators */
+            if (itemKeys[i].equals(menuSeparatorKey)) {
+                separator = new JSeparator(JSeparator.VERTICAL);
+                toolBar.add(separator);
+            }
+            else {
+                action = getAction(itemKeys[i]);
+                newButton = toolBar.add(action);
+                newButton.setMinimumSize(buttonSize);
+                newButton.setPreferredSize(buttonSize);
+                newButton.setMaximumSize(buttonSize);
+                newButton.setFocusPainted(false);
+            }
+        }
+        return toolBar;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/EffectPanel.java b/src/com/lightdev/app/shtm/EffectPanel.java
new file mode 100644
index 0000000..e7ff5b5
--- /dev/null
+++ b/src/com/lightdev/app/shtm/EffectPanel.java
@@ -0,0 +1,143 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Font;
+import java.awt.GridLayout;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.UIManager;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.html.CSS;
+
+/**
+ * a panel to display and change line attributes
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class EffectPanel extends JPanel implements AttributeComponent {
+    /** a radio button for the underline attribute */
+    JRadioButton uLine;
+    /** a radio button for the strike through attribute */
+    JRadioButton strike;
+    /** a radio button if no line effect is set */
+    JRadioButton noLine;
+    private Object originalValue;
+    private int setValCount = 0;
+    String selection = Util.CSS_ATTRIBUTE_NONE;
+
+    public EffectPanel() {
+        super(new GridLayout(3, 1, 3, 3));
+        /** initialize the line effects button group */
+        noLine = new JRadioButton(Util.getResourceString("noLineLabel"));
+        uLine = new JRadioButton(Util.getResourceString("uLineLabel"));
+        strike = new JRadioButton(Util.getResourceString("strikeLabel"));
+        final ButtonGroup effectGroup = new ButtonGroup();
+        effectGroup.add(noLine);
+        effectGroup.add(uLine);
+        effectGroup.add(strike);
+        //JPanel linePanel = new JPanel(new GridLayout(3,1,3,3));
+        setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util.getResourceString("effectLabel")));
+        final Font font = UIManager.getFont("TextField.font");
+        uLine.setFont(font);
+        strike.setFont(font);
+        noLine.setFont(font);
+        add(noLine);
+        add(uLine);
+        add(strike);
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            return getAttributes();
+        }
+        else {
+            return getValue();
+        }
+    }
+
+    private AttributeSet getAttributes() {
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        selection = Util.CSS_ATTRIBUTE_NONE;
+        if (uLine.isSelected()) {
+            selection = Util.CSS_ATTRIBUTE_UNDERLINE;
+            StyleConstants.setUnderline(set, true);
+        }
+        else if (strike.isSelected()) {
+            selection = Util.CSS_ATTRIBUTE_LINE_THROUGH;
+            StyleConstants.setStrikeThrough(set, true);
+        }
+        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.TEXT_DECORATION, selection);
+        return set;
+    }
+
+    public AttributeSet getValue() {
+        final AttributeSet set = getAttributes();
+        if (((originalValue == null) && (!selection.equalsIgnoreCase(Util.CSS_ATTRIBUTE_NONE)))
+                || ((originalValue != null) && (!originalValue.toString().equalsIgnoreCase(selection)))) {
+            return set;
+        }
+        else {
+            return new SimpleAttributeSet();
+        }
+    }
+
+    public boolean setValue(final AttributeSet a) {
+        boolean success = false;
+        if (a.isDefined(CSS.Attribute.TEXT_DECORATION)) {
+            final String value = a.getAttribute(CSS.Attribute.TEXT_DECORATION).toString();
+            if (value.equalsIgnoreCase(Util.CSS_ATTRIBUTE_UNDERLINE)) {
+                uLine.setSelected(true);
+                if (++setValCount < 2) {
+                    originalValue = Util.CSS_ATTRIBUTE_UNDERLINE;
+                }
+                success = true;
+            }
+            else if (value.equalsIgnoreCase(Util.CSS_ATTRIBUTE_LINE_THROUGH)) {
+                strike.setSelected(true);
+                if (++setValCount < 2) {
+                    originalValue = Util.CSS_ATTRIBUTE_LINE_THROUGH;
+                }
+                success = true;
+            }
+            else {
+                noLine.setSelected(true);
+            }
+        }
+        else {
+            noLine.setSelected(true);
+        }
+        return success;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/FontDialog.java b/src/com/lightdev/app/shtm/FontDialog.java
new file mode 100644
index 0000000..d2a09d7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/FontDialog.java
@@ -0,0 +1,71 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Frame;
+
+import javax.swing.text.AttributeSet;
+
+/**
+ * Dialog to show and manipulate font attributes.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class FontDialog extends DialogShell {
+    /** the font panel to use in this dialog */
+    private final FontPanel fontPanel;
+
+    /**
+     * constructor
+     *
+     * @param parent  the main frame having the TextResources
+     * @param title  the title for this dialog
+     * @param a  the set of attributes to show and manipulate
+     */
+    public FontDialog(final Frame parent, final String title, final AttributeSet a) {
+        super(parent, title);
+        // construct font panel
+        fontPanel = new FontPanel(a, false);
+        // add font panel to content pane of DialogShell
+        final Container contentPane = super.getContentPane();
+        contentPane.add(fontPanel, BorderLayout.CENTER);
+        // cause optimal placement of all elements
+        pack();
+    }
+
+    /**
+     * get the set of attributes set in this dialog
+     *
+     * @return the attributes set in this dialog
+     */
+    public AttributeSet getAttributes() {
+        return fontPanel.getAttributes();
+    }
+}
diff --git a/src/com/lightdev/app/shtm/FontPanel.java b/src/com/lightdev/app/shtm/FontPanel.java
new file mode 100644
index 0000000..afe3188
--- /dev/null
+++ b/src/com/lightdev/app/shtm/FontPanel.java
@@ -0,0 +1,502 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GraphicsEnvironment;
+import java.awt.GridLayout;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+
+/**
+ * A panel for showing and manipulating font information.
+ *
+ * <p><code>FontPanel</code> shows and manipulates CSS attributes. To
+ * set it to HTML attributes, methods setAttributes and getAttributes
+ * have to be overridden.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class FontPanel extends JPanel implements TitledPickList.TitledPickListListener, ColorPanel.ColorPanelListener {
+    /** a text field to show a sample of the selected font attributes */
+    JTextField sample = new JTextField();
+    /** table for automatic font component value read/write */
+    private final Vector fontComponents = new Vector(0);
+
+    public FontPanel(final boolean pickBgColor) {
+        setLayout(new BorderLayout(5, 5));
+        /** create a label for previewing font selections */
+        sample.setText("");
+        sample.setEditable(false);
+        sample.setPreferredSize(new Dimension(200, 50));
+        sample.setHorizontalAlignment(SwingConstants.CENTER);
+        sample.setText(Util.getResourceString("previewText"));
+        final JPanel previewPanel = new JPanel(new BorderLayout());
+        previewPanel.add(sample, BorderLayout.CENTER);
+        previewPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("previewLabel")));
+        /**
+         * create a pick list for family filled with
+         * available font family names
+         */
+        final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        final FamilyPickList family = new FamilyPickList(ge.getAvailableFontFamilyNames(),
+            Util.getResourceString("familyLabel"));
+        family.addTitledPickListListener(this);
+        fontComponents.add(family);
+        /** create a pick list for font size */
+        final SizePickList size = new SizePickList(SHTMLPanelImpl.FONT_SIZES, Util.getResourceString("sizeLabel"));
+        size.addTitledPickListListener(this);
+        fontComponents.add(size);
+        /** wrap together family and size */
+        final JPanel familySizePanel = new JPanel(new BorderLayout(5, 5));
+        familySizePanel.add(family, BorderLayout.CENTER);
+        familySizePanel.add(size, BorderLayout.EAST);
+        /** create a panel to put font parts family, size and stlye in */
+        final JPanel fontPartsPanel = new JPanel(new BorderLayout(5, 5));
+        fontPartsPanel.add(familySizePanel, BorderLayout.CENTER);
+        final String[] fontStyles = new String[] { Util.getResourceString("plainName"),
+                Util.getResourceString("boldName"), Util.getResourceString("italicName"),
+                Util.getResourceString("boldItalicName") };
+        final StylePickList style = new StylePickList(fontStyles, Util.getResourceString("styleLabel"));
+        style.addTitledPickListListener(this);
+        fontPartsPanel.add(style, BorderLayout.EAST);
+        fontComponents.add(style);
+        /** create a panel for underline / line through */
+        final EffectPanel linePanel = new EffectPanel();
+        fontComponents.add(linePanel);
+        /** create a panel for color choices */
+        final JPanel colorPanel = new JPanel(new GridLayout(2, 1, 3, 3));
+        colorPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("colorLabel")));
+        final ColorPanel fCol = new ColorPanel(Util.getResourceString("foregroundLabel"), Color.black,
+            CSS.Attribute.COLOR);
+        fCol.addColorPanelListener(this);
+        fontComponents.add(fCol);
+        colorPanel.add(fCol);
+        sample.setForeground(Color.black);
+        if (pickBgColor) {
+            final ColorPanel bCol = new ColorPanel(Util.getResourceString("backgroundLabel"), Color.white,
+                CSS.Attribute.BACKGROUND_COLOR);
+            bCol.addColorPanelListener(this);
+            fontComponents.add(bCol);
+            colorPanel.add(bCol);
+            sample.setBackground(Color.white);
+        }
+        /** create a panel to combine line and color choices */
+        final JPanel eastPanel = new JPanel(new BorderLayout());
+        eastPanel.add(linePanel, BorderLayout.NORTH);
+        eastPanel.add(colorPanel, BorderLayout.SOUTH);
+        /** add all font controls to our font panel */
+        add(fontPartsPanel, BorderLayout.CENTER);
+        add(eastPanel, BorderLayout.EAST);
+        add(previewPanel, BorderLayout.SOUTH);
+        add(new JPanel(), BorderLayout.NORTH);
+        add(new JPanel(), BorderLayout.WEST);
+    }
+
+    /**
+     * construct a FontPanel and display a set of attributes
+     *
+     * @param frame  the main frame having the TextResources
+     * @param a  the set of attributes to display
+     */
+    public FontPanel(final AttributeSet a, final boolean pickBgColor) {
+        this(pickBgColor);
+        /** set the new FontPanel to display our set of attributes */
+        setAttributes(a);
+    }
+
+    /**
+     * handle ColorChangeEvents from one of our color panels
+     *
+     * @param e  the ColorPanelEvent to handle
+     */
+    public void colorChanged(final ColorPanel.ColorPanelEvent e) {
+        final ColorPanel source = (ColorPanel) e.getSource();
+        if (source.getAttributeKey() == CSS.Attribute.COLOR) {
+            sample.setForeground(source.getColor());
+        }
+        else if (source.getAttributeKey() == CSS.Attribute.BACKGROUND_COLOR) {
+            sample.setBackground(source.getColor());
+        }
+    }
+
+    /**
+     * set all components of this FontPanel to reflect a set of
+     * attributes.
+     *
+     * @param a  the set of attributes to show
+     */
+    public void setAttributes(final AttributeSet a) {
+        final Enumeration components = fontComponents.elements();
+        while (components.hasMoreElements()) {
+            ((AttributeComponent) components.nextElement()).setValue(a);
+        }
+    }
+
+    /**
+     * get the set of attributes resulting from the settings on
+     * this FontPanel.
+     *
+     * @return the set of attributes set in this FontPanel
+     */
+    public AttributeSet getAttributes() {
+        final SimpleAttributeSet attributes = new SimpleAttributeSet();
+        final Enumeration components = fontComponents.elements();
+        while (components.hasMoreElements()) {
+            attributes.addAttributes(((AttributeComponent) components.nextElement()).getValue());
+        }
+        return attributes;
+    }
+
+    public AttributeSet getAttributes(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            final SimpleAttributeSet attributes = new SimpleAttributeSet();
+            final Enumeration components = fontComponents.elements();
+            while (components.hasMoreElements()) {
+                attributes.addAttributes(((AttributeComponent) components.nextElement()).getValue(includeUnchanged));
+            }
+            return attributes;
+        }
+        else {
+            return getAttributes();
+        }
+    }
+
+    public void reset() {
+        Object c;
+        for (int i = 0; i < fontComponents.size(); i++) {
+            c = fontComponents.get(i);
+            if (c instanceof FamilyPickList) {
+                ((FamilyPickList) c).reset();
+            }
+            else if (c instanceof SizePickList) {
+                ((SizePickList) c).reset();
+            }
+            else if (c instanceof StylePickList) {
+                ((StylePickList) c).reset();
+            }
+        }
+    }
+
+    /**
+     * if another value was picked from a list, update the
+     * sample
+     */
+    public void valueChanged(final TitledPickList.TitledPickListEvent e) {
+        final Object source = e.getSource();
+        final Font saveFont = sample.getFont();
+        if (source instanceof FamilyPickList) {
+            sample.setFont(new Font(((FamilyPickList) source).getFamily(), saveFont.getStyle(), saveFont.getSize()));
+        }
+        else if (source instanceof SizePickList) {
+            sample.setFont(new Font(saveFont.getFamily(), saveFont.getStyle(), Integer
+                .parseInt((String) ((SizePickList) source).getSelection())));
+            /*adjustFontSize(Integer.parseInt((String) ((SizePickList) source).getSelection()))));*/
+        }
+        else if (source instanceof StylePickList) {
+            sample.setFont(new Font(saveFont.getFamily(), ((StylePickList) source).getFontStyle(), saveFont.getSize()));
+        }
+    }
+
+    /* TODO
+     * fix for bug id 4765271
+     * (see http://developer.java.sun.com/developer/bugParade/bugs/4765271.html)
+     */
+    /**
+     * extend <code>TitledPickList</code> with a way to set values
+     * special to font family values
+     */
+    class FamilyPickList extends TitledPickList implements AttributeComponent {
+        private int setValCount = 0;
+        private Object originalValue;
+
+        /**
+         * constructor
+         *
+         * @param options  the options to be selectable in this list
+         * @param titleText  the title for the pick list
+         */
+        FamilyPickList(final String[] options, final String titleText) {
+            super(options, titleText);
+        }
+
+        /**
+         * set the value of this <code>TitledPickList</code>
+         *
+         * @param a  the set of attributes possibly having a
+         *          font family attribute this pick list could display
+         *
+         * @return true, if the set of attributes had a font family attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            ignoreTextChanges = true;
+            final String newSelection = Util.styleSheet().getFont(a).getFamily();
+            setSelection(newSelection);
+            ignoreTextChanges = false;
+            if (++setValCount < 2) {
+                originalValue = newSelection;
+            }
+            return true;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            final Object value = getSelection();
+            if (includeUnchanged
+                    || ((originalValue == null) && (value != null))
+                    || ((originalValue != null) && (value != null) && (!originalValue.toString().equalsIgnoreCase(
+                        value.toString())))) {
+                Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_FAMILY, value.toString());
+                set.addAttribute(HTML.Attribute.FACE, value.toString());
+            }
+            return set;
+        }
+
+        public AttributeSet getValue() {
+            return getValue(false);
+        }
+
+        public String getFamily() {
+            return (String) getSelection();
+        }
+
+        public void reset() {
+            setValCount = 0;
+            originalValue = null;
+        }
+    }
+
+    /**
+     * extend <code>TitledPickList</code> with a way to set values
+     * special to font size values
+     */
+    class SizePickList extends TitledPickList implements AttributeComponent {
+        private int setValCount = 0;
+        private String originalValue;
+
+        /**
+         * constructor
+         *
+         * @param options  the options to be selectable in this list
+         * @param titleText  the title for the pick list
+         */
+        SizePickList(final String[] options, final String titleText) {
+            super(options, titleText);
+        }
+
+        /**
+         * set the value of this <code>TitledPickList</code>
+         *
+         * @param a  the set of attributes possibly having a
+         *          font size attribute this pick list could display
+         *
+         * @return true, if the set of attributes had a font size attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            ignoreTextChanges = true;
+            final int size = Util.styleSheet().getFont(a).getSize();
+            final String newSelection = Integer.toString(size);
+            setSelection(newSelection);
+            if (++setValCount < 2) {
+                originalValue = newSelection;
+            }
+            return true;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            final String value = (String) getSelection();
+            if ((includeUnchanged || (originalValue == null) && (value != null))
+                    || ((originalValue != null) && (!originalValue.equalsIgnoreCase(value)))) {
+                final String relativeSize = Integer.toString(getIndex() + 1);
+                set.addAttribute(HTML.Attribute.SIZE, relativeSize);
+                Util.styleSheet().addCSSAttributeFromHTML(set, CSS.Attribute.FONT_SIZE, relativeSize /*+ "pt"*/);
+            }
+            return set;
+        }
+
+        public AttributeSet getValue() {
+            return getValue(false);
+        }
+
+        public void reset() {
+            setValCount = 0;
+            originalValue = null;
+        }
+    }
+
+    /**
+     * extend <code>TitledPickList</code> with a way to set values
+     * special to font style values
+     */
+    class StylePickList extends TitledPickList implements AttributeComponent {
+        private int originalValue;
+        private int setValCount = 0;
+
+        /**
+         * constructor
+         *
+         * @param options  the options to be selectable in this list
+         * @param titleText  the title for the pick list
+         */
+        StylePickList(final String[] options, final String titleText) {
+            super(options, titleText);
+        }
+
+        /**
+         * set the value of this <code>TitledPickList</code>
+         *
+         * @param a  the set of attributes possibly having a
+         *          font style attribute this pick list could display
+         *
+         * @return true, if the set of attributes had a font style attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            ignoreTextChanges = true;
+            final boolean success = false;
+            int styleNo = 0;
+            String value;
+            if (a.isDefined(CSS.Attribute.FONT_WEIGHT)) {
+                value = a.getAttribute(CSS.Attribute.FONT_WEIGHT).toString();
+                if (value.equalsIgnoreCase(StyleConstants.Bold.toString())) {
+                    styleNo++;
+                }
+            }
+            if (a.isDefined(CSS.Attribute.FONT_STYLE)) {
+                value = a.getAttribute(CSS.Attribute.FONT_STYLE).toString();
+                if (value.equalsIgnoreCase(StyleConstants.Italic.toString())) {
+                    styleNo += 2;
+                }
+            }
+            setSelection(styleNo);
+            if (++setValCount < 2) {
+                originalValue = styleNo;
+            }
+            ignoreTextChanges = false;
+            return success;
+        }
+
+        public AttributeSet getValue() {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            final int styleNo = getIndex();
+            switch (styleNo) {
+                case 0:
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_WEIGHT, Util.CSS_ATTRIBUTE_NORMAL);
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE, Util.CSS_ATTRIBUTE_NORMAL);
+                    break;
+                case 1:
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_WEIGHT, StyleConstants.Bold.toString());
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE, Util.CSS_ATTRIBUTE_NORMAL);
+                    break;
+                case 2:
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_WEIGHT, Util.CSS_ATTRIBUTE_NORMAL);
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE, StyleConstants.Italic.toString());
+                    break;
+                case 3:
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_WEIGHT, StyleConstants.Bold.toString());
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE, StyleConstants.Italic.toString());
+                    break;
+            }
+            return set;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            if (includeUnchanged) {
+                final String value = Util.CSS_ATTRIBUTE_NORMAL;
+                final SimpleAttributeSet set = new SimpleAttributeSet();
+                final int styleNo = getIndex();
+                switch (styleNo) {
+                    case 0:
+                        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE, value);
+                        break;
+                    case 1:
+                        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_WEIGHT,
+                            StyleConstants.Bold.toString());
+                        break;
+                    case 2:
+                        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE,
+                            StyleConstants.Italic.toString());
+                        break;
+                    case 3:
+                        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_WEIGHT,
+                            StyleConstants.Bold.toString());
+                        Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE,
+                            StyleConstants.Italic.toString());
+                        break;
+                }
+                return set;
+            }
+            else {
+                return getValue();
+            }
+        }
+
+        public int getFontStyle() {
+            int fontStyle = 0;
+            switch (getIndex()) {
+                case 0:
+                    fontStyle = Font.PLAIN;
+                    break;
+                case 1:
+                    fontStyle = Font.BOLD;
+                    break;
+                case 2:
+                    fontStyle = Font.ITALIC;
+                    break;
+                case 3:
+                    fontStyle = Font.BOLD | Font.ITALIC;
+                    break;
+            }
+            return fontStyle;
+        }
+
+        public void reset() {
+            setValCount = 0;
+            originalValue = -2;
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/FrmMain.java b/src/com/lightdev/app/shtm/FrmMain.java
new file mode 100644
index 0000000..0a16c78
--- /dev/null
+++ b/src/com/lightdev/app/shtm/FrmMain.java
@@ -0,0 +1,118 @@
+/*
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Toolkit;
+import java.awt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.swing.JFrame;
+
+/**
+ * Main window of application SimplyHTML.
+ *
+ * <p>This class constructs the main panel and all of its GUI elements
+ * such as menus, etc.</p>
+ *
+ * <p>It defines a set of inner classes creating actions which can be
+ * connected to menus, buttons or instantiated individually.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Dimitri Polivaev
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ *
+ */
+class FrmMain extends JFrame {
+    public static final String APP_NAME = "SimplyHTML";
+    public static final String VERSION = "0.16.05";
+    /** static reference to this instance of class FrmMain */
+    private SHTMLPanelImpl mainPane;
+
+    private FrmMain() {
+        SHTMLPanelImpl.setTextResources(null);
+        setIconImage(Toolkit.getDefaultToolkit().createImage(
+            DynamicResource.getResource(SHTMLPanelImpl.getResources(), "appIcon")));
+        setTitle(APP_NAME);
+    }
+
+    private void start() {
+        SplashScreen.showInstance();
+        try {
+            EventQueue.invokeAndWait(new Runnable() {
+                public void run() {
+                    mainPane = new SHTMLPanelMultipleDocImpl();
+                    //                    mainPane = new SHTMLPanelSingleDocImpl();
+                    mainPane.setContentPanePreferredSize(new Dimension(1024, 500));
+                    getContentPane().add(mainPane);
+                    pack();
+                    final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+                    final Dimension frameSize = getSize();
+                    if (frameSize.height > screenSize.height) {
+                        frameSize.height = screenSize.height;
+                    }
+                    if (frameSize.width > screenSize.width) {
+                        frameSize.width = screenSize.width;
+                    }
+                    //Center the window
+                    setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
+                    setVisible(true); // show the window
+                    getSHTMLPanel().getMostRecentFocusOwner().requestFocus();
+                }
+            });
+        }
+        catch (final InterruptedException e) {
+            e.printStackTrace();
+        }
+        catch (final InvocationTargetException e) {
+            e.printStackTrace();
+        }
+        SplashScreen.hideInstance();
+    }
+
+    /**
+     * catch requests to close the application's main frame to
+     * ensure proper clean up before the application is
+     * actually terminated.
+     */
+    protected void processWindowEvent(final WindowEvent e) {
+        if (!(e.getID() == WindowEvent.WINDOW_CLOSING) || mainPane.close()) {
+            super.processWindowEvent(e);
+        }
+    }
+
+    protected SHTMLPanel getSHTMLPanel() {
+        return mainPane;
+    }
+
+    static void run() {
+        final FrmMain frmMain = new FrmMain();
+        frmMain.start();
+    }
+}
diff --git a/src/com/lightdev/app/shtm/HTMLText.java b/src/com/lightdev/app/shtm/HTMLText.java
new file mode 100644
index 0000000..af45405
--- /dev/null
+++ b/src/com/lightdev/app/shtm/HTMLText.java
@@ -0,0 +1,319 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Vector;
+
+import javax.swing.text.AbstractDocument;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.ElementIterator;
+import javax.swing.text.html.HTMLDocument;
+
+/**
+ * A class to represent a portion of HTML text.
+ *
+ * <p>In stage 9 copy and paste have been refined to correct bugs that
+ * occurred when cut and paste was happening in nested paragraph elements</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class HTMLText {
+    /** the HTML representation of the text */
+    private String htmlText;
+    /** the plain text representation of the text */
+    private String plainText;
+    /** holds the copied plain text chunks */
+    private final Vector clipText = new Vector(0);
+    /** holds the copied character attributes mapping to clipText */
+    private final Vector clipAttr = new Vector(0);
+    /**
+     * indicates whether or not the html represented by this
+     * <code>HTMLText</code> instance contains more than one paragraph
+     */
+    //private boolean multiPara = false;
+    private boolean stringRepresentation = false;
+
+    /**
+     * construct a new empty <code>HTMLText</code> object
+     */
+    public HTMLText() {
+    }
+
+    public HTMLText(final String htmlText, final String plainText) {
+        this.htmlText = htmlText;
+        this.plainText = plainText;
+        stringRepresentation = true;
+    }
+
+    /**
+     * copy an HTML string representation of a content portion from the
+     * given editor pane.
+     *
+     * @param  src  the <code>SHTMLEditorPane</code> to copy from
+     * @param  start  the position to start copying at
+     * @param  length  the length of the content portion to copy
+     *
+     * @return an HTML string representation of the copied portion of content
+     *
+     * @see com.lightdev.app.shtm.SHTMLEditorPane
+     */
+    public void copyHTML(final SHTMLEditorPane src, final int start, final int length) throws BadLocationException,
+            IOException {
+        final HTMLDocument doc = (HTMLDocument) src.getDocument();
+        if (doc.getParagraphElement(start).equals(doc.getParagraphElement(start + length))) {
+            stringRepresentation = false;
+            clearStyledText();
+            copyStyledText(src);
+        }
+        else {
+            stringRepresentation = true;
+            final StringWriter sw = new StringWriter();
+            final SHTMLWriter w = new SHTMLWriter(sw, doc, start, length);
+            final Element first = doc.getParagraphElement(start);
+            final Element last = doc.getCharacterElement(start + length);
+            w.write(first, last);
+            htmlText = sw.getBuffer().toString();
+            plainText = doc.getText(start, length);
+        }
+    }
+
+    /**
+     * insert this <code>HTMLText<code> into a <code>Document</code>.
+     *
+     * @param  document  the document to insert into
+     * @param  position  the text position to insert at
+     */
+    public void pasteHTML(final Document document, int position) throws BadLocationException, IOException {
+        /**
+         * if only text within one paragraph is to be inserted,
+         * iterate over copied text chunks and insert each
+         * chunk with its own set of copied attributes. Else
+         * simply read copied HTML code back in.
+         */
+        if (!stringRepresentation) {
+            final int nrTextChunks = getClipTextSize();
+            String text;
+            for (int i = 0; i < nrTextChunks; i++) {
+                text = getCharactersAt(i);
+                document.insertString(position, text, getCharacterAttributes(i));
+                position += text.length();
+            }
+        }
+    }
+
+    /**
+     * Determines the HTML string resulting from pasting the given HTML string at the given
+     * position within the given paragraph element.
+     *
+     * @param doc  the document to insert to
+     * @param characterElement  the character element to split
+     * @param paragraphElement  the paragraph element to split
+     * @param targetPosition  the text position inside the document where to split
+     * @param pastedHtml  the html text to insert at pos
+     */
+    public String splitPaste(final SHTMLDocument doc, final Element characterElement, final Element paragraphElement,
+                             final int targetPosition, final String pastedHtml, final boolean pastedHTMLHasParagraphTags) {
+        // A model for this method: SHTMLEditorPane.InsertLineBreakAction.
+        final StringWriter sw = new StringWriter();
+        final SHTMLWriter w = new SHTMLWriter(sw, doc);
+        String paragraphElementAdjustedName = paragraphElement.getName();
+        final boolean impliedParagraph = paragraphElementAdjustedName.equalsIgnoreCase("p-implied");
+        if (impliedParagraph) {
+            paragraphElementAdjustedName = "p";
+        }
+        try {
+            final int count = paragraphElement.getElementCount();
+            if (!impliedParagraph || pastedHTMLHasParagraphTags) {
+                w.writeStartTag(paragraphElementAdjustedName, paragraphElement.getAttributes());
+            }
+            for (int elementIdx = 0; elementIdx < count; elementIdx++) {
+                final Element element = paragraphElement.getElement(elementIdx);
+                if (element.equals(characterElement)) {
+                    // Why the following?
+                    //if(elementIdx > 0) 
+                    //  w.writeStartTag(paragraphElementAdjustedName, paragraphElement.getAttributes());
+                    //Write first part of the splitted text.
+                    final SHTMLWriter htmlStartWriter = new SHTMLWriter(sw, doc, element.getStartOffset(),
+                        targetPosition - element.getStartOffset());
+                    htmlStartWriter.write(element);
+                    if (pastedHTMLHasParagraphTags) {
+                        w.writeEndTag(paragraphElementAdjustedName);
+                    }
+                    //Write the pasted text.
+                    sw.write(pastedHtml);
+                    //Write the second part of the splited text.
+                    if (pastedHTMLHasParagraphTags) {
+                        w.writeStartTag(paragraphElementAdjustedName, paragraphElement.getAttributes());
+                    }
+                    final SHTMLWriter htmlEndWriter = new SHTMLWriter(sw, doc, targetPosition, element.getEndOffset()
+                            - targetPosition);
+                    htmlEndWriter.write(element);
+                    // Why the following?
+                    //if(elementIdx > 0) 
+                    //  w.writeEndTag(paragraphElementAdjustedName);
+                }
+                else {
+                    w.write(element);
+                }
+            }
+            if (!impliedParagraph || pastedHTMLHasParagraphTags) {
+                w.writeEndTag(paragraphElementAdjustedName);
+            }
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+        }
+        return sw.getBuffer().toString();
+    }
+
+    /**
+     * Copy the selected portion of an SHTMLEditorPane as styled text,
+     * i.e. chunks of plain text strings with an AttributeSet associated
+     * to each of them.
+     *
+     * @param src  the SHTMLEditorPane to copy from
+     */
+    private void copyStyledText(final SHTMLEditorPane src) throws BadLocationException {
+        final Document doc = src.getDocument();
+        final int selStart = src.getSelectionStart();
+        final int selEnd = src.getSelectionEnd();
+        int eStart;
+        int eEnd;
+        final ElementIterator eli = new ElementIterator(doc);
+        Element elem = eli.first();
+        while (elem != null) {
+            eStart = elem.getStartOffset();
+            eEnd = elem.getEndOffset();
+            if (elem.getName().equalsIgnoreCase(AbstractDocument.ContentElementName)) {
+                if ((eEnd >= selStart) && (eStart <= selEnd)) {
+                    clipAttr.addElement(elem.getAttributes());
+                    if (eStart < selStart) {
+                        if (eEnd > selEnd) { // both ends of elem outside selection
+                            clipText.addElement(src.getText(selStart, selEnd - selStart));
+                        }
+                        else { // only first part of elem outside selection
+                            clipText.addElement(src.getText(selStart, eEnd - selStart));
+                        }
+                    }
+                    else if (eEnd > selEnd) { // only last part of elem outside selection
+                        clipText.addElement(src.getText(eStart, selEnd - eStart));
+                    }
+                    else { // whole element inside selection
+                        clipText.addElement(src.getText(eStart, eEnd - eStart));
+                    }
+                }
+            }
+            elem = eli.next();
+        }
+    }
+
+    /** Gets the number of text chunks in this <code>StyledText</code> object. */
+    private int getClipTextSize() {
+        return clipText.size();
+    }
+
+    /**
+     * get the attributes of a certain chunk of styled text
+     *
+     * @param chunkPos - the number of the chunk to get the attributes for
+     * @return the attributes for respective character position
+     */
+    private AttributeSet getCharacterAttributes(final int chunkNo) {
+        return (AttributeSet) clipAttr.elementAt(chunkNo);
+    }
+
+    /**
+     * get the characters of a certain chunk of styled text
+     *
+     * @param chunkNo - the number of the chunk to get the characters for
+     * @return the characters for respective chunk as String
+     */
+    private String getCharactersAt(final int chunkNo) {
+        return (String) clipText.elementAt(chunkNo);
+    }
+
+    /** clear all styled text contents of this <code>HTMLText</code> object */
+    private void clearStyledText() {
+        clipText.clear();
+        clipAttr.clear();
+    }
+
+    /**
+     * get a String containing all chunks of text contained in this object
+     *
+     * @return string of all chunks in this object
+     */
+    public String toString() {
+        final StringBuffer text = new StringBuffer();
+        if (stringRepresentation) {
+            text.append(plainText);
+        }
+        else {
+            int i;
+            for (i = 0; i < clipText.size(); i++) {
+                text.append((String) clipText.elementAt(i));
+            }
+        }
+        return text.toString();
+    }
+
+    /** (See also isParagraphTag.) */
+    public static boolean containsParagraphTags(final String htmlText) {
+        //An simplistic heuristic. Does not handle tags in comments, for instance.
+        return htmlText
+            .matches("(?ims).*<(blockquote|dir|div|dl|dt|frameset|h1|h2|h3|h4|h5|h6|hr|li|menu|ol|p|pre|table|td|th|tr|ul).*?>.*");
+    }
+
+    /** Determines whether the text has a table with exactly one cell and one row. */
+    public boolean isOneCellInOneRow() {
+        //return false;
+        if (htmlText.matches("(?ims).*</td>.*<td.*")) {
+            return false;
+        }
+        if (htmlText.matches("(?ims).*</tr>.*<tr.*")) {
+            return false;
+        }
+        if (!htmlText.matches("(?ims).*<table.*")) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean usesStringRepresenation() {
+        return stringRepresentation;
+    }
+
+    public String getHTMLText() {
+        return htmlText;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/HTMLTextSelection.java b/src/com/lightdev/app/shtm/HTMLTextSelection.java
new file mode 100644
index 0000000..b050d78
--- /dev/null
+++ b/src/com/lightdev/app/shtm/HTMLTextSelection.java
@@ -0,0 +1,114 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+
+/**
+ * A transferable for HTML text.
+ *
+ * <p>It can be used in drag and drop operations or in copy and paste
+ * operations. Additional to <code>HTMLText</code> it supports the
+ * <code>String</code> data flavor.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ *
+ * @see java.awt.datatransfer.DataFlavor.stringFlavor
+ * @see java.awt.datatransfer.DataFlavor.plainTextFlavor
+ * @see com.lightdev.app.shtm.HTMLText
+ */
+class HTMLTextSelection implements Transferable {
+    /** index of HTML text data flavor */
+    private static final int HTML_TEXT = 0;
+    /** the data to transfer */
+    private final HTMLText data;
+    /** the data flavor of this transferable */
+    private static final DataFlavor[] flavors = { new DataFlavor(com.lightdev.app.shtm.HTMLText.class, "HTMLText") };
+
+    /**
+     * construct a <code>HTMLTextSelection</code> with a chunk
+     * of styled text.
+     *
+     * @param data - a HTMLText object
+     *
+     * @see com.lightdev.app.shtm.HTMLText
+     */
+    public HTMLTextSelection(final HTMLText data) {
+        this.data = data;
+    }
+
+    /* ---- start of Transferable implementation ----------------------------*/
+    /**
+     * Returns an array of DataFlavor objects indicating the flavors the data
+     * can be provided in.  The array should be ordered according to preference
+     * for providing the data (from most richly descriptive to least descriptive).
+     * @return an array of data flavors in which this data can be transferred
+     */
+    public DataFlavor[] getTransferDataFlavors() {
+        return (DataFlavor[]) flavors.clone();
+    }
+
+    /**
+     * Returns whether or not the specified data flavor is supported for
+     * this object.
+     * @param flavor the requested flavor for the data
+     * @return boolean indicating wjether or not the data flavor is supported
+     */
+    public boolean isDataFlavorSupported(final DataFlavor flavor) {
+        for (int i = 0; i < flavors.length; i++) {
+            if (flavors[i].equals(flavor)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns an object which represents the data to be transferred.  The class
+     * of the object returned is defined by the representation class of the flavor.
+     *
+     * @param flavor the requested flavor for the data
+     * @see DataFlavor#getRepresentationClass
+     * @exception IOException                if the data is no longer available
+     *              in the requested flavor.
+     * @exception UnsupportedFlavorException if the requested data flavor is
+     *              not supported.
+     */
+    public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+        if (flavor.equals(flavors[HTML_TEXT])) {
+            return data;
+        }
+        else {
+            throw new UnsupportedFlavorException(flavor);
+        }
+    }
+    /* ----------- end of Transferable implementation ------------------- */
+}
diff --git a/src/com/lightdev/app/shtm/ImageDialog.java b/src/com/lightdev/app/shtm/ImageDialog.java
new file mode 100644
index 0000000..fba6c20
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ImageDialog.java
@@ -0,0 +1,630 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.StringWriter;
+import java.util.Vector;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLDocument;
+
+import com.sun.demo.ExampleFileFilter;
+
+/**
+ * A dialog providing an image repository and a way to edit display options
+ * for images from the repository.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ *
+ */
+class ImageDialog extends DialogShell implements ActionListener, ListSelectionListener, ChangeListener {
+    /** directory this ImageDialog maintains */
+    private File imgDir;
+    /** KeyListener for watching changes in the scale text field */
+    private final KeyHandler keyHandler = new KeyHandler();
+    /** FocusListener for watching changes in the scale text field */
+    private final FocusHandler focusHandler = new FocusHandler();
+    private final SimpleAttributeSet originalAttributes = new SimpleAttributeSet();
+    /**
+     * indicates whether or not changes in a SizeSelectorPanel are
+     * to be processed. Usually, changes caused by a method of this
+     * class are to be ignored
+     */
+    private boolean ignoreChangeEvents = false;
+    /** list with images in this image repository */
+    private JList imgFileList;
+    /** button to add an image file to the repository */
+    private JButton addImgBtn;
+    /** button to delete an image file from the repository */
+    private JButton delImgBtn;
+    /** text field for manipulating the scale of an image */
+    private JTextField scale;
+    /** component to manipulate the image width */
+    private SizeSelectorPanel imgWidth;
+    /** component to manipulate the image height */
+    private SizeSelectorPanel imgHeight;
+    /** component to display the original width of an image */
+    private JLabel oWidth;
+    /** component to display the original height of an image */
+    private JLabel oHeight;
+    /** component to preview an image */
+    private ImagePreview preview;
+    /** component to scroll an image inside the preview */
+    private JScrollPane scPrev;
+    /**
+     * contains all components having attributes for the image represented
+     * in this <code>ImageDialog</code>
+     */
+    private final Vector attributeComponents = new Vector();
+    /** the help id for this dialog */
+    private static final String helpTopicId = "item166";
+    /** the document the image came from, if any */
+    private SHTMLDocument doc;
+
+    /**
+     * construct a new ImageDialog
+     *
+     * @param parent  the parent frame of this ImageDialog
+     * @param title  the title of this ImageDialog
+     * @param imgDir  the directory of the image repository
+     */
+    public ImageDialog(final Dialog parent, final String title, final File imgDir) {
+        super(parent, title, helpTopicId);
+        initDialog(title, imgDir);
+    }
+
+    /**
+     * construct a new ImageDialog
+     *
+     * @param parent  the parent frame of this ImageDialog
+     * @param title  the title of this ImageDialog
+     * @param imgDir  the directory of the image repository
+     */
+    public ImageDialog(final Frame parent, final String title, final File imgDir) {
+        super(parent, title, helpTopicId);
+        initDialog(title, imgDir);
+    }
+
+    public ImageDialog(final Frame parent, final String title, final File imgDir, final SHTMLDocument sourceDoc) {
+        super(parent, title, helpTopicId);
+        doc = sourceDoc;
+        initDialog(title, imgDir);
+    }
+
+    /**
+     * build the dialog contents after construction
+     *
+     * @param title  the title of this ImageDialog
+     * @param imgDir  the directory of the image repository
+     */
+    private void initDialog(final String title, final File imgDir) {
+        //System.out.println("ImageDialog.initDialog imgDir=" + imgDir.getAbsolutePath());
+        this.imgDir = imgDir;
+        Dimension dim;
+        // create an image directory panel
+        final JPanel dirPanel = new JPanel(new BorderLayout());
+        dirPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("imgDirPanelTitle")));
+        // create a list to disply image files in
+        imgFileList = new JList();
+        dim = new Dimension(100, 100);
+        imgFileList.setMinimumSize(dim);
+        imgFileList.setPreferredSize(dim);
+        imgFileList.addListSelectionListener(this);
+        updateFileList();
+        // create a panel with action buttons for image files
+        final JPanel dirBtnPanel = new JPanel();
+        // create image directory action buttons
+        addImgBtn = new JButton(Util.getResourceString("addImgBtnTitle"));
+        addImgBtn.addActionListener(this);
+        delImgBtn = new JButton(Util.getResourceString("delImgBtnTitle"));
+        delImgBtn.addActionListener(this);
+        // add action buttons to button panel
+        dirBtnPanel.add(addImgBtn);
+        dirBtnPanel.add(delImgBtn);
+        // add components to image directory panel
+        dirPanel.add(imgFileList, BorderLayout.CENTER);
+        dirPanel.add(dirBtnPanel, BorderLayout.SOUTH);
+        // create an image preview panel
+        final JPanel previewPanel = new JPanel(new BorderLayout());
+        previewPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("imgPreviewPanelTitle")));
+        // add a new ImagePreview object to the preview panel
+        preview = new ImagePreview();
+        dim = new Dimension(250, 250);
+        preview.setMinimumSize(dim);
+        preview.setPreferredSize(dim);
+        scPrev = new JScrollPane(preview);
+        previewPanel.add(scPrev, BorderLayout.CENTER);
+        // layout and constraints to use later on
+        final GridBagLayout g = new GridBagLayout();
+        final GridBagConstraints c = new GridBagConstraints();
+        // create an image properties panel
+        final JPanel eastPanel = new JPanel(new BorderLayout());
+        final JPanel propertiesPanel = new JPanel(g);
+        eastPanel.add(propertiesPanel, BorderLayout.NORTH);
+        eastPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("imgPropertiesPanelTitle")));
+        // add scale component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("imgScaleLabel")), g, c, 0, 0,
+            GridBagConstraints.EAST);
+        scale = new JTextField();
+        scale.addKeyListener(keyHandler);
+        scale.addFocusListener(focusHandler);
+        dim = new Dimension(50, 20);
+        scale.setMinimumSize(dim);
+        scale.setPreferredSize(dim);
+        final JPanel helperPanel = new JPanel();
+        helperPanel.add(scale);
+        helperPanel.add(new JLabel(SizeSelectorPanel.UNIT_PERCENT, SwingConstants.LEFT));
+        Util.addGridBagComponent(propertiesPanel, helperPanel, g, c, 1, 0, GridBagConstraints.WEST);
+        // add width component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("imgWidthLabel")), g, c, 0, 1,
+            GridBagConstraints.EAST);
+        imgWidth = new SizeSelectorPanel(HTML.Attribute.WIDTH, null, false, SizeSelectorPanel.TYPE_LABEL);
+        attributeComponents.addElement(imgWidth);
+        imgWidth.getValueSelector().addChangeListener(this);
+        Util.addGridBagComponent(propertiesPanel, imgWidth, g, c, 1, 1, GridBagConstraints.WEST);
+        // add height component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("imgHeightLabel")), g, c, 0, 2,
+            GridBagConstraints.EAST);
+        imgHeight = new SizeSelectorPanel(HTML.Attribute.HEIGHT, null, false, SizeSelectorPanel.TYPE_LABEL);
+        attributeComponents.addElement(imgHeight);
+        imgHeight.getValueSelector().addChangeListener(this);
+        Util.addGridBagComponent(propertiesPanel, imgHeight, g, c, 1, 2, GridBagConstraints.WEST);
+        // add hspace component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("imgHSpaceLabel")), g, c, 0, 3,
+            GridBagConstraints.EAST);
+        final SizeSelectorPanel hSpace = new SizeSelectorPanel(HTML.Attribute.HSPACE, null, false,
+            SizeSelectorPanel.TYPE_LABEL);
+        attributeComponents.addElement(hSpace);
+        Util.addGridBagComponent(propertiesPanel, hSpace, g, c, 1, 3, GridBagConstraints.WEST);
+        // add vspace component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("imgVSpaceLabel")), g, c, 0, 4,
+            GridBagConstraints.EAST);
+        final SizeSelectorPanel vSpace = new SizeSelectorPanel(HTML.Attribute.VSPACE, null, false,
+            SizeSelectorPanel.TYPE_LABEL);
+        attributeComponents.addElement(vSpace);
+        Util.addGridBagComponent(propertiesPanel, vSpace, g, c, 1, 4, GridBagConstraints.WEST);
+        // add alignment component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("imgAlignLabel")), g, c, 0, 5,
+            GridBagConstraints.EAST);
+        final String[] items = new String[] { Util.getResourceString("imgAlignTop"),
+                Util.getResourceString("imgAlignMiddle"), Util.getResourceString("imgAlignBottom"),
+                Util.getResourceString("imgAlignLeft"), Util.getResourceString("imgAlignCenter"),
+                Util.getResourceString("imgAlignRight") };
+        final String[] names = new String[] { "top", "middle", "bottom", "left", "center", "right" };
+        final AttributeComboBox imgAlign = new AttributeComboBox(items, names, null, HTML.Attribute.ALIGN);
+        attributeComponents.addElement(imgAlign);
+        Util.addGridBagComponent(propertiesPanel, imgAlign, g, c, 1, 5, GridBagConstraints.WEST);
+        // add original width component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("oWidthLabel")), g, c, 0, 6,
+            GridBagConstraints.EAST);
+        oWidth = new JLabel("");
+        Util.addGridBagComponent(propertiesPanel, oWidth, g, c, 1, 6, GridBagConstraints.WEST);
+        // add original height component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("oHeightLabel")), g, c, 0, 7,
+            GridBagConstraints.EAST);
+        oHeight = new JLabel("");
+        Util.addGridBagComponent(propertiesPanel, oHeight, g, c, 1, 7, GridBagConstraints.WEST);
+        // add border component
+        Util.addGridBagComponent(propertiesPanel, new JLabel(Util.getResourceString("imgBorderLabel")), g, c, 0, 8,
+            GridBagConstraints.EAST);
+        final SizeSelectorPanel imgBorder = new SizeSelectorPanel(HTML.Attribute.BORDER, null, false,
+            SizeSelectorPanel.TYPE_LABEL);
+        attributeComponents.addElement(imgBorder);
+        Util.addGridBagComponent(propertiesPanel, imgBorder, g, c, 1, 8, GridBagConstraints.WEST);
+        // add to content pane of DialogShell
+        final Container contentPane = super.getContentPane();
+        contentPane.add(dirPanel, BorderLayout.WEST);
+        contentPane.add(previewPanel, BorderLayout.CENTER);
+        contentPane.add(eastPanel, BorderLayout.EAST);
+        // cause optimal placement of all elements
+        pack();
+        scPrev.addComponentListener(new ResizeListener());
+    }
+
+    public Integer getImgWidth() {
+        return imgWidth.getIntValue();
+    }
+
+    public Integer getImgHeight() {
+        return imgHeight.getIntValue();
+    }
+
+    /**
+     * set dialog content from a given set of image attributes
+     *
+     * @param a  the set of attributes to set dialog contents from
+     */
+    public void setImageAttributes(final AttributeSet a) {
+        //System.out.println("ImageDialog.setImageAttributes");
+        ignoreChangeEvents = true;
+        originalAttributes.addAttributes(a);
+        if (a.isDefined(HTML.Attribute.SRC)) {
+            File imgFile = null;
+            if (doc != null) {
+                imgFile = new File(Util.resolveRelativePath(a.getAttribute(HTML.Attribute.SRC).toString(), doc
+                    .getBase().getFile()));
+            }
+            else {
+                imgFile = new File(a.getAttribute(HTML.Attribute.SRC).toString());
+            }
+            //System.out.println("ImageDialog.setImageAttribute imgFile=" + imgFile.getAbsolutePath());
+            imgFileList.setSelectedValue(imgFile.getName().toLowerCase(), true);
+        }
+        for (int i = 0; i < attributeComponents.size(); i++) {
+            ((AttributeComponent) attributeComponents.get(i)).setValue(a);
+        }
+        if (a.isDefined(HTML.Attribute.WIDTH)) {
+            preview.setPreviewWidth(Integer.parseInt(a.getAttribute(HTML.Attribute.WIDTH).toString()));
+        }
+        if (a.isDefined(HTML.Attribute.HEIGHT)) {
+            preview.setPreviewHeight(Integer.parseInt(a.getAttribute(HTML.Attribute.HEIGHT).toString()));
+        }
+        final int scalePct = preview.getScale();
+        scale.setText(Integer.toString(scalePct));
+        ignoreChangeEvents = false;
+    }
+
+    public void setImage(final String fName, final String w, final String h) {
+        //System.out.println("ImageDialog.setImage fName=" + fName);
+        imgFileList.setSelectedValue(new File(fName).getName(), true);
+        preview.setImage(new ImageIcon(fName));
+        try {
+            if (w != null && w.length() > 0) {
+                preview.setPreviewWidth(Integer.parseInt(w));
+            }
+            if (h != null && h.length() > 0) {
+                preview.setPreviewHeight(Integer.parseInt(h));
+            }
+        }
+        catch (final Exception e) {
+            Util.errMsg(this, null, e);
+        }
+    }
+
+    /**
+     * get the HTML representing the image selected in this
+     * <code>ImageDialog</code>
+     */
+    public String getImageHTML() {
+        final SimpleAttributeSet set = new SimpleAttributeSet(originalAttributes);
+        final StringWriter sw = new StringWriter();
+        final SHTMLWriter w = new SHTMLWriter(sw, doc == null ? new HTMLDocument() : doc);
+        for (int i = 0; i < attributeComponents.size(); i++) {
+            set.addAttributes(((AttributeComponent) attributeComponents.get(i)).getValue());
+        }
+        set.addAttribute(HTML.Attribute.SRC, getImageSrc());
+        try {
+            w.writeStartTag(HTML.Tag.IMG.toString(), set);
+        }
+        catch (final Exception e) {
+            Util.errMsg(this, e.getMessage(), e);
+        }
+        return sw.getBuffer().toString();
+    }
+
+    /**
+     * get the value for the SRC attribute of an image tag
+     *
+     * @return the value of the SRC attribute of an image tag
+     */
+    public String getImageSrc() {
+        final StringBuffer buf = new StringBuffer();
+        final Object value = imgFileList.getSelectedValue();
+        if (value != null) {
+            buf.append(SHTMLPanelImpl.IMAGE_DIR);
+            buf.append(Util.URL_SEPARATOR);
+            buf.append(value.toString());
+        }
+        return buf.toString();
+    }
+
+    /**
+     * handle the event when the user pressed the 'Add...' button
+     * to add a new image to the repository
+     */
+    private void handleAddImage() {
+        try {
+            final JFileChooser chooser = new JFileChooser();
+            chooser.setMultiSelectionEnabled(true);
+            final ExampleFileFilter filter = new ExampleFileFilter();
+            filter.addExtension("gif");
+            filter.addExtension("jpg");
+            filter.addExtension("jpeg");
+            filter.setDescription(Util.getResourceString("imageFileDesc"));
+            chooser.setFileFilter(filter);
+            if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
+                final File[] sFiles = chooser.getSelectedFiles();
+                if (!imgDir.exists()) {
+                    imgDir.mkdirs();
+                }
+                final String imgDirName = imgDir.getAbsolutePath();
+                for (int i = 0; i < sFiles.length; i++) {
+                    //System.out.println("file selected: " + sFiles[i] + " new name= " + imgDirName + File.separator + sFiles[i].getName());
+                    Util.copyFile(sFiles[i], new File(imgDirName + File.separator + sFiles[i].getName()));
+                    updateFileList();
+                }
+            }
+        }
+        catch (final Exception e) {
+            Util.errMsg(this, e.getMessage(), e);
+        }
+    }
+
+    /**
+     * handle the event occurring when the user pressed the 'Delete' button
+     * to remove an image from the repository
+     */
+    private void handleDeleteImage() {
+        final String fName = imgFileList.getSelectedValue().toString();
+        if (Util.msg(JOptionPane.YES_NO_OPTION, "confirmDelete", "deleteFileQuery", fName, "\r\n")) {
+            final File delFile = new File(imgDir.getAbsolutePath() + File.separator + fName);
+            delFile.delete();
+            updateFileList();
+        }
+    }
+
+    /**
+     * display all files found in the image directory
+     */
+    private void updateFileList() {
+        if (imgDir != null && imgFileList != null) {
+            final String[] files = imgDir.list();
+            if (files != null && files.length > 0) {
+                for (int i = 0; i < files.length; i++) {
+                    files[i] = files[i].toLowerCase();
+                }
+                imgFileList.setListData(files);
+            }
+        }
+    }
+
+    /**
+     * update all image property displays to the current setting
+     */
+    private void updateControls() {
+        ignoreChangeEvents = true;
+        final int scalePct = preview.getScale();
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        oWidth.setText(Integer.toString(preview.getOriginalWidth()));
+        oHeight.setText(Integer.toString(preview.getOriginalHeight()));
+        //System.out.println("updateControls origW=" + preview.getOriginalWidth());
+        //System.out.println("updateControls add WIDTH attr as " + Integer.toString(
+        //            preview.getOriginalWidth() * scalePct / 100) + SizeSelectorPanel.UNIT_PT);
+        set.addAttribute(HTML.Attribute.WIDTH, Integer.toString(preview.getOriginalWidth() * scalePct / 100)
+                + SizeSelectorPanel.UNIT_PT);
+        set.addAttribute(HTML.Attribute.HEIGHT, Integer.toString(preview.getOriginalHeight() * scalePct / 100)
+                + SizeSelectorPanel.UNIT_PT);
+        imgWidth.setValue(set);
+        imgHeight.setValue(set);
+        scale.setText(Integer.toString(scalePct));
+        ignoreChangeEvents = false;
+    }
+
+    /**
+     * apply a scale set by the user through respective text field and
+     * update all related image property displays
+     */
+    private void applyPreviewScale() {
+        //System.out.println("applyPreviewScale scale=" + scale.getText());
+        ignoreChangeEvents = true;
+        try {
+            preview.setScale(Integer.parseInt(scale.getText()));
+            updateControls();
+        }
+        catch (final Exception e) {
+        }
+        ignoreChangeEvents = false;
+    }
+
+    /**
+     * apply a new width set by the user and update
+     *  all related image property displays
+     */
+    private void applyPreviewWidth() {
+        //System.out.println("applyPreviewWidth width=" + imgWidth.getIntValue().intValue());
+        ignoreChangeEvents = true;
+        preview.setPreviewWidth(imgWidth.getIntValue().intValue());
+        final int scalePct = preview.getScale();
+        //System.out.println("applyPreviewWidth scale now " + scalePct);
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        scale.setText(Integer.toString(scalePct));
+        set.addAttribute(HTML.Attribute.HEIGHT, Integer.toString(preview.getOriginalHeight() * scalePct / 100)
+                + SizeSelectorPanel.UNIT_PT);
+        //System.out.println("applyPreviewWidth, changing height to " + Integer.toString(
+        //    preview.getOriginalHeight() * scalePct / 100) + SizeSelectorPanel.UNIT_PT);
+        imgHeight.setValue(set);
+        ignoreChangeEvents = false;
+    }
+
+    /**
+     * apply a new height set by the user and update
+     *  all related image property displays
+     */
+    private void applyPreviewHeight() {
+        //System.out.println("applyPreviewHeight height=" + imgHeight.getIntValue().intValue());
+        ignoreChangeEvents = true;
+        preview.setPreviewHeight(imgHeight.getIntValue().intValue());
+        final int scalePct = preview.getScale();
+        //System.out.println("applyPreviewHeight scale now " + scalePct);
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        scale.setText(Integer.toString(scalePct));
+        set.addAttribute(HTML.Attribute.WIDTH, Integer.toString(preview.getOriginalWidth() * scalePct / 100)
+                + SizeSelectorPanel.UNIT_PT);
+        //System.out.println("applyPreviewHeight, changing width to " + Integer.toString(
+        //    preview.getOriginalWidth() * scalePct / 100) + SizeSelectorPanel.UNIT_PT);
+        imgWidth.setValue(set);
+        ignoreChangeEvents = false;
+    }
+
+    /* ---------------- event handling start ------------------------- */
+    /**
+     * implements the ActionListener interface to be notified of
+     * clicks onto the file repository buttons.
+     */
+    public void actionPerformed(final ActionEvent e) {
+        final Object src = e.getSource();
+        if (src == addImgBtn) {
+            handleAddImage();
+        }
+        else if (src == delImgBtn) {
+            handleDeleteImage();
+        }
+        else {
+            super.actionPerformed(e);
+        }
+    }
+
+    /**
+     * Listener for changes in the image list.
+     *
+     * <p>updates the image preview and property displays according
+     * to the current selection (if any)</p>
+     */
+    public void valueChanged(final ListSelectionEvent e) {
+        if (!imgFileList.isSelectionEmpty()) {
+            /*System.out.println("ImageDialog.valueChanged setting preview image to " + imgDir.getAbsolutePath() +
+                                 File.separator +
+                                 imgFileList.getSelectedValue().toString());*/
+            preview.setImage(new ImageIcon(imgDir.getAbsolutePath() + File.separator
+                    + imgFileList.getSelectedValue().toString()));
+            updateControls();
+        }
+        else {
+            preview.setImage(null);
+            final int vWidth = scPrev.getWidth() - 5;
+            final int vHeight = scPrev.getHeight() - 5;
+            preview.setPreferredSize(new Dimension(vWidth, vHeight));
+            preview.revalidate();
+        }
+    }
+
+    /**
+     * Listener for resize events.
+     *
+     * <p>used on the JScrollPane holding the image preview
+     * to adjust the preview to size changes and to synchronize
+     * property displays accordingly.</p>
+     */
+    private class ResizeListener extends ComponentAdapter {
+        public void componentResized(final ComponentEvent e) {
+            final int vWidth = scPrev.getWidth() - 5;
+            final int vHeight = scPrev.getHeight() - 5;
+            preview.setPreferredSize(new Dimension(vWidth, vHeight));
+            preview.revalidate();
+            updateControls();
+        }
+    }
+
+    /**
+     * Listener for key events
+     *
+     * <p>Used to adjust preview properties according to
+     * user settings in the scale text field</p>
+     */
+    private class KeyHandler extends KeyAdapter {
+        public void keyReleased(final KeyEvent e) {
+            final Object source = e.getSource();
+            final int keyCode = e.getKeyCode();
+            if (source.equals(scale)) {
+                if (keyCode == KeyEvent.VK_ENTER) {
+                    applyPreviewScale();
+                }
+            }
+        }
+    }
+
+    /**
+     * Listener for focus events
+     *
+     * <p>Used to adjust preview properties according to
+     * user settings in the scale text field</p>
+     */
+    private class FocusHandler extends FocusAdapter {
+        public void focusLost(final FocusEvent e) {
+            final Object source = e.getSource();
+            if (source.equals(scale)) {
+                applyPreviewScale();
+            }
+        }
+    }
+
+    /**
+     * Listener for change events
+     *
+     * <p>Used to adjust preview properties according to
+     * user settings in SizeSelectorPanels</p>
+     */
+    public void stateChanged(final ChangeEvent e) {
+        if (!ignoreChangeEvents) {
+            final Object source = e.getSource();
+            if (source.equals(imgWidth.getValueSelector())) {
+                applyPreviewWidth();
+            }
+            else if (source.equals(imgHeight.getValueSelector())) {
+                applyPreviewHeight();
+            }
+        }
+    }
+    /* ---------------- event handling end ------------------------- */
+}
diff --git a/src/com/lightdev/app/shtm/ImagePreview.java b/src/com/lightdev/app/shtm/ImagePreview.java
new file mode 100644
index 0000000..47bb776
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ImagePreview.java
@@ -0,0 +1,278 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.Scrollable;
+import javax.swing.SwingConstants;
+
+/**
+ * An <code>ImagePreview</code> is a component to preview
+ * GIF and JPEG images.
+ *
+ * <p>The preview adapts (shrinks) images to its size upon their
+ * assignment. When the preview is resized, its image is adapted again.</p>
+ *
+ * <p>Alternately, when altering the image width, height and scale properties
+ * with respective setters, the image is resized within the preview without
+ * the preview itself adapting in size.</p>
+ *
+ * <p>Scroll bars are displayed as appropriate.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ *
+ */
+class ImagePreview extends JComponent implements Scrollable {
+    /**
+     * scroll increment (for Scrollable implementation)
+     */
+    private int maxUnitIncrement = 1;
+    /**
+     * the image to be previewed
+     */
+    private ImageIcon pic;
+
+    /**
+     * Construct an <CODE>ImagePreview</CODE>.
+     *
+     * @param  pic - the image to be previewed
+     */
+    public ImagePreview(final ImageIcon pic) {
+        setImage(pic);
+    }
+
+    /**
+     * Construct an <CODE>ImagePreview</CODE> without an image
+     * associated.
+     */
+    public ImagePreview() {
+        this(null);
+    }
+
+    /**
+     * Get the original width of the image previewed in this component
+     *
+     * @return  the original width of the image previewed in this component
+     *             or -1 if no image is assigned
+     */
+    public int getOriginalWidth() {
+        if (pic != null) {
+            return pic.getIconWidth();
+        }
+        else {
+            return -1;
+        }
+    }
+
+    /**
+     * Get the original height of the image previewed in this component
+     *
+     * @return  the original height of the image previewed in this component
+     *             or -1 if no image is assigned
+     */
+    public int getOriginalHeight() {
+        if (pic != null) {
+            return pic.getIconHeight();
+        }
+        else {
+            return -1;
+        }
+    }
+
+    /**
+     * Set the image to be previewed.
+     */
+    public void setImage(final ImageIcon pic) {
+        this.pic = pic;
+        if (pic != null) {
+            this.getGraphics().clearRect(0, 0, getWidth(), getHeight());
+            this.paint(this.getGraphics());
+        }
+    }
+
+    /**
+     * Paints this component.
+     * If the image associated with this component is smaller than the size
+     * of the component, the image is painted in its original size. Otherwise,
+     * the image is scaled down to the size of this component.
+     *
+     * @param   g - The graphics context to use for painting.
+     */
+    public void paint(final Graphics g) {
+        if (pic != null) {
+            int dWidth = pic.getIconWidth();
+            int dHeight = pic.getIconHeight();
+            final int scale = getScale();
+            dWidth = dWidth * scale / 100;
+            dHeight = dHeight * scale / 100;
+            g.drawImage(pic.getImage(), 0, 0, dWidth, dHeight, this);
+        }
+    }
+
+    /**
+     * Gets the size adjustment necessary for the image to fit into this
+     * component and returns the resulting scale percentage.
+     *
+     * @return  the scale percentage of the image
+     */
+    public int getScale() {
+        int scale = 100;
+        if (pic != null) {
+            int vPct = 100;
+            int hPct = 100;
+            final Dimension ps = getPreferredSize();
+            hPct = (int) (ps.getWidth() / ((double) pic.getIconWidth() / (double) 100));
+            //System.out.println("ImagePreview getScale ps.getWidth " + ps.getWidth());
+            //System.out.println("ImagePreview getScale pic.getIconWidth() " + pic.getIconWidth());
+            //System.out.println("ImagePreview getScale hPct " + hPct + "\r\n\r\n");
+            vPct = (int) (ps.getHeight() / ((double) pic.getIconHeight() / (double) 100));
+            //System.out.println("ImagePreview getScale ps.getHeight() " + ps.getHeight());
+            //System.out.println("ImagePreview getScale pic.getIconHeight() " + pic.getIconHeight());
+            //System.out.println("ImagePreview getScale vPct " + vPct + "\r\n\r\n");
+            if (hPct < vPct) {
+                scale = hPct;
+            }
+            else {
+                scale = vPct;
+            }
+        }
+        //System.out.println("ImagePreview getScale=" + scale + "\r\n\r\n");
+        return scale;
+    }
+
+    /**
+     * set the preview to a new width maintaining the image proportions
+     *
+     * @param  newWidth   the new width for the image preview
+     */
+    public void setPreviewWidth(final int newWidth) {
+        //System.out.println("ImagePreview setPreviewWidth newWidth=" + newWidth);
+        if (pic != null) {
+            try {
+                final int hPct = (int) (newWidth / ((double) getOriginalWidth() / (double) 100));
+                final int newHeight = getOriginalHeight() * hPct / 100;
+                setPreferredSize(new Dimension(newWidth, newHeight));
+            }
+            catch (final Exception e) {
+                e.printStackTrace();
+                setPreferredSize(new Dimension(20, 20));
+            }
+            revalidate();
+        }
+    }
+
+    /**
+     * set the preview to a new height maintaining the image proportions
+     *
+     * @param  newHeight   the new height for the image preview
+     */
+    public void setPreviewHeight(final int newHeight) {
+        if (pic != null) {
+            try {
+                final int vPct = (int) (newHeight / ((double) getOriginalHeight() / (double) 100));
+                final int newWidth = getOriginalWidth() * vPct / 100;
+                setPreferredSize(new Dimension(newWidth, newHeight));
+            }
+            catch (final Exception e) {
+                e.printStackTrace();
+                setPreferredSize(new Dimension(20, 20));
+            }
+            revalidate();
+        }
+    }
+
+    /**
+     * Adapt the size of the image previewed by this component to a new
+     * scale.
+     *
+     * @param  newScale   the new scale the image shall adapt to in size
+     */
+    public void setScale(final int newScale) {
+        int newWidth;
+        int newHeight;
+        newWidth = getOriginalWidth() * newScale / 100;
+        newHeight = getOriginalHeight() * newScale / 100;
+        setPreferredSize(new Dimension(newWidth, newHeight));
+        revalidate();
+    }
+
+    /*
+      ------------ Scrollable implementation start ----------------------
+    */
+    public Dimension getPreferredScrollableViewportSize() {
+        return getPreferredSize();
+    }
+
+    public int getScrollableUnitIncrement(final Rectangle visibleRect, final int orientation, final int direction) {
+        //Get the current position.
+        int currentPosition = 0;
+        if (orientation == SwingConstants.HORIZONTAL) {
+            currentPosition = visibleRect.x;
+        }
+        else {
+            currentPosition = visibleRect.y;
+        }
+        //Return the number of pixels between currentPosition
+        //and the nearest tick mark in the indicated direction.
+        if (direction < 0) {
+            final int newPosition = currentPosition - (currentPosition / maxUnitIncrement) * maxUnitIncrement;
+            return (newPosition == 0) ? maxUnitIncrement : newPosition;
+        }
+        else {
+            return ((currentPosition / maxUnitIncrement) + 1) * maxUnitIncrement - currentPosition;
+        }
+    }
+
+    public int getScrollableBlockIncrement(final Rectangle visibleRect, final int orientation, final int direction) {
+        if (orientation == SwingConstants.HORIZONTAL) {
+            return visibleRect.width - maxUnitIncrement;
+        }
+        else {
+            return visibleRect.height - maxUnitIncrement;
+        }
+    }
+
+    public boolean getScrollableTracksViewportWidth() {
+        return false;
+    }
+
+    public boolean getScrollableTracksViewportHeight() {
+        return false;
+    }
+
+    public void setMaxUnitIncrement(final int pixels) {
+        maxUnitIncrement = pixels;
+    }
+    /*
+      --------- Scrollable implementation end ---------------------------
+    */
+}
diff --git a/src/com/lightdev/app/shtm/InvisibleView.java b/src/com/lightdev/app/shtm/InvisibleView.java
new file mode 100644
index 0000000..673a4ea
--- /dev/null
+++ b/src/com/lightdev/app/shtm/InvisibleView.java
@@ -0,0 +1,197 @@
+/*
+* SimplyHTML, a word processor based on Java, HTML and CSS
+* Copyright (C) 2002 Ulrich Hilger
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Element;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.Position;
+import javax.swing.text.View;
+
+/**
+ * A view to hide HTML tags (e.g. comments)
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class InvisibleView extends View {
+    /** indicates whether or not this view is to be shown in its component */
+    boolean isVisible = false;
+
+    /**
+     * constructor
+     */
+    public InvisibleView(final Element e) {
+        super(e);
+    }
+
+    /**
+     * Determines the preferred span for this view along an
+     * axis.
+     *
+     * @param axis may be either <code>View.X_AXIS</code> or
+     *		<code>View.Y_AXIS</code>
+     * @return   the span the view would like to be rendered into.
+     *           Typically the view is told to render into the span
+     *           that is returned, although there is no guarantee.
+     *           The parent may choose to resize or break the view
+     * @see View#getPreferredSpan
+     */
+    public float getPreferredSpan(final int axis) {
+        return 0;
+    }
+
+    /**
+     * Determines the maximum span for this view along an
+     * axis.
+     *
+     * @param axis may be either <code>View.X_AXIS</code> or
+     *		<code>View.Y_AXIS</code>
+     * @return  the maximum span the view can be rendered into
+     * @see View#getPreferredSpan
+     */
+    public float getMaximumSpan() {
+        return 0;
+    }
+
+    /**
+     * Determines the minimum span for this view along an
+     * axis.
+     *
+     * @param axis may be either <code>View.X_AXIS</code> or
+     *		<code>View.Y_AXIS</code>
+     * @return  the minimum span the view can be rendered into
+     * @see View#getPreferredSpan
+     */
+    public float getMinimumSpan() {
+        return 0;
+    }
+
+    /**
+     * Renders using the given rendering surface and area on that
+     * surface.  The view may need to do layout and create child
+     * views to enable itself to render into the given allocation.
+     *
+     * @param g the rendering surface to use
+     * @param allocation the allocated region to render into
+     * @see View#paint
+     */
+    public void paint(final Graphics g, final Shape allocation) {
+        if (isVisible) {
+            // paint something here
+        }
+        else {
+            setSize(0, 0);
+        }
+    }
+
+    /**
+     * Provides a mapping from the view coordinate space to the logical
+     * coordinate space of the model.  The <code>biasReturn</code>
+     * argument will be filled in to indicate that the point given is
+     * closer to the next character in the model or the previous
+     * character in the model.
+     *
+     * @param x the X coordinate >= 0
+     * @param y the Y coordinate >= 0
+     * @param a the allocated region in which to render
+     * @return the location within the model that best represents the
+     *  given point in the view >= 0.  The <code>biasReturn</code>
+     *  argument will be
+     * filled in to indicate that the point given is closer to the next
+     * character in the model or the previous character in the model.
+     */
+    public int viewToModel(final float x, final float y, final Shape a, final Position.Bias[] parm4) {
+        return 0;
+    }
+
+    /**
+     * Provides a mapping, for a given character,
+     * from the document model coordinate space
+     * to the view coordinate space.
+     *
+     * @param pos the position of the desired character (>=0)
+     * @param a the area of the view, which encompasses the requested character
+     * @param b the bias toward the previous character or the
+     *  next character represented by the offset, in case the
+     *  position is a boundary of two views; <code>b</code> will have one
+     *  of these values:
+     * <ul>
+     * <li> <code>Position.Bias.Forward</code>
+     * <li> <code>Position.Bias.Backward</code>
+     * </ul>
+     * @return the bounding box, in view coordinate space,
+     *		of the character at the specified position
+     * @exception BadLocationException  if the specified position does
+     *   not represent a valid location in the associated document
+     * @exception IllegalArgumentException if <code>b</code> is not one of the
+     *		legal <code>Position.Bias</code> values listed above
+     * @see View#viewToModel
+     */
+    public Shape modelToView(final int pos, final Shape a, final Position.Bias b)
+            throws javax.swing.text.BadLocationException {
+        return new Rectangle(0, 0);
+    }
+
+    /**
+     * Establishes the parent view for this view.  This is
+     * guaranteed to be called before any other methods if the
+     * parent view is functioning properly.  This is also
+     * the last method called, since it is called to indicate
+     * the view has been removed from the hierarchy as
+     * well. When this method is called to set the parent to
+     * null, this method does the same for each of its children,
+     * propogating the notification that they have been
+     * disconnected from the view tree. If this is
+     * reimplemented, <code>super.setParent()</code> should
+     * be called.
+     *
+     * @param parent the new parent, or <code>null</code> if the view is
+     * 		being removed from a parent
+     */
+    public void setParent(final View parent) {
+        if (parent != null) {
+            final Container host = parent.getContainer();
+            if (host != null) {
+                isVisible = ((JTextComponent) host).isEditable();
+            }
+        }
+        super.setParent(parent);
+    }
+
+    /**
+     * @return true if the Component is visible.
+     */
+    public boolean isVisible() {
+        return isVisible;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/LicensePane.java b/src/com/lightdev/app/shtm/LicensePane.java
new file mode 100644
index 0000000..2bec058
--- /dev/null
+++ b/src/com/lightdev/app/shtm/LicensePane.java
@@ -0,0 +1,97 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+/**
+ * A panel for displaying license information of application SimplyHTML.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class LicensePane extends JPanel {
+    /* line separator character (sequence) */
+    private final String lineSeparator = System.getProperty("line.separator");
+
+    /**
+     * construct a <code>LicensePane</code>
+     */
+    public LicensePane(final Dimension d, final String licensePath) {
+        /* create a text area to show the license text in */
+        final JTextArea licText = new JTextArea(getLicenseText(getClass().getResourceAsStream(licensePath)));
+        licText.setEditable(false);
+        licText.setFont(new Font("Courier", Font.PLAIN, 12));
+        /* create a scroll pane as the license text is long */
+        JScrollPane licPane = new JScrollPane();
+        licPane = new JScrollPane(licText);
+        licPane.setPreferredSize(d);
+        licPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+        licPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        /* add the scroll pane to this panel */
+        setLayout(new BorderLayout());
+        add(licPane, BorderLayout.CENTER);
+        licText.setCaretPosition(0); // go to top of text (for JRE versions earlier than 1.4)
+    }
+
+    /**
+     * read and return the license text
+     *
+     * @return the license text
+     */
+    private String getLicenseText(final InputStream is) {
+        final StringBuffer license = new StringBuffer();
+        try {
+            // InputStream is = getClass().getResourceAsStream(getLicense());
+            final BufferedReader r = new BufferedReader(new InputStreamReader(is));
+            String buf = r.readLine();
+            while (buf != null) {
+                license.append(buf);
+                license.append(lineSeparator);
+                buf = r.readLine();
+            }
+            r.close();
+            is.close();
+        }
+        catch (final Exception e) {
+            Util.errMsg(
+                this,
+                "The license text could not be opened.\n\nPlease consult file 'readme.txt' for installation guidelines\n\nSimplyHTML and all of its parts are distributed under\nthe terms and conditions of the GNU General Public License (GPL).\nYou may want to obtain a free and complete distribution package at\nhttp://www.lightdev.com",
+                e);
+        }
+        return license.toString();
+    }
+}
diff --git a/src/com/lightdev/app/shtm/LinkDialog.java b/src/com/lightdev/app/shtm/LinkDialog.java
new file mode 100644
index 0000000..75492a1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/LinkDialog.java
@@ -0,0 +1,818 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.swing.ButtonGroup;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.HTML;
+
+/**
+ * Dialog to create and edit links.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ *
+ */
+class LinkDialog extends DialogShell implements ActionListener {
+    /** table for link types: name -> type */
+    private Hashtable linkTypes;
+    /** table for link types: type -> name */
+    private Hashtable linkTypeNames;
+    /** cache for link address */
+    private String addressCache = null;
+    /** the document this dialog was constructed with */
+    private final Document doc;
+    private final SHTMLEditorPane editorPane;
+    /** dialog components */
+    private final JComboBox linkStyle;
+    private final JComboBox linkType;
+    private final JTextField linkAddress;
+    private final JButton browseAddress;
+    private final JTextField linkAnchor;
+    private final JButton browseAnchor;
+    private final JTextField linkText;
+    private final JRadioButton showAsText;
+    private final JRadioButton showAsImage;
+    private String linkImageFileName;
+    private final ImagePreview linkImage;
+    private final JButton setImage;
+    private final JTextField linkImgWidth;
+    private final JTextField linkImgHeight;
+    private final JPanel linkTextPanel;
+    private final JPanel linkImagePanel;
+    /** some constants */
+    private final String LINK_TYPE_KEY = "linkType";
+    private final String LINK_TYPE_NAME_KEY = "linkTypeName";
+    private final String LINK_TYPE_RELATIVE_KEY = Util.getResourceString("linkType1");
+    private final String LINK_TYPE_NEWS_KEY = Util.getResourceString("linkType7");
+    private final String LINK_TYPE_MAILTO_KEY = Util.getResourceString("linkType8");
+    private final String LINK_TYPE_RELATIVE = Util.getResourceString("linkTypeName1");
+    private final String LINK_TYPE_LOCAL = Util.getResourceString("linkTypeName2");
+    private final String LINK_TYPE_NEWS = Util.getResourceString("linkTypeName7");
+    private final String LINK_TYPE_MAILTO = Util.getResourceString("linkTypeName8");
+    /** indicates, whether or not action handlers should react on events */
+    private boolean ignoreActions = false;
+    /** the image directory for the document links are edited from in this dialog */
+    private final File imgDir;
+    /** the currently selected image file for this link */
+    private String imgFile = null;
+    /** the help id for this dialog */
+    private static final String helpTopicId = "item164";
+    private static boolean simpleLinkDialog = Util.preferenceIsTrue("simpleLinkDialog");
+
+    //private int renderMode;
+    /**
+     * construct a new LinkDialog
+     *
+     * If the selection (selectionStart and selectionEnd) has an existing link,
+     * edit this link
+     * Create a link for the selected text otherwise.
+     *
+     * @param parent  the parent frame for the dialog
+     * @param title  the dialog title
+     * @param doc  the document to edit link settings for
+     */
+    public LinkDialog(final Frame parent, final String title, final SHTMLEditorPane editorPane, final File imgDir/*, int renderMode*/) {
+        // initialize DialogShell
+        super(parent, title, helpTopicId);
+        // save document for later use
+        this.editorPane = editorPane;
+        doc = editorPane.getSHTMLDocument();
+        this.imgDir = imgDir;
+        //this.renderMode = renderMode;
+        // layout and constraints to use later on
+        final GridBagLayout g = new GridBagLayout();
+        final GridBagConstraints c = new GridBagConstraints();
+        // create link style selector
+        final JPanel p = new JPanel(g);
+        JLabel lb = new JLabel(Util.getResourceString("linkStyleLabel"));
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, lb, g, c, 0, 0, GridBagConstraints.EAST);
+        }
+        final Vector styleNames = Util
+            .getStyleNamesForTag(((SHTMLDocument) doc).getStyleSheet(), HTML.Tag.A.toString());
+        final String standardStyleName = Util.getResourceString("standardStyleName");
+        styleNames.insertElementAt(standardStyleName, 0);
+        linkStyle = new JComboBox(styleNames);
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, linkStyle, g, c, 1, 0, GridBagConstraints.WEST);
+        }
+        // create link type selector
+        lb = new JLabel(Util.getResourceString("linkTypeLabel"));
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, lb, g, c, 0, 1, GridBagConstraints.EAST);
+        }
+        buildLinkTypes();
+        linkType = new JComboBox(linkTypeNames.values().toArray());
+        linkType.addActionListener(this);
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, linkType, g, c, 1, 1, GridBagConstraints.WEST);
+        }
+        // create link address field
+        lb = new JLabel(Util.getResourceString("linkAddressLabel"));
+        Util.addGridBagComponent(p, lb, g, c, 0, 2, GridBagConstraints.EAST);
+        linkAddress = new JTextField();
+        linkAddress.setPreferredSize(new Dimension(300, 20));
+        linkAddress.setMaximumSize(new Dimension(500, 20));
+        linkAddress.addActionListener(this);
+        Util.addGridBagComponent(p, linkAddress, g, c, 1, 2, GridBagConstraints.WEST, 2, 1,
+            GridBagConstraints.HORIZONTAL, 1, 0);
+        browseAddress = new JButton(Util.getResourceString("linkBrowseLabel"));
+        browseAddress.addActionListener(this);
+        Util.addGridBagComponent(p, browseAddress, g, c, 3, 2, GridBagConstraints.WEST);
+        // create link anchor field
+        lb = new JLabel(Util.getResourceString("linkAnchorLabel"));
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, lb, g, c, 0, 3, GridBagConstraints.EAST);
+        }
+        linkAnchor = new JTextField();
+        linkAnchor.setPreferredSize(new Dimension(150, 20));
+        linkAnchor.setMaximumSize(new Dimension(500, 20));
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, linkAnchor, g, c, 1, 3, GridBagConstraints.WEST, 1, 1,
+                GridBagConstraints.HORIZONTAL, 1, 0);
+        }
+        browseAnchor = new JButton(Util.getResourceString("linkBrowseLabel"));
+        browseAnchor.addActionListener(this);
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, browseAnchor, g, c, 2, 3, GridBagConstraints.WEST);
+        }
+        // create link display selector
+        lb = new JLabel(Util.getResourceString("linkDisplayLabel"));
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, lb, g, c, 0, 4, GridBagConstraints.EAST);
+        }
+        showAsText = new JRadioButton(Util.getResourceString("showAsTextLabel"));
+        showAsText.addActionListener(this);
+        showAsImage = new JRadioButton(Util.getResourceString("showAsImageLabel"));
+        showAsImage.addActionListener(this);
+        JPanel helpPanel = new JPanel();
+        helpPanel.add(showAsText);
+        helpPanel.add(showAsImage);
+        if (!simpleLinkDialog) {
+            Util.addGridBagComponent(p, helpPanel, g, c, 1, 4, GridBagConstraints.WEST);
+        }
+        final ButtonGroup bg = new ButtonGroup();
+        bg.add(showAsText);
+        bg.add(showAsImage);
+        // create link text panel
+        linkTextPanel = new JPanel(new BorderLayout());
+        linkTextPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("linkTextLabel")));
+        linkText = new JTextField();
+        linkText.setPreferredSize(new Dimension(400, 20));
+        linkText.setMaximumSize(new Dimension(500, 20));
+        if (!simpleLinkDialog) {
+            linkTextPanel.add(linkText, BorderLayout.CENTER);
+            Util.addGridBagComponent(p, linkTextPanel, g, c, 1, 5, GridBagConstraints.WEST, 2, 1,
+                GridBagConstraints.HORIZONTAL, 1, 0);
+        }
+        else {
+            lb = new JLabel(Util.getResourceString("linkTextLabel"));
+            Util.addGridBagComponent(p, lb, g, c, 0, 5, GridBagConstraints.EAST);
+            Util.addGridBagComponent(p, linkText, g, c, 1, 5, GridBagConstraints.WEST, 2, 1,
+                GridBagConstraints.HORIZONTAL, 1, 0);
+        }
+        //linkTextPanel.setVisible(false);
+        // create link image panel
+        linkImagePanel = new JPanel(new BorderLayout(5, 5));
+        linkImagePanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("linkImageLabel")));
+        linkImage = new ImagePreview();
+        linkImage.setPreferredSize(new Dimension(70, 70));
+        linkImagePanel.add(new JScrollPane(linkImage), BorderLayout.CENTER);
+        helpPanel = new JPanel(g);
+        lb = new JLabel(Util.getResourceString("imgWidthLabel"));
+        Util.addGridBagComponent(helpPanel, lb, g, c, 0, 0, GridBagConstraints.EAST);
+        linkImgWidth = new JTextField();
+        linkImgWidth.setPreferredSize(new Dimension(50, 20));
+        linkImgWidth.setMinimumSize(new Dimension(50, 20));
+        linkImgWidth.setEditable(false);
+        Util.addGridBagComponent(helpPanel, linkImgWidth, g, c, 1, 0, GridBagConstraints.WEST);
+        lb = new JLabel(Util.getResourceString("imgHeightLabel"));
+        Util.addGridBagComponent(helpPanel, lb, g, c, 0, 1, GridBagConstraints.EAST);
+        linkImgHeight = new JTextField();
+        linkImgHeight.setPreferredSize(new Dimension(50, 20));
+        linkImgHeight.setMinimumSize(new Dimension(50, 20));
+        linkImgHeight.setEditable(false);
+        Util.addGridBagComponent(helpPanel, linkImgHeight, g, c, 1, 1, GridBagConstraints.WEST);
+        setImage = new JButton(Util.getResourceString("setImageLabel"));
+        setImage.addActionListener(this);
+        Util.addGridBagComponent(helpPanel, setImage, g, c, 1, 2, GridBagConstraints.WEST);
+        final JPanel helpPanel2 = new JPanel(new BorderLayout());
+        helpPanel2.add(helpPanel, BorderLayout.NORTH);
+        linkImagePanel.add(helpPanel2, BorderLayout.EAST);
+        Util.addGridBagComponent(p, linkImagePanel, g, c, 1, 5, GridBagConstraints.WEST, 2, 1, GridBagConstraints.BOTH,
+            1, 1);
+        // get content pane of DialogShell to add components to
+        final Container contentPane = super.getContentPane();
+        // add panels to content pane of DialogShell
+        contentPane.add(p, BorderLayout.CENTER);
+        // add key listeners
+        // The following could perhaps be done by adding the listener only
+        // to one place. But to which one?
+        linkAddress.addKeyListener(getCompletionKeyListener());
+        linkText.addKeyListener(getCompletionKeyListener());
+        linkAnchor.addKeyListener(getCompletionKeyListener());
+        // cause optimal placement of all elements
+        pack();
+        // init dialog with existing link (if any)
+        if (!setExistingLink(editorPane.getSelectionStart(), editorPane.getSelectionEnd())) {
+            setLinkText(editorPane.getSelectionStart(), editorPane.getSelectionEnd());
+        }
+    }
+
+    /**
+     * set the link text component of this dialog from the document
+     * this dialog is associated to
+     *
+     * @param start  the start position of the link text in the document
+     * @param end  the end position of the link text in the document
+     */
+    private void setLinkText(final int start, final int end) {
+        try {
+            linkText.setText(doc.getText(start, end - start));
+            //System.out.println("showAsText = true");
+            showAsText.setSelected(true);
+            linkTextPanel.setVisible(true);
+            linkImagePanel.setVisible(false);
+        }
+        catch (final BadLocationException ble) {
+            Util.errMsg(this, ble.getLocalizedMessage(), ble);
+        }
+    }
+
+    /**
+     * set components of this dialog from an exisiting link in
+     * the associated document (if any).
+     *
+     * @param selectionStart  the start position of the text currently selected in the document
+     * @param selectionEnd  the end position of the text currently selected in the document
+     *
+     * @return ture, if a link was found, false if not
+     */
+    private boolean setExistingLink(final int selectionStart, final int selectionEnd) {
+        setIgnoreActions(true);
+        final Element linkElement = editorPane.getCurrentLinkElement();
+        final boolean foundLink = (linkElement != null);
+        if (foundLink) {
+            final AttributeSet elemAttrs = linkElement.getAttributes();
+            final Object linkAttr = elemAttrs.getAttribute(HTML.Tag.A);
+            final Object href = ((AttributeSet) linkAttr).getAttribute(HTML.Attribute.HREF);
+            if (href != null) {
+                try {
+                    setDialogFromUrl(new URL(href.toString()));
+                }
+                catch (final Exception ex) {
+                    setDialogFromRelative(href.toString());
+                }
+                final Object img = elemAttrs.getAttribute(HTML.Attribute.SRC);
+                if (img != null) {
+                    setLinkImage(img, elemAttrs);
+                }
+                else {
+                    setLinkText(linkElement.getStartOffset(), linkElement.getEndOffset());
+                }
+            }
+        }
+        else {
+            linkType.setSelectedItem(LINK_TYPE_LOCAL);
+            setLinkText(selectionStart, selectionEnd);
+        }
+        setIgnoreActions(false);
+        return foundLink;
+    }
+
+    /**
+     * set the link image to be shown in this dialog from a given
+     * image file name and AttributeSet
+     *
+     * @param imgAttr  the file name of the image to be shown
+     * @param attrSet  the set of attributes having width and height of the image (if any)
+     */
+    public void setLinkImage(final Object imgAttr, final AttributeSet attrSet) {
+        String wStr = null;
+        String hStr = null;
+        if (imgAttr != null) {
+            imgFile = Util.resolveRelativePath(imgAttr.toString(), ((SHTMLDocument) doc).getBase().getPath()).replace(
+                Util.URL_SEPARATOR_CHAR, File.separatorChar);
+            while (imgFile.startsWith(File.separator)) {
+                imgFile = imgFile.substring(1);
+            }
+        }
+        final Object width = attrSet.getAttribute(HTML.Attribute.WIDTH);
+        if (width != null) {
+            wStr = width.toString();
+        }
+        final Object height = attrSet.getAttribute(HTML.Attribute.HEIGHT);
+        if (height != null) {
+            hStr = height.toString();
+        }
+        setImageSpecs(wStr, hStr);
+        showAsImage.setSelected(true);
+        linkTextPanel.setVisible(false);
+        linkImagePanel.setVisible(true);
+    }
+
+    /**
+     * get the text to be displayed for the link
+     *
+     * @return the link text
+     */
+    public String getLinkText() {
+        return linkText.getText();
+    }
+
+    /**
+     * get the style name (attribute 'class') to be used for
+     * a link
+     *
+     * @return the style name
+     */
+    public String getStyleName() {
+        return linkStyle.getSelectedItem().toString();
+    }
+
+    /**
+     * set this dialog to ignore actions
+     *
+     * @param ignore  indicator whether or not to ignore actions
+     */
+    public void setIgnoreActions(final boolean ignore) {
+        ignoreActions = ignore;
+    }
+
+    /**
+     * set the components of this dialog from a given URL
+     *
+     * @param url  the url to set link components from
+     */
+    private void setDialogFromUrl(final URL url) {
+        if (url == null) {
+            return;
+        }
+        if (simpleLinkDialog) {
+            setLinkAddress(url.toString());
+            return;
+        }
+        String protName;
+        final String protocol = url.getProtocol();
+        if (protocol != null) {
+            protName = (String) linkTypeNames.get(protocol);
+        }
+        else {
+            protName = (String) linkTypeNames.get(LINK_TYPE_RELATIVE_KEY);
+        }
+        if (protName != null) {
+            linkType.setSelectedItem(protName);
+        }
+        setLinkAddress(getPathFromUrl(url, protocol));
+        linkAnchor.setText(url.getRef());
+    }
+
+    /**
+     * extract the path from a URL
+     *
+     * @param url  the url to get the path from
+     * @param protocol  the protocol of the url
+     *
+     * @return the path of the URL
+     */
+    private String getPathFromUrl(final URL url, final String protocol) {
+        String path = "";
+        final String urlStr = url.toString();
+        int pos = urlStr.indexOf(protocol);
+        if (pos > -1) {
+            path = urlStr.substring(protocol.length());
+            while (path.startsWith(Util.URL_SEPARATOR) || path.startsWith(Util.PROTOCOL_SEPARATOR)) {
+                path = path.substring(1);
+            }
+        }
+        pos = path.indexOf(Util.ANCHOR_SEPARATOR);
+        if (pos > -1) {
+            path = path.substring(0, pos);
+        }
+        return path;
+    }
+
+    /**
+     * set components of this dialog from a relative link path
+     *
+     * @param hrefStr  the relative link to show in the dialog
+     */
+    private void setDialogFromRelative(String hrefStr) {
+        linkType.setSelectedItem(LINK_TYPE_RELATIVE);
+        final int pos = hrefStr.indexOf(Util.ANCHOR_SEPARATOR);
+        if (pos > -1) {
+            linkAnchor.setText(hrefStr.substring(pos + 1));
+            hrefStr = hrefStr.substring(0, pos);
+        }
+        setLinkAddress(hrefStr);
+    }
+
+    /**
+     * build link type tables to match
+     * type names by types and vice versa
+     */
+    private void buildLinkTypes() {
+        String name;
+        String type;
+        linkTypes = new Hashtable(); // key = type name -> value = type
+        linkTypeNames = new Hashtable(); // key = type -> value = type name
+        for (int i = 1; i < 9; i++) {
+            type = Util.getResourceString(LINK_TYPE_KEY + Integer.toString(i));
+            name = Util.getResourceString(LINK_TYPE_NAME_KEY + Integer.toString(i));
+            linkTypes.put(name, type);
+            linkTypeNames.put(type, name);
+        }
+    }
+
+    private boolean linkAddressHasProtocol() {
+        return linkAddress.getText().indexOf(':') >= 0;
+    }
+
+    /**
+     * get the chosen protocol
+     */
+    private String getProtocol() {
+        String prot = null;
+        try {
+            final String protName = linkType.getSelectedItem().toString();
+            if (!protName.equalsIgnoreCase(LINK_TYPE_RELATIVE)) {
+                prot = transformProtocol(linkTypes.get(protName).toString());
+            }
+        }
+        catch (final Exception e) {
+        }
+        return prot;
+    }
+
+    /**
+     * transform a given protocol to be shown in the correct notation
+     */
+    private String transformProtocol(final String protName) {
+        final StringBuffer prot = new StringBuffer(protName);
+        if (protName.equalsIgnoreCase(LINK_TYPE_MAILTO_KEY) || protName.equalsIgnoreCase(LINK_TYPE_NEWS_KEY)) {
+            prot.append(Util.PROTOCOL_SEPARATOR);
+        }
+        else {
+            if (!protName.equalsIgnoreCase(LINK_TYPE_RELATIVE_KEY)) {
+                prot.append(Util.PROTOCOL_SEPARATOR + Util.URL_SEPARATOR);
+            }
+        }
+        return prot.toString();
+    }
+
+    /**
+     * Gets a file from a file chooser.
+     *
+     * @return the chosen file, or null, if none has been chosen or cancel has benn pressed
+     */
+    private File chooseFile() {
+        File file = null;
+        final JFileChooser chooser = new JFileChooser();
+        chooser.setMultiSelectionEnabled(false);
+        chooser.setSelectedFile(new File(((SHTMLDocument) doc).getBase().getFile()));
+        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
+            file = chooser.getSelectedFile();
+        }
+        return file;
+    }
+
+    /**
+     * set the address field of this <code>LinkDialog</code>
+     *
+     * @param address  the address to be set
+     */
+    private void setLinkAddress(final String address) {
+        addressCache = getLinkAddress();
+        linkAddress.setText(address);
+    }
+
+    /**
+     * get a set of attributes to represent the link
+     * defined in this dialog
+     *
+     * @return the set of attributes defining this link
+     */
+    public AttributeSet getLinkAttribute() {
+        final SimpleAttributeSet aSet = new SimpleAttributeSet();
+        aSet.addAttribute(HTML.Attribute.HREF, getHref());
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        if (showAsImage.isSelected()) {
+            final SimpleAttributeSet imgSet = new SimpleAttributeSet();
+            imgSet.addAttribute(HTML.Attribute.SRC, imgFile);
+            set.addAttribute(HTML.Tag.IMG, imgSet);
+        }
+        set.addAttribute(HTML.Tag.A, aSet);
+        return set;
+    }
+
+    /**
+     * get the file name of the image to be taken
+     * for the link defined in this dialog
+     *
+     * @return the image file name
+     */
+    public String getLinkImage() {
+        if (showAsImage.isSelected()) {
+            return imgFile;
+        }
+        else {
+            return null;
+        }
+    }
+
+    /**
+     * get the size of the image to be taken
+     * for the link defined in this dialog
+     *
+     * @return the image size
+     */
+    public Dimension getLinkImageSize() {
+        if (showAsImage.isSelected()) {
+            try {
+                return new Dimension(Integer.parseInt(linkImgWidth.getText()),
+                    Integer.parseInt(linkImgHeight.getText()));
+            }
+            catch (final Exception e) {
+                return null;
+            }
+        }
+        else {
+            return null;
+        }
+    }
+
+    /**
+     * get the currently selected link address
+     *
+     * @return the link address
+     */
+    public String getLinkAddress() {
+        String link = linkAddress.getText();
+        final String prot = getProtocol();
+        if (prot != null && !linkAddressHasProtocol()
+                && !prot.equalsIgnoreCase(transformProtocol(LINK_TYPE_RELATIVE_KEY))
+                && !prot.equalsIgnoreCase(transformProtocol(LINK_TYPE_MAILTO_KEY))
+                && !link.startsWith(Util.URL_SEPARATOR)) {
+            link = Util.URL_SEPARATOR + link;
+        }
+        return link;
+    }
+
+    /**
+     * Gets the URL string of the hyperlink's reference.
+     *
+     * @return the object this link refers to
+     */
+    public String getHref() {
+        final StringBuffer href = new StringBuffer();
+        final String protocol = getProtocol();
+        final String linkAddressText = linkAddress.getText();
+        final String linkAnchorText = linkAnchor.getText();
+        if ((linkAddressText == null || linkAddressText.length() < 1)
+                && (linkAnchorText != null && linkAnchorText.length() > 0)) {
+            // link to an anchor inside this document
+            href.append(Util.ANCHOR_SEPARATOR);
+            href.append(linkAnchorText);
+        }
+        else {
+            if (protocol != null && !linkAddressHasProtocol()) {
+                href.append(protocol);
+            }
+            href.append(getLinkAddress());
+            final String anchor = linkAnchor.getText();
+            if (anchor.length() > 0) {
+                href.append(Util.ANCHOR_SEPARATOR);
+                href.append(anchor);
+            }
+        }
+        return href.toString();
+    }
+
+    /**
+     * get the file this link refers to (if any)
+     *
+     * @return the file this link refers to, or null if no file is referenced
+     */
+    private File getLinkedFile() {
+        File file = null;
+        try {
+            final String prot = linkType.getSelectedItem().toString();
+            if (prot.equalsIgnoreCase(LINK_TYPE_LOCAL)) {
+                file = new File(getLinkAddress().replace(Util.URL_SEPARATOR_CHAR, File.separatorChar));
+            }
+            else if (prot.equalsIgnoreCase(LINK_TYPE_RELATIVE)) {
+                new File(((SHTMLDocument) doc).getBase().getPath());
+                final String toStr = getLinkAddress();
+                new File(toStr);
+                file = new File(Util.resolveRelativePath(getLinkAddress(), ((SHTMLDocument) doc).getBase().getPath()));
+            }
+        }
+        catch (final Exception e) {
+        }
+        return file;
+    }
+
+    /** -------- ActionListener implementation start (including additional handling methods) ---------- */
+    /**
+     * actionListener implementation to control dialog components
+     */
+    public void actionPerformed(final ActionEvent e) {
+        if (!ignoreActions) {
+            final Object source = e.getSource();
+            if (source.equals(showAsText)) {
+                linkTextPanel.setVisible(true);
+                linkImagePanel.setVisible(false);
+            }
+            else if (source.equals(showAsImage)) {
+                linkTextPanel.setVisible(false);
+                linkImagePanel.setVisible(true);
+            }
+            else if (source.equals(browseAddress)) {
+                final File file = chooseFile();
+                if (file != null) {
+                    if (simpleLinkDialog) {
+                        try {
+                            setLinkAddress(file.toURI().toURL().toString());
+                        }
+                        catch (final Exception ex) {
+                        }
+                    }
+                    else {
+                        setLinkAddress(file.getPath().replace(File.separatorChar, Util.URL_SEPARATOR_CHAR));
+                    }
+                }
+            }
+            else if (source.equals(linkType)) {
+                handleLinkTypeAction();
+            }
+            else if (source.equals(browseAnchor)) {
+                handleBrowseAnchorAction();
+            }
+            else if (source.equals(setImage)) {
+                handleLinkImageAction();
+            }
+            else {
+                super.actionPerformed(e);
+            }
+        }
+    }
+
+    /**
+     * handle an action performed by the component that allows
+     * selection of a link image
+     */
+    private void handleLinkImageAction() {
+        final ImageDialog dlg = new ImageDialog(this, Util.getResourceString("imageDialogTitle"), imgDir);
+        if (imgFile != null) {
+            dlg.setImage(imgFile, linkImgWidth.getText(), linkImgHeight.getText());
+        }
+        Util.center(this, dlg);
+        dlg.setModal(true);
+        dlg.setVisible(true);
+        /** if the user made a selection, apply it to the document */
+        if (dlg.getResult() == DialogShell.RESULT_OK) {
+            imgFile = Util.resolveRelativePath(dlg.getImageSrc(), ((SHTMLDocument) doc).getBase().getPath()).replace(
+                Util.URL_SEPARATOR_CHAR, File.separatorChar);
+            while (imgFile.startsWith(File.separator)) {
+                imgFile = imgFile.substring(1);
+            }
+            setImageSpecs(dlg.getImgWidth().toString(), dlg.getImgHeight().toString());
+        }
+    }
+
+    /**
+     * set the properties of the image to be shown for
+     * the link defined ni this dialog
+     *
+     * @param width  image width
+     * @param height image height
+     */
+    private void setImageSpecs(final String width, final String height) {
+        final ImageIcon icon = new ImageIcon(imgFile);
+        linkImage.setImage(icon);
+        linkImage.setScale(100);
+        if (width != null) {
+            linkImgWidth.setText(width);
+            linkImage.setPreviewWidth(Integer.parseInt(width));
+        }
+        if (height != null) {
+            linkImgHeight.setText(height);
+            linkImage.setPreviewHeight(Integer.parseInt(height));
+        }
+    }
+
+    /**
+     * handle an action performed by the component that allows
+     * selection of a link protocol ('link type' on the GUI)
+     */
+    private void handleLinkTypeAction() {
+        final String type = linkType.getSelectedItem().toString();
+        browseAddress.setEnabled(type.equalsIgnoreCase(LINK_TYPE_LOCAL));
+        browseAnchor.setEnabled(type.equalsIgnoreCase(LINK_TYPE_LOCAL) || type.equalsIgnoreCase(LINK_TYPE_RELATIVE));
+        if (type.equalsIgnoreCase(LINK_TYPE_RELATIVE)) {
+            try {
+                final File from = new File(((SHTMLDocument) doc).getBase().getPath());
+                final String toStr = getLinkAddress();
+                final File to = new File(toStr);
+                setLinkAddress(Util.getRelativePath(from, to));
+            }
+            catch (final Exception ex) {
+                Util.errMsg(this, null, ex);
+            }
+        }
+        else if (type.equalsIgnoreCase(LINK_TYPE_LOCAL)) {
+            try {
+                final String absPath = ((SHTMLDocument) doc).getBase().getFile().substring(1);
+                final String relPath = getLinkAddress();
+                setLinkAddress(Util.URL_SEPARATOR + Util.resolveRelativePath(relPath, absPath));
+            }
+            catch (final Exception ex) {
+                Util.errMsg(this, ex.getMessage(), ex);
+            }
+        }
+    }
+
+    /**
+     * Handles an action performed by the button used
+     * to browse anchors of a given file.
+     */
+    private void handleBrowseAnchorAction() {
+        //System.out.println("LinkDialog actionPerformed browseAnchor file=" + getLinkedFile().getAbsolutePath());
+        try {
+            AnchorDialog anchorDialog;
+            final File file = getLinkedFile();
+            final String linkAddrText = linkAddress.getText();
+            if (linkAddrText == null || linkAddrText.length() < 1) {
+                anchorDialog = new AnchorDialog(this, Util.getResourceString("anchorDialogTitle"), doc);
+            }
+            else {
+                anchorDialog = new AnchorDialog(this, Util.getResourceString("anchorDialogTitle"), file.toURI().toURL());
+            }
+            Util.center(this, anchorDialog);
+            anchorDialog.setModal(true);
+            anchorDialog.setVisible(true);
+            if (anchorDialog.getResult() == DialogShell.RESULT_OK) {
+                linkAnchor.setText(anchorDialog.getAnchor());
+            }
+        }
+        catch (final MalformedURLException ex) {
+            Util.errMsg(this, ex.getMessage(), ex);
+        }
+    }
+    /** -------- ActionListener implementation end  (including additional handling methods) ---------- */
+}
diff --git a/src/com/lightdev/app/shtm/ListDialog.java b/src/com/lightdev/app/shtm/ListDialog.java
new file mode 100644
index 0000000..c8aab55
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ListDialog.java
@@ -0,0 +1,81 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Frame;
+
+import javax.swing.text.AttributeSet;
+
+/**
+ * A dialog for showing and manipulating list format.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class ListDialog extends DialogShell {
+    private final ListPanel listPanel;
+
+    public ListDialog(final Frame parent, final String title) {
+        super(parent, title);
+        // create a ListPanel and keep a reference for later use
+        listPanel = new ListPanel();
+        // add to content pane of DialogShell
+        final Container contentPane = super.getContentPane();
+        contentPane.add(listPanel, BorderLayout.CENTER);
+        // cause optimal placement of all elements
+        pack();
+    }
+
+    /**
+     * set the attributes this ListDialog shall represent
+     *
+     * @param a  the set of attributes to display list attributes from
+     */
+    public void setListAttributes(final AttributeSet a) {
+        listPanel.setValue(a);
+    }
+
+    /**
+     * get the list attributes the ListDialog currently is set to.
+     *
+     * @return the set of list attributes this ListDialog currently represents
+     */
+    public AttributeSet getListAttributes() {
+        return listPanel.getValue();
+    }
+
+    /**
+     * get the list tag currently selected in this <code>ListDialog</code>
+     *
+     * @return the list tag currently selected or null, if no list is selected
+     */
+    public String getListTag() {
+        return listPanel.getListTag();
+    }
+}
diff --git a/src/com/lightdev/app/shtm/ListPanel.java b/src/com/lightdev/app/shtm/ListPanel.java
new file mode 100644
index 0000000..5e344d7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ListPanel.java
@@ -0,0 +1,171 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+
+/**
+ * A panel for showing and manipulating list format.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class ListPanel extends JPanel implements AttributeComponent {
+    /** selector for list type */
+    private final AttributeComboBox listType;
+    /** selector for list position */
+    private final AttributeComboBox listPosition;
+    /** list indent selector */
+    private final BoundariesPanel bndPanel;
+    /** list tag from setValue/getValue (UL or OL) */
+    private String listTag;
+
+    /**
+     * construct a new ListPanel
+     */
+    public ListPanel() {
+        setLayout(new BorderLayout());
+        // have a grid bag layout ready to use
+        final GridBagLayout g = new GridBagLayout();
+        final GridBagConstraints c = new GridBagConstraints();
+        // build list format panel
+        final JPanel formatPanel = new JPanel(g);
+        // add label for list type
+        Util.addGridBagComponent(formatPanel, new JLabel(Util.getResourceString("listTypeLabel")), g, c, 0, 0,
+            GridBagConstraints.EAST);
+        // add combo box for list type selection
+        String[] items = new String[] { Util.getResourceString("listTypeNone"),
+                Util.getResourceString("listTypeDecimal"), Util.getResourceString("listTypeLowerRoman"),
+                Util.getResourceString("listTypeUpperRoman"), Util.getResourceString("listTypeLowerAlpha"),
+                Util.getResourceString("listTypeUpperAlpha"), Util.getResourceString("listTypeDisc"),
+                Util.getResourceString("listTypeCircle"), Util.getResourceString("listTypeSquare") };
+        String[] names = new String[] { "none", "decimal", "lower-roman", "upper-roman", "lower-alpha", "upper-alpha",
+                "disc", "circle", "square" };
+        listType = new AttributeComboBox(items, names, CSS.Attribute.LIST_STYLE_TYPE, null);
+        Util.addGridBagComponent(formatPanel, listType, g, c, 1, 0, GridBagConstraints.WEST);
+        // add label for list position
+        Util.addGridBagComponent(formatPanel, new JLabel(Util.getResourceString("listPositionLabel")), g, c, 0, 1,
+            GridBagConstraints.EAST);
+        // add combo box for list postion selection
+        items = new String[] { Util.getResourceString("listPosInside"), Util.getResourceString("listPosOutside") };
+        names = new String[] { "inside", "outside" };
+        listPosition = new AttributeComboBox(items, names, CSS.Attribute.LIST_STYLE_POSITION, null);
+        Util.addGridBagComponent(formatPanel, listPosition, g, c, 1, 1, GridBagConstraints.WEST);
+        // create list boundaries panel
+        bndPanel = new BoundariesPanel(CSS.Attribute.MARGIN);
+        bndPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("listIndentTitle")));
+        // add components to this ListPanel
+        add(formatPanel, BorderLayout.CENTER);
+        add(bndPanel, BorderLayout.SOUTH);
+    }
+
+    /**
+     * get the list tag currently selected in this <code>ListPanel</code>
+     *
+     * @return the list tag currently selected or null, if no list is selected
+     */
+    public String getListTag() {
+        return listTag;
+    }
+
+    /**
+     * translate list types as per CSS attribute list-style-type into list
+     * tag (UL or OL).
+     */
+    private void setTagFromType() {
+        final int index = listType.getSelectedIndex();
+        if (index > 5) {
+            listTag = HTML.Tag.UL.toString();
+        }
+        else if (index > 0) {
+            listTag = HTML.Tag.OL.toString();
+        }
+        else {
+            listTag = null;
+        }
+    }
+
+    /**
+     * set the value of this <code>AttributeComponent</code>
+     *
+     * @param a  the set of attributes possibly having an
+     *          attribute this component can display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(final AttributeSet a) {
+        final Object name = a.getAttribute(javax.swing.text.StyleConstants.NameAttribute);
+        if (name != null) {
+            listTag = name.toString();
+        }
+        listType.setValue(a);
+        listPosition.setValue(a);
+        bndPanel.setValue(a);
+        return true;
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        setTagFromType();
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        set.addAttributes(listType.getValue());
+        set.addAttributes(listPosition.getValue());
+        set.addAttributes(bndPanel.getValue());
+        return set;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            setTagFromType();
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            set.addAttributes(listType.getValue(includeUnchanged));
+            set.addAttributes(listPosition.getValue(includeUnchanged));
+            set.addAttributes(bndPanel.getValue(includeUnchanged));
+            return set;
+        }
+        else {
+            return getValue();
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/ManagePluginsAction.java b/src/com/lightdev/app/shtm/ManagePluginsAction.java
new file mode 100644
index 0000000..9d9807d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ManagePluginsAction.java
@@ -0,0 +1,85 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.util.Enumeration;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JOptionPane;
+import javax.swing.JPopupMenu;
+import javax.swing.SwingUtilities;
+
+/**
+ * Action to invoke a PluginManagerDialog
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class ManagePluginsAction extends AbstractAction implements SHTMLAction {
+    public static final String managePluginsAction = "managePlugins";
+
+    public ManagePluginsAction() {
+        super(managePluginsAction);
+        getProperties();
+        /*putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(
+            KeyEvent.VK_N, KeyEvent.CTRL_MASK));*/
+    }
+
+    public void actionPerformed(final ActionEvent e) {
+        final JPopupMenu menu = (JPopupMenu) ((Component) e.getSource()).getParent();
+        final SHTMLPanelImpl shtmlPanel = (SHTMLPanelImpl) SwingUtilities.getAncestorOfClass(SHTMLPanelImpl.class,
+            menu.getInvoker());
+        final PluginManagerDialog pmd = new PluginManagerDialog(JOptionPane.getFrameForComponent(shtmlPanel),
+            Util.getResourceString("pluginManagerDialogTitle"));
+        Util.center(shtmlPanel, pmd);
+        pmd.setModal(true);
+        pmd.setVisible(true);
+        /** if the user made a selection, apply it to the document */
+        if (pmd.getResult() == DialogShell.RESULT_OK) {
+            shtmlPanel.clearDockPanels();
+            final Enumeration plugins = SHTMLPanelImpl.pluginManager.plugins();
+            SHTMLPlugin pi;
+            while (plugins.hasMoreElements()) {
+                pi = (SHTMLPlugin) plugins.nextElement();
+                shtmlPanel.refreshPluginDisplay(pi);
+            }
+            shtmlPanel.paintComponents(shtmlPanel.getGraphics());
+        }
+        shtmlPanel.adjustDividers();
+        shtmlPanel.updateActions();
+    }
+
+    public void update() {
+    }
+
+    public void getProperties() {
+        SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+    }
+}
diff --git a/src/com/lightdev/app/shtm/MarginPanel.java b/src/com/lightdev/app/shtm/MarginPanel.java
new file mode 100644
index 0000000..99f3101
--- /dev/null
+++ b/src/com/lightdev/app/shtm/MarginPanel.java
@@ -0,0 +1,67 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.GridLayout;
+
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.html.CSS;
+
+/**
+ * Panel to set text margin attributes.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class MarginPanel extends AttributePanel {
+    private final BoundariesPanel margin;
+    private final BoundariesPanel padding;
+
+    public MarginPanel() {
+        super();
+        // margin/padding panel
+        setLayout(new GridLayout(2, 1, 3, 3));
+        // construct margin panel
+        margin = new BoundariesPanel(CSS.Attribute.MARGIN);
+        // set border and title and add margin panel
+        margin
+            .setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util.getResourceString("marginLabel")));
+        this.add(margin);
+        // construct padding panel
+        padding = new BoundariesPanel(CSS.Attribute.PADDING);
+        // set border and title adn add padding panel
+        padding.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("paddingLabel")));
+        this.add(padding);
+    }
+
+    public void reset() {
+        margin.reset();
+        padding.reset();
+    }
+}
diff --git a/src/com/lightdev/app/shtm/NamedObject.java b/src/com/lightdev/app/shtm/NamedObject.java
new file mode 100644
index 0000000..b6365ca
--- /dev/null
+++ b/src/com/lightdev/app/shtm/NamedObject.java
@@ -0,0 +1,66 @@
+/*FreeMind - A Program for creating and viewing Mindmaps
+*Copyright (C) 2000-2006 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitri Polivaev and others.
+*
+*See COPYING for Details
+*
+*This program is free software; you can redistribute it and/or
+*modify it under the terms of the GNU General Public License
+*as published by the Free Software Foundation; either version 2
+*of the License, or (at your option) any later version.
+*
+*This program is distributed in the hope that it will be useful,
+*but WITHOUT ANY WARRANTY; without even the implied warranty of
+*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*GNU General Public License for more details.
+*
+*You should have received a copy of the GNU General Public License
+*along with this program; if not, write to the Free Software
+*Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+/*
+ * Created on 08.05.2005
+ *
+ */
+package com.lightdev.app.shtm;
+
+/**
+ * Utility Class for displaying local object names in GUI components.
+ * 
+ * @author Dimitri Polivaev
+ * 18.01.2007
+ */
+public class NamedObject {
+    private String name;
+    private Object object;
+
+    private NamedObject() {
+    }
+
+    public NamedObject(final Object object, final String name) {
+        this.object = object;
+        this.name = name;
+    }
+
+    static public NamedObject literal(final String literal) {
+        final NamedObject result = new NamedObject();
+        result.object = literal;
+        result.name = literal;
+        return result;
+    }
+
+    public boolean equals(final Object o) {
+        if (o instanceof NamedObject) {
+            final NamedObject ts = (NamedObject) o;
+            return object.equals(ts.object);
+        }
+        return object.equals(o);
+    }
+
+    public String toString() {
+        return name;
+    }
+
+    public Object getObject() {
+        return object;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/ParaStyleDialog.java b/src/com/lightdev/app/shtm/ParaStyleDialog.java
new file mode 100644
index 0000000..25f5314
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ParaStyleDialog.java
@@ -0,0 +1,547 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.StringWriter;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Document;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleContext;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.StyleSheet;
+
+/**
+ * Dialog to set paragraph attributes and to manipulate styles in a
+ * given style sheet.
+ *
+ * <p>In stage 9 this has an additional combo box to select different
+ * element types in MODE_NAMED_STYLES.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class ParaStyleDialog extends DialogShell implements AttributeComponent, ActionListener, ListSelectionListener,
+        ChangeListener {
+    private final String standardStyleName = Util.getResourceString("standardStyleName");
+    /** mode to edit named styles with this dialog */
+    private static int MODE_NAMED_STYLES = 1;
+    /** mode to set a paragraph style with this dialog */
+    private static int MODE_PARAGRAPH_STYLE = 2;
+    /** button to save a named style */
+    private JButton saveStyleBtn;
+    /** button to save a named style under a different name */
+    private JButton saveStyleAsBtn;
+    /** button to delete a named style */
+    private JButton deleteStyleBtn;
+    /** the mode this dialog was created in */
+    private final int mode;
+    /** the AttributeComponents in this dialog */
+    private final Vector components = new Vector();
+    /** the FontPanel for the paragraph font settings */
+    private final FontPanel fp;
+    /** list of styles available in style sheet */
+    private JList styleList;
+    /** style sheet to use in MODE_NAMED_STYLES */
+    private StyleSheet styles;
+    /** the document this dialog is operating on when in MODE_NAMED_STYLES */
+    private final Document doc;
+    /** set of attributes for mapping discrepancies between HTML and Java */
+    private AttributeSet mapSet;
+    /**
+     * panel for setting paragraph styles (needed in the change listener
+     * of the list of named styles)
+     */
+    private final StylePanel sp;
+    /**
+     * panel for setting margins (needed in the change listener
+     * of the list of named styles)
+     */
+    private final MarginPanel mp;
+    /** table to map between HTML tags and 'content types' */
+    static private NamedObject[] cTypes = null;
+    /** selector for content type */
+    private JComboBox cType;
+
+    /**
+     * create a <code>ParaStyleDialog</code> to manipulate
+     * the format of a paragraph
+     *
+     * @param parent  the parent frame of this dialog
+     * @param title  the text to be shown as title for this dialog
+     */
+    public ParaStyleDialog(final Frame parent, final String title) {
+        this(parent, title, null, MODE_PARAGRAPH_STYLE);
+    }
+
+    /**
+     * create a <code>ParaStyleDialog</code> to edit named
+     * styles of a given document
+     *
+     * @param parent  the parent frame of this dialog
+     * @param title the text to be shown as title for this dialog
+     * @param doc  the document having the style sheet to edit named styles from
+     */
+    public ParaStyleDialog(final Frame parent, final String title, final Document doc) {
+        this(parent, title, doc, MODE_NAMED_STYLES);
+    }
+
+    /**
+     * construct a <code>ParaStyleDialog</code>
+     *
+     * @param parent  the parent frame for this dialog
+     * @param title  the text to be shown as title for this dialog
+     * @param mode  the mode this dialog is to be created, one of MODE_NAMED_STYLES or MODE_PARAGRAPH_STYLE
+     */
+    private ParaStyleDialog(final Frame parent, final String title, final Document doc, final int mode) {
+        super(parent, title);
+        JPanel hPanel = null;
+        this.mode = mode;
+        this.doc = doc;
+        // get content pane of DialogShell to add components to
+        final Container contentPane = super.getContentPane();
+        // construct tabbed pane for the various groups of settings
+        final JTabbedPane tp = new JTabbedPane();
+        tp.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
+        // create style panel
+        sp = new StylePanel(StylePanel.TYPE_PARAGRAPH);
+        sp.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util.getResourceString("cellGenTabLabel")));
+        components.add(sp);
+        // create margin panel
+        mp = new MarginPanel();
+        components.add(mp);
+        mp.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("cellMarginTabLabel")));
+        if (mode == MODE_NAMED_STYLES) {
+            styles = ((SHTMLDocument) doc).getStyleSheet();
+            // create a combo box for content type
+            initContentTypes();
+            cType = new JComboBox(cTypes);
+            cType.addActionListener(this);
+            // create a list of styles
+            //Vector styleNames = Util.getStyleNamesForTag(styles, getContentType());
+            //styleNames.insertElementAt(standardStyleName, 0);
+            styleList = new JList(/*new DefaultComboBoxModel(styleNames)*/);
+            updateStyleList();
+            styles.addChangeListener(this);
+            styleList.addListSelectionListener(this);
+            // create a panel to control the styles
+            final JPanel btnPanel = new JPanel(new GridLayout(3, 1, 5, 5));
+            saveStyleBtn = new JButton(Util.getResourceString("saveStyleButtonLabel"));
+            saveStyleBtn.addActionListener(this);
+            saveStyleBtn.setEnabled(false);
+            saveStyleAsBtn = new JButton(Util.getResourceString("saveStyleAsButtonLabel"));
+            saveStyleAsBtn.addActionListener(this);
+            deleteStyleBtn = new JButton(Util.getResourceString("deleteStyleButtonLabel"));
+            deleteStyleBtn.addActionListener(this);
+            deleteStyleBtn.setEnabled(false);
+            btnPanel.add(saveStyleBtn);
+            btnPanel.add(saveStyleAsBtn);
+            btnPanel.add(deleteStyleBtn);
+            // use a helper panel for placement of buttons
+            hPanel = new JPanel(new BorderLayout());
+            hPanel.add(btnPanel, BorderLayout.NORTH);
+            // create named styles panel
+            final JPanel nsPanel = new JPanel(new BorderLayout(5, 5));
+            nsPanel.add(cType, BorderLayout.NORTH);
+            nsPanel.add(new JScrollPane(styleList), BorderLayout.CENTER);
+            nsPanel.add(hPanel, BorderLayout.EAST);
+            nsPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+                .getResourceString("stylePanelLabel")));
+            nsPanel.setVisible(mode == MODE_NAMED_STYLES);
+            // use a helper panel for placement of style and named styles panels
+            hPanel = new JPanel(new BorderLayout());
+            hPanel.add(sp, BorderLayout.NORTH);
+            hPanel.add(nsPanel, BorderLayout.CENTER);
+            okButton.setText(Util.getResourceString("closeLabel"));
+        }
+        else {
+            hPanel = new JPanel(new BorderLayout());
+            hPanel.add(sp, BorderLayout.NORTH);
+        }
+        // create paragraph panel
+        final JPanel paraPanel = new JPanel(new BorderLayout());
+        paraPanel.add(hPanel, BorderLayout.CENTER);
+        paraPanel.add(mp, BorderLayout.EAST);
+        // add paragraph panel to tabbed pane
+        tp.add(Util.getResourceString("paraTabLabel"), paraPanel);
+        // create font panel and add to tabbed pane
+        fp = new FontPanel(true);
+        // add tabbed pane to content pane of dialog
+        contentPane.add(tp, BorderLayout.CENTER);
+        cancelButton.setVisible(mode != MODE_NAMED_STYLES);
+        tp.add(Util.getResourceString("fontTabLabel"), fp);
+        // cause optimal placement of all elements
+        pack();
+    }
+
+    /**
+     * update the list of available styles for the currently
+     * selected tag
+     */
+    private void updateStyleList() {
+        final Vector styleNames = Util.getStyleNamesForTag(styles, getContentType());
+        styleNames.insertElementAt(standardStyleName, 0);
+        styleList.setModel(new DefaultComboBoxModel(styleNames));
+    }
+
+    /**
+     * initialize content types hashtable
+     */
+    private void initContentTypes() {
+        cTypes = new NamedObject[10];
+        int i = 0;
+        cTypes[i++] = new NamedObject(HTML.Tag.P.toString(), Util.getResourceString("cTagNamePara"));
+        cTypes[i++] = new NamedObject(HTML.Tag.H1.toString(), Util.getResourceString("cTagNameHead1"));
+        cTypes[i++] = new NamedObject(HTML.Tag.H2.toString(), Util.getResourceString("cTagNameHead2"));
+        cTypes[i++] = new NamedObject(HTML.Tag.H3.toString(), Util.getResourceString("cTagNameHead3"));
+        cTypes[i++] = new NamedObject(HTML.Tag.H4.toString(), Util.getResourceString("cTagNameHead4"));
+        cTypes[i++] = new NamedObject(HTML.Tag.H5.toString(), Util.getResourceString("cTagNameHead5"));
+        cTypes[i++] = new NamedObject(HTML.Tag.H6.toString(), Util.getResourceString("cTagNameHead6"));
+        cTypes[i++] = new NamedObject(HTML.Tag.A.toString(), Util.getResourceString("cTagNameLink"));
+        cTypes[i++] = new NamedObject(HTML.Tag.UL.toString(), Util.getResourceString("cTagNameUL"));
+        cTypes[i++] = new NamedObject(HTML.Tag.OL.toString(), Util.getResourceString("cTagNameOL"));
+    }
+
+    /**
+     * get the currently selected tag
+     *
+     * @return the tag name currently selected
+     */
+    private String getContentType() {
+        return ((NamedObject) cType.getSelectedItem()).getObject().toString();
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        final SimpleAttributeSet attributes = new SimpleAttributeSet();
+        final Enumeration elements = components.elements();
+        AttributeComponent ac;
+        while (elements.hasMoreElements()) {
+            ac = (AttributeComponent) elements.nextElement();
+            attributes.addAttributes(ac.getValue());
+        }
+        attributes.addAttributes(fp.getAttributes());
+        return attributes;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            final SimpleAttributeSet attributes = new SimpleAttributeSet();
+            final Enumeration elements = components.elements();
+            AttributeComponent ac;
+            while (elements.hasMoreElements()) {
+                ac = (AttributeComponent) elements.nextElement();
+                attributes.addAttributes(ac.getValue(includeUnchanged));
+            }
+            attributes.addAttributes(fp.getAttributes(includeUnchanged));
+            return attributes;
+        }
+        else {
+            return getValue();
+        }
+    }
+
+    /**
+     * set the value of this <code>AttributeComponent</code>
+     *
+     * @param a  the set of attributes possibly having an
+     *          attribute this component can display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(final AttributeSet a) {
+        boolean result = true;
+        /*
+        System.out.println("\r\n");
+        de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
+        hd.listAttributes(a, 4);
+        */
+        final AttributeSet set = Util.resolveAttributes(a);
+        final Enumeration elements = components.elements();
+        AttributeComponent ac;
+        while (elements.hasMoreElements()) {
+            ac = (AttributeComponent) elements.nextElement();
+            if (!ac.setValue(set)) {
+                result = false;
+            }
+        }
+        fp.setAttributes(set);
+        return result;
+    }
+
+    /**
+     * listen to changes of style list,
+     * switch state of save and delete buttons accordingly and
+     * set dialog to the selected style, if any
+     */
+    public void valueChanged(final ListSelectionEvent e) {
+        if (e.getSource().equals(styleList)) {
+            final int selectedStyleNo = styleList.getSelectedIndex();
+            final boolean styleSelected = selectedStyleNo > -1;
+            saveStyleBtn.setEnabled(styleSelected);
+            deleteStyleBtn.setEnabled(styleSelected);
+            if (styleSelected) {
+                // set dialog contents to selected style
+                sp.reset();
+                fp.reset();
+                mp.reset();
+                String styleName;
+                final String className = styleList.getSelectedValue().toString();
+                if (className.equalsIgnoreCase(standardStyleName)) {
+                    styleName = getContentType();
+                }
+                else {
+                    styleName = getContentType() + Util.CLASS_SEPARATOR + className;
+                }
+                //Style style = styles.getStyle(styleName);
+                AttributeSet style = styles.getStyle(styleName);
+                if (style == null) {
+                    style = new SimpleAttributeSet();
+                }
+                final MutableAttributeSet allStyles = (MutableAttributeSet) SHTMLPanelImpl.getMaxAttributes(
+                    ((SHTMLDocument) doc).getCharacterElement(doc.getEndPosition().getOffset()),
+                    ((SHTMLDocument) doc).getStyleSheet());
+                allStyles.addAttributes(style);
+                //mapSet = new AttributeMapper(Util.resolveAttributes(style)).getMappedAttributes(AttributeMapper.toJava);
+                //setValue(style);
+                setValue(allStyles);
+            }
+        }
+    }
+
+    /**
+     * get the style name currently selected in the list of style names
+     *
+     * @return the name of the style currently selected in the
+     * list of style names or null if none is currently selected
+     */
+    private String getSelectedStyleName() {
+        String styleName = null;
+        if (styleList.getSelectedIndex() > -1) {
+            styleName = styleList.getSelectedValue().toString();
+        }
+        return styleName;
+    }
+
+    /**
+     * save the current settings on this <code>ParaStyleDialog</code>
+     * to its associated style sheet under the name currently
+     * selected in the list of named styles.
+     *
+     * <p>This will overwrite the existing style with the current
+     * settings on this dialog.</p>
+     */
+    private void doSaveStyle() {
+        final String styleName = getSelectedStyleName();
+        if (styleName != null) {
+            saveStyleAs(styleName);
+        }
+    }
+
+    /**
+     * save the current settings on this <code>ParaStyleDialog</code>
+     * to its associated style sheet under a name defined by the user.
+     *
+     * <p>This will ask for a name a style shall be saved under. If the name
+     * exists, the user is prompted whether or not it shall be overwritten.
+     * The sytle is saved according to the user's choices.</p>
+     */
+    private void doSaveStyleAs() {
+        String initialName = getSelectedStyleName();
+        if (initialName == null) {
+            initialName = Util.getResourceString("newStyleDefaultName");
+        }
+        final String newStyleName = Util.nameInput(null, initialName, "\\w[\\w ]*", "styleNameInputTitle",
+            "styleNameInputText").trim();
+        if (newStyleName != null) {
+            if (styleNameExists(newStyleName) || newStyleName.equalsIgnoreCase(standardStyleName)) {
+                if (Util.msg(JOptionPane.YES_NO_OPTION, "confirmSaveAs", "fileExistsQuery", newStyleName, " ")) {
+                    saveStyleAs(newStyleName);
+                }
+            }
+            else {
+                saveStyleAs(newStyleName);
+            }
+        }
+    }
+
+    /**
+     * delete the currently selected style name for the
+     * currently selected tag
+     */
+    private void doDeleteStyle() {
+        final String styleName = getSelectedStyleName();
+        if (styleName != null) {
+            if (Util.msg(JOptionPane.YES_NO_OPTION, "confirmDelete", "deleteStyleQuery", styleName, "\r\n\r\n")) {
+                styles.removeStyle(getContentType() + Util.CLASS_SEPARATOR + styleName);
+            }
+        }
+    }
+
+    /**
+     * save a style under a given name
+     *
+     * @param newStyleName  the name the style has to be saved under
+     */
+    private void saveStyleAs(final String newStyleName) {
+        try {
+            String className = getContentType();
+            if (!newStyleName.equalsIgnoreCase(standardStyleName)) {
+                className = className + Util.CLASS_SEPARATOR + newStyleName;
+            }
+            final StringWriter sw = new StringWriter();
+            final CSSWriter cw = new CSSWriter(sw, null);
+            final SimpleAttributeSet a = new SimpleAttributeSet();
+            if (mapSet != null) {
+                a.addAttributes(mapSet);
+            }
+            /*
+            AttributeSet test = getValue(true);
+            de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
+            hd.listAttributes(test, 4);
+            System.out.println(" \r\n");
+            */
+            a.addAttributes(new AttributeMapper(getValue(true)).getMappedAttributes(AttributeMapper.toCSS));
+            // hd.listAttributes(a, 4);
+            cw.writeRule(className, a);
+            final String ruleStr = sw.getBuffer().toString();
+            styles.removeStyle(className);
+            styles.addRule(ruleStr);
+            if (doc != null) {
+                final SHTMLDocument sd = (SHTMLDocument) doc;
+                if (!sd.hasStyleRef()) {
+                    sd.insertStyleRef();
+                }
+            }
+        }
+        catch (final Exception ex) {
+            Util.errMsg(this, ex.getMessage(), ex);
+        }
+    }
+
+    /**
+     * get the style sheet this dialog uses
+     *
+     * @return the used style sheet
+     */
+    public StyleSheet getStyleSheet() {
+        return styles;
+    }
+
+    /**
+     * check whether or not a named style already exists in the style sheet
+     * associated to this dialog
+     *
+     * @param styleName  the name of the style to be looked for
+     *
+     * @return true, if the given style name alread is used in the style sheet,
+     *    false if not
+     */
+    private boolean styleNameExists(final String styleName) {
+        final Vector styleNames = Util.getStyleNamesForTag(styles, getContentType() /*HTML.Tag.P.toString()*/);
+        return (styleNames.indexOf(styleName) > -1);
+    }
+
+    /**
+     * overridden to addd some custom cleanup upon closing of dialog
+     */
+    public void dispose() {
+        if (mode == MODE_NAMED_STYLES) {
+            styles.removeChangeListener(this);
+        }
+        super.dispose();
+    }
+
+    /**
+     * ChangeListener implementation to be used on a style sheet.
+     *
+     * <p>This is used to update the list of named styles whenever
+     * a change was saved to the style sheet.</p>
+     */
+    public void stateChanged(final ChangeEvent e) {
+        final Object src = e.getSource();
+        if (src instanceof StyleContext.NamedStyle) {
+            final Vector styleNames = Util
+                .getStyleNamesForTag((AttributeSet) src, getContentType() /*HTML.Tag.P.toString()*/);
+            styleNames.insertElementAt(standardStyleName, 0);
+            styleList.setModel(new DefaultComboBoxModel(styleNames));
+        }
+    }
+
+    /**
+     * listen to actions and route them accordingly, i.e. react to
+     * buttons save, save as and delete style
+     */
+    public void actionPerformed(final ActionEvent e) {
+        final Object src = e.getSource();
+        if (src.equals(saveStyleBtn)) {
+            doSaveStyle();
+        }
+        else if (src.equals(saveStyleAsBtn)) {
+            doSaveStyleAs();
+        }
+        else if (src.equals(deleteStyleBtn)) {
+            doDeleteStyle();
+        }
+        else if (src.equals(cType)) {
+            // update list of named styles
+            updateStyleList();
+        }
+        else {
+            super.actionPerformed(e);
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/PluginManager.java b/src/com/lightdev/app/shtm/PluginManager.java
new file mode 100644
index 0000000..5f0cbb8
--- /dev/null
+++ b/src/com/lightdev/app/shtm/PluginManager.java
@@ -0,0 +1,246 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Finds and loads plug-ins of application SimplyHTML.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class PluginManager {
+    /** name of sub-package where plug-ins are stored */
+    private final String PLUGIN_PACKAGE = "installed";
+    /** the class loader pointing to all plug-in locations (JARs) */
+    private URLClassLoader loader;
+    /** the class names of all loaded plug-ins */
+    private final Vector pluginClassNames = new Vector();
+    /** the plug-in objects loaded by this <code>PluginManager</code> */
+    private final Hashtable loadedPlugins = new Hashtable();
+    private final Hashtable nameMap = new Hashtable();
+    /** the URLs pointing to the classes in pluginClassNames */
+    private final Vector urls = new Vector();
+    private final SHTMLPanelImpl owner;
+
+    /**
+     * construct a new <code>PluginManager</code> and load
+     * all available plug-ins.
+     */
+    public PluginManager(final SHTMLPanelImpl owner) {
+        this.owner = owner;
+    }
+
+    /**
+     * get all plug-ins loaded by this <code>PluginManager</code>
+     */
+    public Enumeration plugins() {
+        return loadedPlugins.elements();
+    }
+
+    public ClassLoader getPluginLoader() {
+        return loader;
+    }
+
+    /**
+     * get a loaded plug-in by its GUI name.
+     *
+     * @param guiName  the GUI name of this plaug-in
+     *
+     * @return the plug-in having the given GUI name, or null of no plug-in
+     * with that name is present
+     */
+    public SHTMLPlugin pluginForName(final String guiName) {
+        final String intName = (String) nameMap.get(guiName);
+        return (SHTMLPlugin) loadedPlugins.get(intName);
+    }
+
+    public Object[] getPluginNames() {
+        return nameMap.keySet().toArray();
+    }
+
+    /**
+     * load all plug-ins found in the plug-in path
+     */
+    public void loadPlugins() {
+        loadedPlugins.clear();
+        final String pluginPrefix = this.getClass().getPackage().getName() + Util.CLASS_SEPARATOR + PLUGIN_PACKAGE
+                + Util.CLASS_SEPARATOR;
+        findPlugins(pluginPrefix.replace(Util.CLASS_SEPARATOR_CHAR, Util.URL_SEPARATOR_CHAR));
+        final Enumeration cNames = pluginClassNames.elements();
+        Class cl;
+        Object o;
+        SHTMLPlugin p;
+        String intName;
+        while (cNames.hasMoreElements()) {
+            try {
+                final String nextClass = (String) cNames.nextElement();
+                //System.out.println("PluginManager loadPlugins loading " + pluginPrefix + nextClass /* pluginPrefix + (String) cNames.nextElement()*/);
+                cl = loader.loadClass(/*pluginPrefix +*/
+                /*(String) cNames.nextElement()*/pluginPrefix + nextClass);
+                //System.out.println("PluginManager loadPlugins calling newInstance ");
+                o = cl.newInstance();
+                if (o instanceof SHTMLPlugin) {
+                    p = (SHTMLPlugin) o;
+                    p.initPlugin(owner, null, null, null);
+                    //p.setOwner(owner);
+                    //p.initPluginActions();
+                    intName = p.getInternalName();
+                    loadedPlugins.put(intName, o);
+                    nameMap.put(p.getGUIName(), intName);
+                }
+            }
+            catch (final Exception e) {
+                Util.errMsg(null, this.getClass().getName() + ".loadPlugins: " + e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * get a class loader for a given set of URLs
+     * specifying one or more class paths
+     *
+     * @param urls  set of URLs specifying the class path(s)
+     *
+     * @return  the class loader
+     */
+    private URLClassLoader createLoader(final Vector urls) {
+        final URL[] urlArray = new URL[urls.size()];
+        for (int i = 0; i < urls.size(); i++) {
+            urlArray[i] = (URL) urls.elementAt(i);
+            //System.out.println("urlArray[" + i + "]=" + urlArray[i]);
+        }
+        return new URLClassLoader(urlArray, this.getClass().getClassLoader());
+    }
+
+    /**
+     * find plug-ins by looking for JARs inside a
+     * given path and create a class loader for them.
+     *
+     * <p>JARs are searched in sub-package .plugin.installed
+     * of the package this class resides in.</p>
+     *
+     * <p>On return of this method fields <code>loader</code> and
+     * <code>pluginClassNames</code> are initialized and
+     * filled accordingly.</p>
+     *
+     * @param pluginPath  the path to look for plug-in JAR files, e.g.
+     * com/lightdev/app/shtm/plugin/installed/
+     */
+    private void findPlugins(final String pluginPath) {
+        final String appPath = Util.getClassFilePath(this.getClass());
+        String filePath;
+        if (appPath.indexOf(":") < 0) {
+            filePath = "/" + appPath;
+        }
+        else {
+            filePath = appPath;
+        }
+        //System.out.println("PluginManager.findPlugins appPath=" + appPath + ", filePath=" + filePath);
+        pluginClassNames.clear();
+        urls.clear();
+        String fName;
+        try {
+            final File plugindir = new File(filePath);//new URI(Util.FILE_PREFIX + Util.URL_SEPARATOR + appPath));
+            if (plugindir != null) {
+                final File[] content = plugindir.listFiles();
+                if (content != null) {
+                    for (int i = 0; i < content.length; i++) {
+                        if (content[i].isFile()) {
+                            fName = content[i].getName();
+                            //System.out.println("PluginManager.findPlugins fName=" + fName);
+                            if (fName.toLowerCase().endsWith("jhall.jar")) {
+                                /*System.out.println("PluginManager.findPlugins adding URL " + Util.FILE_PREFIX +
+                                                  Util.URL_SEPARATOR + appPath + fName);*/
+                                urls.addElement(new URL(Util.FILE_PREFIX + Util.URL_SEPARATOR + appPath + fName));
+                            }
+                            if (fName.toLowerCase().endsWith("simplyhtml.jar")) {
+                                /*System.out.println("PluginManager.findPlugins adding URL " + Util.FILE_PREFIX +
+                                                  Util.URL_SEPARATOR + appPath + fName);*/
+                                urls.addElement(new URL(Util.FILE_PREFIX + Util.URL_SEPARATOR + appPath + fName));
+                            }
+                            else if (fName.endsWith(Util.JAR_EXTENSION)) {
+                                readJar(appPath, pluginPath, content[i], fName);
+                            }
+                        }
+                    }
+                }
+            }
+            loader = createLoader(urls);
+        }
+        catch (final Exception e) {
+            Util.errMsg(null, this.getClass().getName() + ".findPlugins: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * read a Java archive (JAR) file and look for classes within
+     * a given package path inside the JAR file. Store class names and
+     * their URLS for later use.
+     *
+     * <p>Some of the parameters required below could be extracted from
+     * others passed to this method but as previous methods already determined
+     * respective paramaters, it is faster to pass the existing values as
+     * parameters than to re-build the values locally.</p>
+     *
+     * @param filePath  the absolute path pointing to the JAR file, e.g.
+     *   file:/C:/Programs/SimplyHTML/
+     * @param pluginPath  the path inside filePath pointing to potential plug-ins
+     * @param jarFile  the file object referring to the JAR file to read
+     * @param fileName  the name of the JAR file
+     */
+    private void readJar(final String filePath, final String pluginPath, final File jarFile, final String fileName) {
+        try {
+            final Enumeration jarEntries = new JarFile(jarFile).entries();
+            JarEntry je;
+            String jeName;
+            while (jarEntries.hasMoreElements()) {
+                je = (JarEntry) jarEntries.nextElement();
+                jeName = je.getName();
+                if (jeName.startsWith(pluginPath) && !je.isDirectory() && jeName.endsWith(Util.CLASS_EXT)) {
+                    /*System.out.println("PluginManager.readJar adding URL " + Util.FILE_PREFIX +
+                                      Util.URL_SEPARATOR + filePath + fileName);*/
+                    urls.addElement(new URL(Util.FILE_PREFIX + Util.URL_SEPARATOR + filePath + fileName));
+                    pluginClassNames.addElement(jeName.substring(pluginPath.length(),
+                        jeName.indexOf(Util.CLASS_SEPARATOR)));
+                }
+            }
+        }
+        catch (final Exception e) {
+            /*Util.errMsg(null, this.getClass().getName() + ".readJar: " +
+                        e.getMessage(), e);*/
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/PluginManagerDialog.java b/src/com/lightdev/app/shtm/PluginManagerDialog.java
new file mode 100644
index 0000000..38346fd
--- /dev/null
+++ b/src/com/lightdev/app/shtm/PluginManagerDialog.java
@@ -0,0 +1,206 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+/**
+ * User interface for changing plug-in settings.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class PluginManagerDialog extends DialogShell implements ListSelectionListener, ActionListener {
+    /** combo box for selecting the dock location */
+    private final JComboBox dockLocation;
+    /** indicates if we can ignore changes (when happenig programmatically */
+    private boolean ignoreChanges = false;
+    /** the list with available plug-ins */
+    private final JList pluginNames;
+    /** constant for activation button label */
+    private final String activateName = Util.getResourceString("activatePlugin");
+    /** constant for deactivation button label */
+    private final String deactivateName = Util.getResourceString("deactivatePlugin");
+    /** button to toggle plug-in activation state */
+    private final JButton toggleActivationButton;
+    /** checkbox to toggle plug-in activation state */
+    private final JCheckBox toggleActivationCheckbox;
+
+    /**
+     * construct a new <code>PluginManagerDialog</code>
+     *
+     * @param parent  the parent frame
+     * @param title  the title of the dialog
+     */
+    public PluginManagerDialog(final Frame parent, final String title) {
+        super(parent, title);
+        final Container contentPane = super.getContentPane();
+        okButton.setText(Util.getResourceString("close"));
+        cancelButton.setVisible(false);
+        GridBagLayout g;
+        final GridBagConstraints c = new GridBagConstraints();
+        /** create panel to show and select plug-ins */
+        final JPanel pluginPanel = new JPanel(new BorderLayout());
+        pluginPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("pluginPanelTitle")));
+        //pluginPanel.setMinimumSize(new Dimension(400, 400));
+        SHTMLPanelImpl.pluginManager.plugins();
+        pluginNames = new JList(SHTMLPanelImpl.pluginManager.getPluginNames());
+        pluginNames.addListSelectionListener(this);
+        pluginNames.setMinimumSize(new Dimension(250, 400));
+        pluginNames.setPreferredSize(new Dimension(250, 400));
+        pluginPanel.add(new JScrollPane(pluginNames), BorderLayout.CENTER);
+        /** create panel for actins on loaded plug-ins */
+        final JPanel actionPanel = new JPanel();
+        toggleActivationButton = new JButton(activateName);
+        toggleActivationButton.setEnabled(false);
+        toggleActivationButton.addActionListener(this);
+        actionPanel.add(toggleActivationButton);
+        pluginPanel.add(actionPanel, BorderLayout.SOUTH);
+        /** create panel to edit settings for a plug-in */
+        g = new GridBagLayout();
+        final JPanel pluginSettingsPanel = new JPanel(g);
+        toggleActivationCheckbox = new JCheckBox("togglePluginActivationCheckbox");
+        toggleActivationCheckbox.setEnabled(false);
+        toggleActivationCheckbox.addActionListener(this);
+        Util.addGridBagComponent(pluginSettingsPanel, toggleActivationCheckbox, g, c, 0, 0, GridBagConstraints.WEST);
+        Util.addGridBagComponent(pluginSettingsPanel, new JLabel(Util.getResourceString("dockLocationLabel")), g, c, 0,
+            1, GridBagConstraints.EAST);
+        final String[] locations = { Util.getResourceString("pluginDockLocationNone"),
+                Util.getResourceString("pluginDockLocationTop"), Util.getResourceString("pluginDockLocationRight"),
+                Util.getResourceString("pluginDockLocationBottom"), Util.getResourceString("pluginDockLocationLeft"), };
+        dockLocation = new JComboBox(locations);
+        dockLocation.setEnabled(false);
+        dockLocation.addActionListener(this);
+        Util.addGridBagComponent(pluginSettingsPanel, dockLocation, g, c, 1, 1, GridBagConstraints.WEST);
+        /** add components to dialog */
+        contentPane.add(pluginPanel, BorderLayout.WEST);
+        final JPanel centerPanel = new JPanel(new BorderLayout());
+        final JPanel centerWestPanel = new JPanel(new BorderLayout());
+        centerWestPanel.add(pluginSettingsPanel, BorderLayout.NORTH);
+        centerPanel.add(centerWestPanel, BorderLayout.WEST);
+        centerPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("pluginSettingsPanelTitle")));
+        //centerPanel.setPreferredSize(new Dimension(200,400));
+        contentPane.add(centerPanel, BorderLayout.CENTER);
+        pack();
+    }
+
+    /**
+     * ListSelectionListener implementation
+     */
+    public void valueChanged(final ListSelectionEvent e) {
+        ignoreChanges = true;
+        if (pluginNames.getSelectedIndex() > -1) {
+            final SHTMLPlugin p = getSelectedPlugin();
+            final boolean active = p.isActive();
+            updateActivationButtonText(active);
+            toggleActivationButton.setEnabled(true);
+            toggleActivationCheckbox.setEnabled(true);
+            toggleActivationCheckbox.setSelected(active);
+            dockLocation.setSelectedIndex(p.getDockLocation());
+            dockLocation.setEnabled(true);
+        }
+        else {
+            toggleActivationButton.setEnabled(false);
+            toggleActivationCheckbox.setEnabled(false);
+            dockLocation.setEnabled(false);
+        }
+        ignoreChanges = false;
+    }
+
+    /**
+     * helper method for getting the currently selected
+     * line in the list of plug-ins
+     */
+    private SHTMLPlugin getSelectedPlugin() {
+        final String name = (String) pluginNames.getSelectedValue();
+        return SHTMLPanelImpl.pluginManager.pluginForName(name);
+    }
+
+    /**
+     * helper method to toggle the button text between
+     * activate and deactivate
+     */
+    private void updateActivationButtonText(final boolean active) {
+        if (active) {
+            toggleActivationButton.setText(deactivateName);
+        }
+        else {
+            toggleActivationButton.setText(activateName);
+        }
+    }
+
+    /**
+     * ActionListener implementation
+     */
+    public void actionPerformed(final ActionEvent e) {
+        final Object source = e.getSource();
+        if ((pluginNames.getSelectedIndex() > -1) && (!ignoreChanges)) {
+            ignoreChanges = true;
+            final SHTMLPlugin p = getSelectedPlugin();
+            if (source.equals(toggleActivationButton)) {
+                p.setStatus(!p.isActive());
+            }
+            else if (source.equals(toggleActivationCheckbox)) {
+                p.setStatus(!p.isActive());
+            }
+            else if (source.equals(dockLocation)) {
+                p.setDockLocation(dockLocation.getSelectedIndex());
+            }
+            else {
+                super.actionPerformed(e);
+            }
+            final boolean active = p.isActive();
+            toggleActivationCheckbox.setSelected(active);
+            updateActivationButtonText(active);
+            ignoreChanges = false;
+        }
+        else {
+            super.actionPerformed(e);
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/PrefsDialog.java b/src/com/lightdev/app/shtm/PrefsDialog.java
new file mode 100644
index 0000000..35c959c
--- /dev/null
+++ b/src/com/lightdev/app/shtm/PrefsDialog.java
@@ -0,0 +1,206 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.prefs.Preferences;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.ListCellRenderer;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+/**
+ * Dialog to set user preferences for application SimplyHTML.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class PrefsDialog extends DialogShell implements ActionListener {
+    /** the look and feels avaliable in the system */
+    private UIManager.LookAndFeelInfo[] lfinfo;
+    /** reference for user preferences for this class */
+    protected Preferences prefs = Preferences.userNodeForPackage(getClass());
+    /** constant for dock location setting in preferences file */
+    public static final String PREFSID_LOOK_AND_FEEL = "Laf";
+    public static final String PREFS_USE_STD_STYLE_SHEET = "use_std_styles";
+    public static final String PREFS_DEFAULT_PASTE_MODE ="default_paste_mode";
+    private final String lafName = UIManager.getLookAndFeel().getName();
+    private final JComboBox lafCombo;
+    private final JCheckBox useStdStyleSheet;
+    private final JComboBox pasteModeCombo;
+    /** the help id for this dialog */
+    private static final String helpTopicId = "item167";
+    private final List<SHTMLPrefsChangeListener> prefChangeListeners = new LinkedList<SHTMLPrefsChangeListener>();
+
+    public PrefsDialog(final Frame parent, final String title) {   	
+        super(parent, title, helpTopicId);
+        // have a grid bag layout ready to use
+        final GridBagLayout g = new GridBagLayout();
+        final GridBagConstraints c = new GridBagConstraints();
+        final JPanel layoutPanel = new JPanel(g);
+        // build a panel for preferences related to the application
+        final JPanel appPrefsPanel = new JPanel(g);
+        Util.addGridBagComponent(appPrefsPanel, new JLabel(Util.getResourceString("prfLafLabel")), g, c, 0, 0,
+            GridBagConstraints.EAST);
+        
+        lafCombo = new JComboBox();
+        initLfComboBox();
+        Util.addGridBagComponent(appPrefsPanel, lafCombo, g, c, 1, 0, GridBagConstraints.EAST);
+        
+        pasteModeCombo = new JComboBox();
+        initPasteModeComboBox();
+        Util.addGridBagComponent(appPrefsPanel, new JLabel(Util.getResourceString("prefsPasteModeLabel")), g, c, 0, 1,
+                GridBagConstraints.EAST);
+        Util.addGridBagComponent(appPrefsPanel, pasteModeCombo, g, c, 1, 1, GridBagConstraints.EAST);
+        
+        // build a panel for preferences related to documents
+        /*
+        JPanel docPrefsPanel = new JPanel(g);
+        Util.addGridBagComponent(docPrefsPanel,
+                                 new JCheckBox(
+                                 FrmMain.dynRes.getResourceString(
+                                 FrmMain.resources, "prfShareDocResourcesLabel")),
+                                 g, c, 0, 1,
+                                 GridBagConstraints.EAST);
+        */
+        Util.addGridBagComponent(layoutPanel, appPrefsPanel, g, c, 0, 0, GridBagConstraints.WEST);
+        // add option for standard stlye sheet
+        useStdStyleSheet = new JCheckBox(Util.getResourceString("linkDefaultStyleSheetLabel"));
+        final boolean useStyle = prefs.getBoolean(PrefsDialog.PREFS_USE_STD_STYLE_SHEET, false);
+        useStdStyleSheet.setSelected(useStyle);
+        Util.addGridBagComponent(layoutPanel, useStdStyleSheet, g, c, 0, 2, GridBagConstraints.WEST);
+                
+        // add to content pane of DialogShell
+        final Container contentPane = super.getContentPane();
+        contentPane.add(layoutPanel, BorderLayout.CENTER);
+        //contentPane.add(appPrefsPanel, BorderLayout.NORTH);
+        //contentPane.add(docPrefsPanel, BorderLayout.CENTER);
+        // cause optimal placement of all elements
+        pack();
+    }
+    
+    public void addPrefChangeListener(final SHTMLPrefsChangeListener listener)
+    {
+    	prefChangeListeners.add(listener);
+    }
+    
+    public void removePrefChangeListener(final SHTMLPrefsChangeListener listener)
+    {
+    	prefChangeListeners.remove(listener);
+    }
+
+    private void initLfComboBox() {
+        lfinfo = UIManager.getInstalledLookAndFeels();
+        final int count = lfinfo.length;
+        final String[] lfNames = new String[count];
+        for (int i = 0; i < count; i++) {
+            lfNames[i] = lfinfo[i].getName();
+        }
+        lafCombo.setModel(new DefaultComboBoxModel(lfNames));
+        lafCombo.setSelectedItem(lafName);
+    }
+    
+    private void initPasteModeComboBox()
+    {
+    	pasteModeCombo.setModel(new DefaultComboBoxModel(SHTMLEditorPane.PasteMode.values()));
+    	pasteModeCombo.setSelectedItem(
+    			SHTMLEditorPane.PasteMode.valueOf(SHTMLEditorPane.PasteMode.class, prefs.get(PREFS_DEFAULT_PASTE_MODE, SHTMLEditorPane.PasteMode.PASTE_HTML.name())));
+    	pasteModeCombo.setRenderer(new ListCellRenderer() {
+
+			public Component getListCellRendererComponent(JList list,
+					Object value, int index, boolean isSelected,
+					boolean cellHasFocus) 
+			{
+				switch ((SHTMLEditorPane.PasteMode)value)
+				{
+				case PASTE_HTML:
+					return new JLabel(Util.getResourceString("pasteModeHTML"));
+				case PASTE_PLAIN_TEXT:
+					return new JLabel(Util.getResourceString("pasteModePlainText"));
+				default:
+					throw new AssertionError();
+				}
+			}
+    		
+    	});
+    }
+
+    /**
+     * implements the ActionListener interface to be notified of
+     * clicks onto the ok and cancel button.
+     */
+    public void actionPerformed(final ActionEvent e) {
+        final Component src = (Component) e.getSource();
+        if (src == okButton) {
+            savePrefs(src);
+        }
+        super.actionPerformed(e);
+    }
+
+    private void savePrefs(final Component src) {
+        try {
+            final String newLaf = lfinfo[lafCombo.getSelectedIndex()].getClassName();
+            if (!lafName.equalsIgnoreCase(newLaf)) {
+                prefs.put(PREFSID_LOOK_AND_FEEL, newLaf);
+                UIManager.setLookAndFeel(newLaf);
+                SwingUtilities.updateComponentTreeUI(JOptionPane.getFrameForComponent(src));
+            }
+            boolean oldStyleSheetPref = prefs.getBoolean(PREFS_USE_STD_STYLE_SHEET, false);
+            prefs.putBoolean(PREFS_USE_STD_STYLE_SHEET, useStdStyleSheet.isSelected());
+            String oldDefaultPasteMode = prefs.get(PREFS_DEFAULT_PASTE_MODE, SHTMLEditorPane.PasteMode.PASTE_HTML.name());
+            prefs.put(PREFS_DEFAULT_PASTE_MODE, ((SHTMLEditorPane.PasteMode)pasteModeCombo.getSelectedItem()).name());
+
+            for (SHTMLPrefsChangeListener listener: prefChangeListeners)
+            {
+            	listener.shtmlPrefChanged(PREFS_USE_STD_STYLE_SHEET, new Boolean(useStdStyleSheet.isSelected()).toString(),
+            			new Boolean(oldStyleSheetPref).toString());
+            
+            	listener.shtmlPrefChanged(PREFS_DEFAULT_PASTE_MODE, prefs.get(PREFS_DEFAULT_PASTE_MODE, null),
+            			oldDefaultPasteMode);
+            }
+        }
+        catch (final Exception ex) {
+            Util.errMsg(this, ex.getMessage(), ex);
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/Remover.java b/src/com/lightdev/app/shtm/Remover.java
new file mode 100644
index 0000000..e2fc9e1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/Remover.java
@@ -0,0 +1,110 @@
+package com.lightdev.app.shtm;
+
+import java.util.Locale;
+
+class Remover {
+	final private String searchedText;
+	private String searchedSubstring;
+	private int begin;
+	private int end;
+	private int removedCharacterNumber;
+	private String processedText;
+	
+	public String getProcessedText() {
+		return processedText;
+	}
+	public Remover(String text) {
+		super();
+		this.processedText = text;
+		this.searchedText = text.toLowerCase(Locale.ENGLISH);
+		begin = end = removedCharacterNumber = 0;
+	}
+	public int getBegin() {
+		return begin;
+	}
+	public int getEnd() {
+		return end;
+	}
+	
+	private String createSearchedSubstring(final String substring) {
+		return "<" + substring.toLowerCase(Locale.ENGLISH);
+	}
+	
+	public boolean findFirst(){
+		begin = removedCharacterNumber;
+		return findNext();
+	}
+	
+	public boolean findNext(){
+		begin = searchedText.indexOf(searchedSubstring, begin);
+		return findEndOfElement();
+	}
+
+	public boolean findLast(){
+		begin = searchedText.lastIndexOf(searchedSubstring);
+		return findEndOfElement();
+	}
+	
+	private boolean findEndOfElement() {
+		if(begin == -1)
+		{
+			end = -1;
+			return false;
+		}
+		end = searchedText.indexOf('>', begin + searchedSubstring.length());
+		if(end == -1){
+			begin = -1;
+			return false;
+		}
+		end++;
+		return true;
+	}
+	
+	public int getWhiteSpaceBefore(){
+		if(begin <= 0)
+			return begin;
+		for(int i = begin - 1; i > 0; i--){
+			if(! Character.isWhitespace(searchedText.charAt(i)))
+				return i + 1;
+		}
+		return 0;
+	}
+	
+	public int getWhiteSpaceAfter(){
+		if(end == -1)
+			return -1;
+		for(int i = end + 1; i < searchedText.length(); i++){
+			if(! Character.isWhitespace(searchedText.charAt(i)))
+				return i;
+		}
+		return searchedText.length();
+	}
+	
+	public Remover removeFirstAndBefore(String element){
+		searchedSubstring = createSearchedSubstring(element);
+		if(findFirst()){
+			final int lastIndex = getWhiteSpaceAfter() - removedCharacterNumber;
+			processedText = processedText.substring(lastIndex);
+			removedCharacterNumber += lastIndex;
+		}
+		return this;
+	}
+	
+	public Remover removeLastAndAfter(String element){
+		searchedSubstring = createSearchedSubstring(element);
+		if(findLast()){
+			final int firstIndex = getWhiteSpaceBefore() - removedCharacterNumber;
+			processedText = processedText.substring(0, firstIndex);
+		}
+		return this;
+	}
+	
+	static public void main(String[] argv){
+		String text = "\n\t<body> 1 </body>";
+		final Remover removeFirstAndBefore = new Remover(text).removeFirstAndBefore("body");
+		String removeLastAndAfter = removeFirstAndBefore.removeLastAndAfter("/body").getProcessedText();
+		System.out.println ('"' + removeLastAndAfter + '"');
+		// assert removeLastAndAfter.equals("1");
+	}
+
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLAction.java b/src/com/lightdev/app/shtm/SHTMLAction.java
new file mode 100644
index 0000000..ec925f1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLAction.java
@@ -0,0 +1,50 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import javax.swing.Action;
+
+/**
+ * Adds methods to the <code>javax.swing.Action</code> interface, needed
+ * by Application SimplyHTML.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ *
+ * @see javax.swing.Action
+ */
+public interface SHTMLAction extends Action {
+    /** update the action's state */
+    public void update();
+
+    /**
+     * this method should be called from the constructor
+     * of each SHTMLAction and can be used to get
+     * action properties from a resource file
+     */
+    public void getProperties();
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLDocument.java b/src/com/lightdev/app/shtm/SHTMLDocument.java
new file mode 100644
index 0000000..23b1074
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLDocument.java
@@ -0,0 +1,746 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Color;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.text.AbstractDocument;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.GapContent;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTML.Tag;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.StyleSheet;
+import javax.swing.undo.CompoundEdit;
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * Extends <code>HTMLDocument</code> by a custom reader which supports
+ * the SPAN tag.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+public class SHTMLDocument extends HTMLDocument {
+    public static final String SUFFIX = " ";
+    private static Set paragraphElements;
+    private CompoundEdit compoundEdit;
+    private int compoundEditDepth;
+    private boolean inSetParagraphAttributes = false;
+    private boolean baseDirChecked = false;
+    private final boolean keepSpanTag = Util.preferenceIsTrue("keepSpanTag");
+
+    /**
+     * Constructs an SHTMLDocument.
+     */
+    public SHTMLDocument() {
+        this(new GapContent(BUFFER_SIZE_DEFAULT), new StyleSheet());
+    }
+
+    /**
+     * Constructs an SHTMLDocument with the default content
+     * storage implementation and the given style/attribute
+     * storage mechanism.
+     *
+     * @param styles  the styles
+     */
+    public SHTMLDocument(final StyleSheet styles) {
+        this(new GapContent(BUFFER_SIZE_DEFAULT), styles);
+    }
+
+    /**
+     * Constructs an SHTMLDocument with the given content
+     * storage implementation and the given style/attribute
+     * storage mechanism.
+     *
+     * @param c  the container for the content
+     * @param styles the styles
+     */
+    public SHTMLDocument(final Content c, final StyleSheet styles) {
+        super(c, styles);
+        compoundEdit = null;
+    }
+
+    /**
+     * apply a set of attributes to a given document element
+     *
+     * @param e  the element to apply attributes to
+     * @param a  the set of attributes to apply
+     */
+    public void addAttributes(final Element e, final AttributeSet a) {
+        if ((e != null) && (a != null)) {
+            try {
+                writeLock();
+                //System.out.println("SHTMLDocument addAttributes e=" + e);
+                //System.out.println("SHTMLDocument addAttributes a=" + a);
+                final int start = e.getStartOffset();
+                final DefaultDocumentEvent changes = new DefaultDocumentEvent(start, e.getEndOffset() - start,
+                    DocumentEvent.EventType.CHANGE);
+                final AttributeSet sCopy = a.copyAttributes();
+                final MutableAttributeSet attr = (MutableAttributeSet) e.getAttributes();
+                changes.addEdit(new AttributeUndoableEdit(e, sCopy, false));
+                attr.addAttributes(a);
+                changes.end();
+                fireChangedUpdate(changes);
+                fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
+            }
+            finally {
+                writeUnlock();
+            }
+        }
+    }
+
+    /**
+     * Removes a consecutive group of child elements.
+     *
+     * @param element  the parent element to remove child elements from
+     * @param index  the index of the first child element to remove
+     * @param count  the number of child elements to remove
+     */
+    public void removeElements(final Element element, final int index, final int count) throws BadLocationException {
+        writeLock();
+        final int start = element.getElement(index).getStartOffset();
+        final int end = element.getElement(index + count - 1).getEndOffset();
+        try {
+            final Element[] removed = new Element[count];
+            final Element[] added = new Element[0];
+            for (int counter = 0; counter < count; counter++) {
+                removed[counter] = element.getElement(counter + index);
+            }
+            final DefaultDocumentEvent defaultDocumentEvent = new DefaultDocumentEvent(start, end - start,
+                DocumentEvent.EventType.REMOVE);
+            ((AbstractDocument.BranchElement) element).replace(index, removed.length, added);
+            defaultDocumentEvent.addEdit(new ElementEdit(element, index, removed, added));
+            final UndoableEdit undoableEdit = getContent().remove(start, end - start);
+            if (undoableEdit != null) {
+                defaultDocumentEvent.addEdit(undoableEdit);
+            }
+            postRemoveUpdate(defaultDocumentEvent);
+            defaultDocumentEvent.end();
+            fireRemoveUpdate(defaultDocumentEvent);
+            if (undoableEdit != null) {
+                fireUndoableEditUpdate(new UndoableEditEvent(this, defaultDocumentEvent));
+            }
+        }
+        finally {
+            writeUnlock();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLDocument#setOuterHTML(javax.swing.text.Element, java.lang.String)
+     */
+    public void setOuterHTML(final Element paragraphElement, final String htmlText) throws BadLocationException,
+            IOException {
+        try {
+            startCompoundEdit();
+            if (paragraphElement.getName().equalsIgnoreCase("p-implied")) {
+                //What has to be replaced is the HTML of the parent of this implied element.
+                final Element parentElement = paragraphElement.getParentElement();
+                final SHTMLWriter writer = new SHTMLWriter(this);
+                final int indexOfElement = parentElement.getElementIndex(paragraphElement.getStartOffset());
+                writer.writeStartTag(parentElement);
+                for (int i = 0; i < indexOfElement; i++) {
+                    writer.write(parentElement.getElement(i));
+                }
+                writer.write(htmlText);
+                for (int i = indexOfElement + 1; i < parentElement.getElementCount(); i++) {
+                    writer.write(parentElement.getElement(i));
+                }
+                writer.writeEndTag(parentElement);
+                super.setOuterHTML(parentElement, writer.toString());
+            }
+            else {
+                super.setOuterHTML(paragraphElement, htmlText);
+            }
+        }
+        finally {
+            endCompoundEdit();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLDocument#insertAfterEnd(javax.swing.text.Element, java.lang.String)
+     */
+    public void insertAfterEnd(final Element elem, final String htmlText) throws BadLocationException, IOException {
+        try {
+            startCompoundEdit();
+            super.insertAfterEnd(elem, htmlText);
+        }
+        finally {
+            endCompoundEdit();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLDocument#insertAfterStart(javax.swing.text.Element, java.lang.String)
+     */
+    public void insertAfterStart(final Element elem, final String htmlText) throws BadLocationException, IOException {
+        try {
+            startCompoundEdit();
+            super.insertAfterStart(elem, htmlText);
+        }
+        finally {
+            endCompoundEdit();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLDocument#insertBeforeEnd(javax.swing.text.Element, java.lang.String)
+     */
+    public void insertBeforeEnd(final Element elem, final String htmlText) throws BadLocationException, IOException {
+        try {
+            startCompoundEdit();
+            super.insertBeforeEnd(elem, htmlText);
+        }
+        finally {
+            endCompoundEdit();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLDocument#insertBeforeStart(javax.swing.text.Element, java.lang.String)
+     */
+    public void insertBeforeStart(final Element elem, final String htmlText) throws BadLocationException, IOException {
+        try {
+            startCompoundEdit();
+            super.insertBeforeStart(elem, htmlText);
+        }
+        finally {
+            endCompoundEdit();
+        }
+    }
+
+    /** */
+    public void replaceHTML(final Element firstElement, final int number, final String htmlText)
+            throws BadLocationException, IOException {
+        if (number > 1) {
+            if (firstElement != null && firstElement.getParentElement() != null && htmlText != null) {
+                final int start = firstElement.getStartOffset();
+                final Element parent = firstElement.getParentElement();
+                final int removeIndex = parent.getElementIndex(start);
+                try {
+                    startCompoundEdit();
+                    removeElements(parent, removeIndex, number - 1);
+                    setOuterHTML(parent.getElement(removeIndex), htmlText);
+                }
+                finally {
+                    endCompoundEdit();
+                }
+            }
+        }
+        else if (number == 1) {
+            setOuterHTML(firstElement, htmlText);
+        }
+    }
+
+    public void startCompoundEdit() {
+        compoundEditDepth++;
+    }
+
+    public void endCompoundEdit() {
+        if (compoundEditDepth != 0) {
+            compoundEditDepth--;
+            if (compoundEditDepth == 0 && compoundEdit != null) {
+                compoundEdit.end();
+                super.fireUndoableEditUpdate(new UndoableEditEvent(this, compoundEdit));
+                compoundEdit = null;
+            }
+        }
+    }
+
+    protected void fireUndoableEditUpdate(final UndoableEditEvent e) {
+        if (compoundEditDepth == 0) {
+            super.fireUndoableEditUpdate(e);
+        }
+        else {
+            if (compoundEdit == null) {
+                compoundEdit = new CompoundEdit();;
+            }
+            compoundEdit.addEdit(e.getEdit());
+        }
+    }
+
+    /* ------------------ custom document title handling start -------------------- */
+    /**
+     * set the title of this SHTMLDocument
+     *
+     * @param title  the title this document shall have
+     */
+    public void setDocumentTitle(final String title) {
+        try {
+            final String titleHTML = "<title></title>";
+            final Element defaultRoot = getDefaultRootElement();
+            final Element head = Util.findElementDown(HTML.Tag.HEAD.toString(), defaultRoot);
+            if (head != null) {
+                final Element pImpl = Util.findElementDown(HTML.Tag.IMPLIED.toString(), head);
+                if (pImpl != null) {
+                    final Element tElem = Util.findElementDown(HTML.Tag.TITLE.toString(), pImpl);
+                    if (tElem == null) {
+                        insertBeforeEnd(pImpl, titleHTML);
+                    }
+                }
+            }
+            else {
+                final Element body = Util.findElementDown(HTML.Tag.BODY.toString(), defaultRoot);
+                insertBeforeStart(body, "<head>" + titleHTML + "</head>");
+            }
+            putProperty(Document.TitleProperty, title);
+        }
+        catch (final Exception e) {
+            Util.errMsg(null, "An exception occurred while trying to insert the title", e);
+        }
+    }
+
+    /**
+     * get the title of this SHTMLDocument
+     *
+     * @return  the title of this document or null if none was set so far
+     */
+    public String getDocumentTitle() {
+        final Object title = getProperty(Document.TitleProperty);
+        if (title != null) {
+            return title.toString();
+        }
+        else {
+            return null;
+        }
+    }
+
+    /* ------------------ custom document title handling end -------------------- */
+    /* ------------------ custom style sheet reference handling start -------------------- */
+    /**
+     * insert a style sheet reference into the head of this SHTMLDocument
+     */
+    public void insertStyleRef() {
+        try {
+            final String styleRef = "  <link rel=stylesheet type=\"text/css\" href=\""
+                    + DocumentPane.DEFAULT_STYLE_SHEET_NAME + "\">";
+            final Element defaultRoot = getDefaultRootElement();
+            final Element head = Util.findElementDown(HTML.Tag.HEAD.toString(), defaultRoot);
+            if (head != null) {
+                final Element pImpl = Util.findElementDown(HTML.Tag.IMPLIED.toString(), head);
+                if (pImpl != null) {
+                    final Element link = Util.findElementDown(HTML.Tag.LINK.toString(), pImpl);
+                    if (link != null) {
+                        setOuterHTML(link, styleRef);
+                    }
+                    else {
+                        insertBeforeEnd(pImpl, styleRef);
+                    }
+                }
+            }
+            else {
+                final Element body = Util.findElementDown(HTML.Tag.BODY.toString(), defaultRoot);
+                insertBeforeStart(body, "<head>" + styleRef + "</head>");
+            }
+        }
+        catch (final Exception e) {
+            Util.errMsg(null, "An exception occurred while trying to insert the style sheet reference link", e);
+        }
+    }
+
+    /**
+     * check whether or not this SHTMLDocument has an explicit style sheet reference
+     *
+     * @return true, if a style sheet reference was found, false if not
+     */
+    public boolean hasStyleRef() {
+        return (getStyleRef() != null);
+    }
+
+    /**
+     * get the style sheet reference of the document in this
+     * <code>DocumentPane</code>.
+     *
+     * @return the reference to this document's style sheet or
+     *    null if none is found
+     */
+    public String getStyleRef() {
+        String linkName = null;
+        final Element link = Util.findElementDown(HTML.Tag.LINK.toString(), getDefaultRootElement());
+        if (link != null) {
+            final Object href = link.getAttributes().getAttribute(HTML.Attribute.HREF);
+            if (href != null) {
+                linkName = href.toString();
+            }
+        }
+        return linkName;
+    }
+
+    /* ------------------ custom style sheet reference handling end -------------------- */
+    /* -------- custom reader implementation start ------ */
+    /**
+     * Fetches the reader for the parser to use to load the document
+     * with HTML.  This is implemented to return an instance of
+     * SHTMLDocument.SHTMLReader.
+     */
+    public HTMLEditorKit.ParserCallback getReader(final int pos) {
+        final Object desc = getProperty(Document.StreamDescriptionProperty);
+        if (desc instanceof URL) {
+            setBase((URL) desc);
+        }
+        final SHTMLReader reader = new SHTMLReader(pos, getLength() == 0);
+        return reader;
+    }
+
+    /**
+     * This reader extends HTMLDocument.HTMLReader by the capability
+     * to handle SPAN tags
+     */
+    public class SHTMLReader extends HTMLDocument.HTMLReader {
+        /** action needed to handle SPAN tags */
+        SHTMLCharacterAction characterAction = new SHTMLCharacterAction();
+        /** the attributes found in a STYLE attribute */
+        AttributeSet styleAttributes;
+        /** indicates whether we're inside a SPAN tag */
+        boolean inSpan = false;
+        boolean emptyDocument;
+        private boolean paragraphInserted;
+        private boolean inBody;
+        private boolean paragraphCreated;
+        private boolean isParagraphTag;
+
+        /**
+         * Constructor
+         * 
+         */
+        public SHTMLReader(final int offset, final boolean emptyDocument) {
+            super(offset, 0, 0, null);
+            this.emptyDocument = emptyDocument;
+            inBody = false;
+            paragraphInserted = false;
+            paragraphCreated = false;
+        }
+
+        /**
+         * Handles the start tag received by the parser.
+         *
+         * If it is a SPAN tag, converts the contents of the STYLE
+         * attribute to an AttributeSet, and adds it to the contents
+         * of this tag.
+         *
+         * Otherwise lets HTMLDocument.HTMLReader do the work.
+         */
+        public void handleStartTag(final HTML.Tag tag, final MutableAttributeSet attributeSet, final int pos) {
+            if (tag == HTML.Tag.BODY) {
+                inBody = true;
+            }
+            else if (inBody) {
+                isParagraphTag = isParagraphTag(tag);
+                if (isParagraphTag) {
+                    if (paragraphCreated && !paragraphInserted) {
+                        insertParagraphEndTag(pos);
+                    }
+                    paragraphInserted = true;
+                }
+                else if (!paragraphCreated && !paragraphInserted) {
+                    insertParagraphStartTag(pos);
+                }
+            }
+            if (tag == HTML.Tag.SPAN && !keepSpanTag) {
+                handleStartSpan(attributeSet);
+            }
+            else {
+                super.handleStartTag(tag, attributeSet, pos);
+                if (tag == HTML.Tag.FONT) {
+                    charAttr.removeAttribute(tag);
+                }
+            }
+        }
+
+        private void insertParagraphStartTag(final int pos) {
+            super.handleStartTag(HTML.Tag.P, new SimpleAttributeSet(), pos);
+            paragraphCreated = true;
+            paragraphInserted = true;
+        }
+
+        private void insertParagraphEndTag(final int pos) {
+            super.handleEndTag(HTML.Tag.P, pos);
+            paragraphCreated = false;
+        }
+
+        private boolean isParagraphTag(final Tag t) {
+            if (paragraphElements == null) {
+                paragraphElements = new HashSet();
+                final Object[] elementList = new Object[] { HTML.Tag.BLOCKQUOTE, HTML.Tag.DIR, HTML.Tag.DIV,
+                        HTML.Tag.DL, HTML.Tag.DT, HTML.Tag.FRAMESET, HTML.Tag.H1, HTML.Tag.H2, HTML.Tag.H3,
+                        HTML.Tag.H4, HTML.Tag.H5, HTML.Tag.H6, HTML.Tag.HR, HTML.Tag.LI, HTML.Tag.MENU, HTML.Tag.OL,
+                        HTML.Tag.P, HTML.Tag.PRE, HTML.Tag.TABLE, HTML.Tag.TD, HTML.Tag.TH, HTML.Tag.TR, HTML.Tag.UL };
+                for (int i = 0; i < elementList.length; i++) {
+                    paragraphElements.add(elementList[i]);
+                }
+            }
+            return paragraphElements.contains(t);
+        }
+
+        private void handleStartSpan(final MutableAttributeSet attributeSet) {
+            if (attributeSet.isDefined(HTML.Attribute.STYLE)) {
+                final String styleAttributeValue = (String) attributeSet.getAttribute(HTML.Attribute.STYLE);
+                attributeSet.removeAttribute(HTML.Attribute.STYLE);
+                styleAttributes = getStyleSheet().getDeclaration(styleAttributeValue);
+                attributeSet.addAttributes(styleAttributes);
+            }
+            else {
+                styleAttributes = null;
+            }
+            final TagAction action = characterAction;
+            if (action != null) {
+                /** Remembers which part we're in for handleSimpleTag. */
+                inSpan = true;
+                action.start(HTML.Tag.SPAN, attributeSet);
+            }
+        }
+
+        /**
+         * SPAN tags are directed to handleSimpleTag by the parser.
+         * If a SPAN tag is detected in this method, it gets redirected
+         * to handleStartTag and handleEndTag respectively.
+         */
+        public void handleSimpleTag(final HTML.Tag t, final MutableAttributeSet a, final int pos) {
+            if (inBody && !paragraphCreated && !paragraphInserted) {
+                insertParagraphStartTag(pos);
+            }
+            if (t == HTML.Tag.SPAN && !keepSpanTag) {
+                if (inSpan) {
+                    handleEndTag(t, pos);
+                }
+                else {
+                    handleStartTag(t, a, pos);
+                }
+            }
+            else {
+                super.handleSimpleTag(t, a, pos);
+            }
+        }
+
+        /**
+         * Handles end tag. If a SPAN tag is directed to this method, end its action,
+         * otherwise, let HTMLDocument.HTMLReader do the work
+         */
+        public void handleEndTag(final HTML.Tag t, final int pos) {
+            if (t == HTML.Tag.BODY) {
+                if (paragraphCreated) {
+                    insertParagraphEndTag(pos);
+                }
+                inBody = false;
+                if (emptyDocument) {
+                    if (!paragraphInserted) {
+                        super.handleStartTag(HTML.Tag.P, getEndingAttributeSet(), pos);
+                        super.handleText("\n".toCharArray(), pos);
+                        super.handleEndTag(HTML.Tag.P, pos);
+                    }
+                    super.handleStartTag(HTML.Tag.P, getEndingAttributeSet(), pos);
+                    super.handleText(" ".toCharArray(), pos);
+                    super.handleEndTag(HTML.Tag.P, pos);
+                }
+                super.handleEndTag(t, pos);
+            }
+            else if (t == HTML.Tag.SPAN && !keepSpanTag) {
+                handleEndSpan();
+            }
+            else {
+                super.handleEndTag(t, pos);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see javax.swing.text.html.HTMLDocument.HTMLReader#handleComment(char[], int)
+         */
+        public void handleComment(final char[] data, final int pos) {
+            if (emptyDocument) {
+                super.handleComment(data, pos);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see javax.swing.text.html.HTMLDocument.HTMLReader#handleText(char[], int)
+         */
+        private void handleEndSpan() {
+            final TagAction action = characterAction;
+            if (action != null) {
+                /**
+                 * remember which part we're in for handleSimpleTag
+                 */
+                inSpan = false;
+                action.end(HTML.Tag.SPAN);
+            }
+        }
+
+        /**
+         * Is used to read the style attribute from
+         * a SPAN tag and to map from HTML to Java attributes.
+         */
+        class SHTMLCharacterAction extends HTMLDocument.HTMLReader.CharacterAction {
+            public void start(final HTML.Tag tag, final MutableAttributeSet attr) {
+                pushCharacterStyle();
+                if (attr.isDefined(IMPLIED)) {
+                    attr.removeAttribute(IMPLIED);
+                }
+                charAttr.addAttribute(tag, attr.copyAttributes());
+                if (styleAttributes != null) {
+                    charAttr.addAttributes(styleAttributes);
+                }
+                if (charAttr.isDefined(HTML.Tag.SPAN)) {
+                    charAttr.removeAttribute(HTML.Tag.SPAN);
+                }
+                //System.out.println("mapping attributes");
+                charAttr = (MutableAttributeSet) new AttributeMapper(charAttr)
+                    .getMappedAttributes(AttributeMapper.toJava);
+            }
+
+            public void end(final HTML.Tag t) {
+                popCharacterStyle();
+            }
+        }
+    }
+
+    /* -------- custom reader implementation end -------- */
+    public Element getParagraphElement(final int pos) {
+        return getParagraphElement(pos, inSetParagraphAttributes);
+    }
+
+    /** Gets the current paragraph element, retracing out of p-implied if the parameter
+     * noImplied is true.
+     * @see javax.swing.text.DefaultStyledDocument#getParagraphElement(int)
+     */
+    public Element getParagraphElement(final int pos, final boolean noPImplied) {
+        Element element = super.getParagraphElement(pos);
+        if (noPImplied) {
+            while (element != null && element.getName().equalsIgnoreCase("p-implied")) {
+                element = element.getParentElement();
+            }
+        }
+        return element;
+    }
+
+    public int getLastDocumentPosition() {
+        final int length = getLength();
+        final int suffixLength = 1;
+        return length > suffixLength ? length - suffixLength : length;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLDocument#setParagraphAttributes(int, int, javax.swing.text.AttributeSet, boolean)
+     */
+    public void setParagraphAttributes(final int offset, final int length, final AttributeSet s, final boolean replace) {
+        startCompoundEdit();
+        super.setParagraphAttributes(offset, length, s, replace);
+        inSetParagraphAttributes = true;
+        super.setParagraphAttributes(offset, length, s, replace);
+        inSetParagraphAttributes = false;
+        endCompoundEdit();
+    }
+
+    public void removeParagraphAttributes(final int offset, final int length) {
+        startCompoundEdit();
+        // clear all paragraph attributes in selection
+        for (int i = offset; i < offset + length;) {
+            final Element paragraphElement = super.getParagraphElement(i);
+            removeParagraphAtributes(paragraphElement);
+            final int endOffset = paragraphElement.getEndOffset();
+            i = endOffset;
+        }
+        endCompoundEdit();
+    }
+
+    private void removeParagraphAtributes(final Element paragraphElement) {
+        if (paragraphElement != null && paragraphElement.getName().equalsIgnoreCase("p-implied")) {
+            removeParagraphAtributes(paragraphElement.getParentElement());
+            return;
+        }
+        final StringWriter writer = new StringWriter();
+        final SHTMLWriter htmlStartWriter = new SHTMLWriter(writer, this);
+        try {
+            htmlStartWriter.writeStartTag(paragraphElement.getName(), null);
+            htmlStartWriter.writeChildElements(paragraphElement);
+            htmlStartWriter.writeEndTag(paragraphElement.getName());
+            setOuterHTML(paragraphElement, writer.toString());
+        }
+        catch (final IOException e) {
+            e.printStackTrace();
+        }
+        catch (final BadLocationException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private SimpleAttributeSet getEndingAttributeSet() {
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        if (Util.preferenceIsTrue("gray_row_below_end")) {
+            StyleConstants.setBackground(set, Color.GRAY);
+        }
+        return set;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLDocument#getBase()
+     */
+    public URL getBase() {
+        URL url = super.getBase();
+        if (false == baseDirChecked) {
+            baseDirChecked = true;
+            final File docDir = new File(url.getFile());
+            if (!docDir.exists()) {
+                docDir.mkdirs();
+            }
+            try {
+                url = docDir.toURI().toURL();
+                super.setBase(url);
+                return url;
+            }
+            catch (final MalformedURLException e) {
+            }
+        }
+        return url;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLDocument#setBase(java.net.URL)
+     */
+    public void setBase(final URL u) {
+        baseDirChecked = false;
+        super.setBase(u);
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLEditorKit.java b/src/com/lightdev/app/shtm/SHTMLEditorKit.java
new file mode 100644
index 0000000..b73114b
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLEditorKit.java
@@ -0,0 +1,296 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Cursor;
+import java.awt.Font;
+import java.awt.Toolkit;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Enumeration;
+
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.LabelView;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyledDocument;
+import javax.swing.text.View;
+import javax.swing.text.ViewFactory;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.MinimalHTMLWriter;
+import javax.swing.text.html.StyleSheet;
+
+
+/**
+ * Extensions to <code>HTMLEditorKit</code> for application SimplyHTML.
+ *
+ * <p>In stage 1 this only re-implements how style sheets are handled by
+ * default.</p>
+ *
+ * <p>Stage 3 adds functionality for usage of the custom HTML document
+ * and HTML reader used with SimplyHTML from this stage on.</p>
+ *
+ * <p>With stage 9 some additional views have been added to
+ * the view factory as a workaround for bug id 4765271
+ * (see http://developer.java.sun.com/developer/bugParade/bugs/4765271.html).</p>
+ *
+ * <p>OK, I give up: With release 2 of stage 9 above views are used no longer and
+ * bug fixing is not done anymore. The HTML support is almost taken as is in the hope
+ * that Sun will enhance it some day. To do compensation inside a single application
+ * is not possible with a reasonable effort.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+public class SHTMLEditorKit extends HTMLEditorKit {
+ 
+	SHTMLEditorKit() {
+        super();
+        final Cursor textCursor = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
+        setDefaultCursor(textCursor);
+    }
+
+    /* --------------- SHTMLDocument implementation start ------------ */
+    /**
+     * Create an uninitialized text storage model
+     * that is appropriate for this type of editor.
+     *
+     * @return the model
+     */
+    public Document createDefaultDocument() {
+        final SHTMLDocument doc = (SHTMLDocument) createEmptyDocument();
+        try {
+            final String standardContent;
+            if (Util.preferenceIsTrue("gray_row_below_end")) {
+                standardContent = "<p>\n</p>\n<p style=\"background-color: #808080\">\n" + SHTMLDocument.SUFFIX
+                        + "\n</p>\n";
+            }
+            else {
+                standardContent = "<p>\n</p>\n<p>\n" + SHTMLDocument.SUFFIX + "\n</p>\n";
+            }
+            doc.setOuterHTML(doc.getParagraphElement(doc.getLength()), standardContent);
+        }
+        catch (final BadLocationException e) {
+            e.printStackTrace();
+        }
+        catch (final IOException e) {
+            e.printStackTrace();
+        }
+        return doc;
+    }
+
+    Document createEmptyDocument() {
+        getStyleSheet();
+        final StyleSheet ss = new ScaledStyleSheet();
+        try {
+            ss.importStyleSheet(Class.forName("javax.swing.text.html.HTMLEditorKit").getResource(DEFAULT_CSS));
+        }
+        catch (final Exception e) {
+        }
+        final SHTMLDocument doc = new SHTMLDocument(ss);
+        doc.setParser(getParser());
+        doc.setAsynchronousLoadPriority(-1);
+        doc.setTokenThreshold(1);
+        return doc;
+    }
+
+	/**
+     * Inserts content from the given stream. If <code>doc</code> is
+     * an instance of HTMLDocument, this will read
+     * HTML 3.2 text. Inserting HTML into a non-empty document must be inside
+     * the body Element, if you do not insert into the body an exception will
+     * be thrown. When inserting into a non-empty document all tags outside
+     * of the body (head, title) will be dropped.
+     *
+     * @param in  the stream to read from
+     * @param doc the destination for the insertion
+     * @param pos the location in the document to place the
+     *   content
+     * @exception IOException on any I/O error
+     * @exception BadLocationException if pos represents an invalid
+     *   location within the document
+     * @exception RuntimeException (will eventually be a BadLocationException)
+     *            if pos is invalid
+     */
+    public void read(final Reader in, final Document doc, final int pos) throws IOException, BadLocationException {
+        if (doc instanceof SHTMLDocument) {
+            final SHTMLDocument hdoc = (SHTMLDocument) doc;
+            final Parser parser = getParser();
+            if (parser == null) {
+                throw new IOException("Can't load parser");
+            }
+            if (pos > doc.getLength()) {
+                throw new BadLocationException("Invalid location", pos);
+            }
+            final ParserCallback receiver = hdoc.getReader(pos);
+            if (doc.getLength() == 0) {
+                final Boolean ignoreCharset = (Boolean) doc.getProperty("IgnoreCharsetDirective");
+                parser.parse(in, receiver, (ignoreCharset == null) ? false : ignoreCharset.booleanValue());
+            }
+            else {
+                parser.parse(in, receiver, true);
+            }
+            receiver.flush();
+        }
+        else {
+            super.read(in, doc, pos);
+        }
+    }
+
+    /**
+     * Write content from a document to the given stream
+     * in a format appropriate for this kind of content handler.
+     *
+     * @param out  the stream to write to
+     * @param doc  the source for the write
+     * @param pos  the location in the document to fetch the
+     *   content
+     * @param len  the amount to write out
+     * @exception IOException on any I/O error
+     * @exception BadLocationException if pos represents an invalid
+     *   location within the document
+     */
+    public void write(final Writer out, final Document doc, final int pos, final int len) throws IOException,
+            BadLocationException {
+        if (doc instanceof SHTMLDocument) {
+            try {
+                final SHTMLWriter w = new SHTMLWriter(out, (SHTMLDocument) doc, pos, len);
+                w.write();
+            }
+            catch (final Exception e) {
+                e.printStackTrace();
+            }
+        }
+        else if (doc instanceof StyledDocument) {
+            final MinimalHTMLWriter w = new MinimalHTMLWriter(out, (StyledDocument) doc, pos, len);
+            w.write();
+        }
+        else {
+            super.write(out, doc, pos, len);
+        }
+    }
+
+    /* --------------- SHTMLDocument implementaion end --------------- */
+    void updateInputAttributes(final SHTMLEditorPane e) {
+        // EditorKit might not have installed the StyledDocument yet.
+        final Document aDoc = e.getDocument();
+        if (!(aDoc instanceof StyledDocument)) {
+            return;
+        }
+        final int start = e.getSelectionStart();
+        // record current character attributes.
+        final StyledDocument doc = (StyledDocument) aDoc;
+        // If nothing is selected, get the attributes from the character
+        // before the start of the selection, otherwise get the attributes
+        // from the character element at the start of the selection.
+        Element run;
+        final Element currentParagraph = doc.getParagraphElement(start);
+        if (currentParagraph.getStartOffset() == start || start != e.getSelectionEnd()) {
+            // Get the attributes from the character at the selection
+            // if in a different paragrah!
+            run = doc.getCharacterElement(start);
+        }
+        else {
+            run = doc.getCharacterElement(Math.max(start - 1, 0));
+        }
+        createInputAttributes(run, getInputAttributes());
+    }
+
+    /* --------------- ViewFactory implementation start -------------- */
+    /** Shared factory for creating HTML Views. */
+    private static final ViewFactory defaultFactory = new SHTMLFactory();
+
+    /**
+     * Fetch a factory that is suitable for producing
+     * views of any models that are produced by this
+     * kit.
+     *
+     * @return the factory
+     */
+    public ViewFactory getViewFactory() {
+        return defaultFactory;
+    }
+
+    static public void removeCharacterAttributes(final StyledDocument doc, final Object attributeName, final int start,
+                                                 final int length) {
+        // clear all character attributes in selection
+        final int end = start + length;
+        SimpleAttributeSet sasText = null;
+        for (int i = start; i < end;) {
+            final Element characterElement = doc.getCharacterElement(i);
+            sasText = new SimpleAttributeSet(characterElement.getAttributes().copyAttributes());
+            final int endOffset = characterElement.getEndOffset();
+            final Enumeration attribEntries1 = sasText.getAttributeNames();
+            while (attribEntries1.hasMoreElements()) {
+                final Object entryKey = attribEntries1.nextElement();
+                if (attributeName != null && entryKey.equals(attributeName) || attributeName == null
+                        && !entryKey.equals(StyleConstants.NameAttribute)) {
+                    sasText.removeAttribute(entryKey);
+                }
+            }
+            final int last = end < endOffset ? end : endOffset;
+            try {
+                doc.setCharacterAttributes(i, last - i, sasText, true);
+            }
+            catch (final Exception e) {
+            }
+            i = i < last ? last : i + 1;
+        }
+    }
+
+    public static class SHTMLFactory extends HTMLEditorKit.HTMLFactory implements ViewFactory {
+        public View create(final Element elem) {
+            View view = null;
+            final Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute);
+            if (o instanceof HTML.Tag) {
+                final HTML.Tag kind = (HTML.Tag) o;
+                //System.out.println("SHTMLEditorKit.SHTMLFactory o is HTML.Tag kind=" + kind.toString());
+                if (kind == HTML.Tag.TABLE) {
+                    view = super.create(elem);
+                }
+                else if (kind == HTML.Tag.COMMENT) {
+                    view = new InvisibleView(elem);
+                }
+                else if (kind instanceof HTML.UnknownTag) {
+                    view = new InvisibleView(elem);
+                }
+                else {
+                    view = super.create(elem);
+                }
+            }
+            else {
+                view = new LabelView(elem);
+            }
+            return view;
+        }
+    }
+    /* --------------- ViewFactory implementation end -------------- */
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLEditorKitActions.java b/src/com/lightdev/app/shtm/SHTMLEditorKitActions.java
new file mode 100644
index 0000000..30444c5
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLEditorKitActions.java
@@ -0,0 +1,3336 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Frame;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.TimerTask;
+import java.util.prefs.Preferences;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JToggleButton;
+import javax.swing.KeyStroke;
+import javax.swing.TransferHandler;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.DefaultEditorKit;
+import javax.swing.text.Element;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyledEditorKit;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+import javax.swing.undo.CannotRedoException;
+
+import com.lightdev.app.shtm.SHTMLEditorPane.PasteMode;
+import com.lightdev.app.shtm.SHTMLPanelImpl.FontFamilyPicker;
+import com.lightdev.app.shtm.SHTMLPanelImpl.FontSizePicker;
+import com.sun.demo.ElementTreePanel;
+import com.sun.demo.ExampleFileFilter;
+
+import de.calcom.cclib.text.FindReplaceDialog;
+import de.calcom.cclib.text.FindReplaceEvent;
+import de.calcom.cclib.text.FindReplaceListener;
+
+/** A class groupping actions. Most actions forward the operation to editor pane. */
+class SHTMLEditorKitActions {
+    /**
+     * action to set the style
+     */
+    static class SetStyleAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+        private boolean ignoreActions = false;
+
+        public SetStyleAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.setStyleAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            if (!ignoreActions) {
+                final StyleSelector styleSelector = (StyleSelector) ae.getSource();
+                final AttributeSet attributeSet = styleSelector.getValue();
+                if (attributeSet != null) {
+                    //de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
+                    //hd.listAttributes(a, 2);
+                    panel.getSHTMLEditorPane().applyAttributes(attributeSet, true);
+                }
+                panel.updateActions();
+            }
+        }
+
+        public void setIgnoreActions(final boolean ignore) {
+            ignoreActions = ignore;
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * append a new table col
+     */
+    static class AppendTableColAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public AppendTableColAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.appendTableColAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().appendTableColumn();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            final SHTMLEditorPane editor = panel.getSHTMLEditorPane();
+            if (editor != null && editor.getCurrentTableCell() != null) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Applies a tag to the <i>paragraph element</i> surrounding the selection,
+     * based on the paragraph tag previously stored in the tag selector; tag selector
+     * is a combo box. If constructed when the tag name passed, it applies that tag. 
+     */
+    static class SetTagAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+        private boolean ignoreActions = false;
+        private String tag = null;
+
+        public SetTagAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.setTagAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public SetTagAction(final SHTMLPanelImpl panel, final String tag) {
+            super(SHTMLPanelImpl.setTagAction);
+            this.panel = panel;
+            this.tag = tag;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            if (!ignoreActions) {
+                if (tag != null) {
+                    panel.getSHTMLEditorPane().applyParagraphTag(tag, null);
+                    panel.updateActions();
+                }
+                else {
+                    final String tagFromSelector = panel.getTagSelector().getSelectedTag();
+                    panel.getSHTMLEditorPane().applyParagraphTag(tagFromSelector, panel.getTagSelector().getTags());
+                    panel.updateActions();
+                }
+            }
+        }
+
+        public void setIgnoreActions(final boolean ignore) {
+            ignoreActions = ignore;
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * append a new table row
+     */
+    static class AppendTableRowAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public AppendTableRowAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.appendTableRowAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().appendTableRow();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /*
+     * Created on 20.08.2006
+     * Copyright (C) 2006 Dimitri Polivaev
+     */
+    static class BoldAction extends StyledEditorKit.BoldAction implements SHTMLAction, AttributeComponent {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public BoldAction(final SHTMLPanelImpl panel) {
+            //Action act = new StyledEditorKit.BoldAction();
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.fontBoldAction);
+            putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_MASK));
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.fontBoldAction);
+        }
+
+        /**
+         * do the format change for the associated attribute
+         *
+         * <p>This reverses the current setting for the associated attribute</p>
+         *
+         * @param  e  the ActionEvent describing the cause for this action
+         */
+        public void actionPerformed(final ActionEvent e) {
+            //System.out.println("ToggleAction getValue=" + getValue() + "selectedValue=" + selectedValue);
+            //editor.applyAttributes(getValue(), (unselectedValue == null));
+            super.actionPerformed(e);
+            //if(unselectedValue != null) {
+            if (panel.getSHTMLEditorPane() != null) {
+                final SHTMLDocument doc = (SHTMLDocument) panel.getSHTMLEditorPane().getDocument();
+                if (doc != null) {
+                    final AttributeSet a = doc.getCharacterElement(panel.getSHTMLEditorPane().getSelectionStart())
+                        .getAttributes();
+                    final boolean isBold = StyleConstants.isBold(a);
+                    //if(a.isDefined(attributeKey)) {
+                    //Object value = a.getAttribute(attributeKey);
+                    putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, isBold ? SHTMLPanelImpl.ACTION_SELECTED
+                            : SHTMLPanelImpl.ACTION_UNSELECTED);
+                }
+            }
+            /*}
+            else {
+              putValue(FrmMain.ACTION_SELECTED_KEY, FrmMain.ACTION_SELECTED);
+            }*/
+            panel.updateActions();
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.fontItalicAction);
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            setEnabled(panel.getSHTMLEditorPane() != null);
+        }
+
+        /**
+         * set the value of this <code>AttributeComponent</code>
+         *
+         * @param a  the set of attributes possibly having an
+         *          attribute this component can display
+         *
+         * @return true, if the set of attributes had a matching attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            boolean success = false;
+            boolean isBold = StyleConstants.isBold(a);
+            if (a.isDefined(CSS.Attribute.FONT_WEIGHT)) {
+                final Object value = a.getAttribute(CSS.Attribute.FONT_WEIGHT);
+                if (value.toString().equalsIgnoreCase(StyleConstants.Bold.toString())) {
+                    isBold = true;
+                }
+            }
+            if (isBold) {
+                putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_SELECTED);
+            }
+            else {
+                putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            }
+            success = true;
+            return success;
+        }
+
+        /**
+         * get the value of this <code>AttributeComponent</code>
+         *
+         * @return the value selected from this component
+         */
+        public AttributeSet getValue() {
+            //System.out.println("ToggleAction getValue getValue(FrmMain.ACTION_SELECTED_KEY)=" + getValue(FrmMain.ACTION_SELECTED_KEY));
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            //if(unselectedValue != null) {
+            if (getValue(SHTMLPanelImpl.ACTION_SELECTED_KEY).toString().equals(SHTMLPanelImpl.ACTION_SELECTED)) {
+                Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_WEIGHT, StyleConstants.Bold.toString());
+            }
+            else {
+                Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_WEIGHT, Util.CSS_ATTRIBUTE_NORMAL.toString());
+            }
+            /*}
+                   else {
+              Util.styleSheet().addCSSAttribute(set,
+                  (CSS.Attribute) getAttributeKey(), selectedValue.toString());
+                   }*/
+            return set;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            return getValue();
+        }
+    }
+
+    /**
+     * Applies a text attribute. (Used to be ToggleAction.)
+     */
+    static class ApplyCSSAttributeAction extends AbstractAction implements SHTMLAction, AttributeComponent {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+        /** the attribute this action represents values for */
+        Object attributeName;
+        /** the value for the attribute being selected */
+        final private Object attributeValue;
+        private final boolean applyToParagraph;
+
+        /**
+         * Constructs a ToggleAttributeAction.
+         * @param panel TODO
+         * @param actionName  the name and command for this action
+         * @param attributeName the name of the attribute to be modified
+         * @param attributeValue the value the attribute should be set to
+         * @param applyToParagraph TODO
+         * @param uVal the value for the attribute not being selected
+         */
+        public ApplyCSSAttributeAction(final SHTMLPanelImpl panel, final String actionName, final Object attributeName,
+                                       final Object attributeValue, final boolean applyToParagraph) {
+            super(actionName);
+            this.panel = panel;
+            putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            this.attributeName = attributeName;
+            this.attributeValue = attributeValue;
+            this.applyToParagraph = applyToParagraph;
+            getProperties();
+        }
+
+        /**
+         * do the format change for the associated attribute
+         *
+         * <p>This reverses the current setting for the associated attribute</p>
+         *
+         * @param  ev  the ActionEvent describing the cause for this action
+         */
+        public void actionPerformed(final ActionEvent ev) {
+            boolean performTheAction = false;
+            if (ev.getSource() instanceof JToggleButton) {
+                final JToggleButton button = (JToggleButton) ev.getSource();
+                performTheAction = button.isSelected();
+            }
+            else {
+                performTheAction = true;
+            }
+            if (performTheAction) {
+                panel.getSHTMLEditorPane().applyAttributes(getValue(), applyToParagraph);
+                putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_SELECTED);
+                panel.updateActions();
+            }
+        }
+
+        /**
+         * get the attribute this action represents values for
+         *
+         * @return the attribute this action represents values for
+         */
+        public Object getAttributeName() {
+            return attributeName;
+        }
+
+        /**
+         * set the value of this <code>AttributeComponent</code>
+         *
+         * @param a  the set of attributes possibly having an
+         *          attribute this component can display
+         *
+         * @return true, if the set of attributes had a matching attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            boolean success = false;
+            if (a.isDefined(attributeName)) {
+                final Object value = a.getAttribute(attributeName);
+                if (value.toString().equalsIgnoreCase(attributeValue.toString())) {
+                    putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_SELECTED);
+                }
+                else {
+                    putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+                }
+                success = true;
+            }
+            else {
+                putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            }
+            return success;
+        }
+
+        /**
+         * get the value of this <code>AttributeComponent</code>
+         *
+         * @return the value selected from this component
+         */
+        public AttributeSet getValue() {
+            //System.out.println("ToggleAction getValue getValue(FrmMain.ACTION_SELECTED_KEY)=" + getValue(FrmMain.ACTION_SELECTED_KEY));
+            final SimpleAttributeSet attributeSet = new SimpleAttributeSet();
+            Util.styleSheet().addCSSAttribute(attributeSet, (CSS.Attribute) getAttributeName(),
+                attributeValue.toString());
+            return attributeSet;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            return getValue();
+        }
+
+        /** update the action's state */
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            setEnabled(panel.getSHTMLEditorPane() != null);
+        }
+
+        /** get image, etc. from resource */
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * delete a table col
+     */
+    static class DeleteTableColAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public DeleteTableColAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.deleteTableColAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().deleteTableCol();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Action that brings up a JFrame with a JTree showing the structure
+     * of the document in the currently active DocumentPane.
+     *
+     * will be hidden from menu if not in development mode (DEV_MODE = false)
+     */
+    static class ShowElementTreeAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+        /** a frame for showing an element tree panel */
+        private JFrame elementTreeFrame = null;
+
+        public ShowElementTreeAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.elemTreeAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+            if (elementTreeFrame == null) {
+                final String title = Util.getResourceString("elementTreeTitle");
+                elementTreeFrame = new JFrame(title);
+                elementTreeFrame.addWindowListener(new WindowAdapter() {
+                    public void windowClosing(final WindowEvent we) {
+                        elementTreeFrame.dispose();
+                        elementTreeFrame = null;
+                    }
+                });
+                final Container fContentPane = elementTreeFrame.getContentPane();
+                fContentPane.setLayout(new BorderLayout());
+                final ElementTreePanel elementTreePanel = new ElementTreePanel(panel.getSHTMLEditorPane());
+                fContentPane.add(elementTreePanel);
+                elementTreeFrame.pack();
+            }
+            elementTreeFrame.setVisible(true);
+            panel.updateActions();
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * delete a table row
+     */
+    static class DeleteTableRowAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public DeleteTableRowAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.deleteTableRowAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().deleteTableRow();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * toggle list formatting for a given type of list on/off
+     */
+    static class ToggleListAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+        private final HTML.Tag listTag;
+
+        public ToggleListAction(final SHTMLPanelImpl panel, final String name, final HTML.Tag listTag) {
+            super(name);
+            this.panel = panel;
+            this.listTag = listTag;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().toggleList(listTag.toString(), null,
+            // What are the attributes good for? They break the appearance of nested numbered lists. --Dan
+            //panel.getMaxAttributes(panel.getSHTMLEditorPane(), listTag.toString()),
+                false);
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * set the title of the currently active document
+     */
+    static class DocumentTitleAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public DocumentTitleAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.documentTitleAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            String newTitle;
+            final String currentTitle = panel.getSHTMLDocument().getDocumentTitle();
+            if (currentTitle != null) {
+                newTitle = currentTitle;
+            }
+            else {
+                newTitle = "";
+            }
+            newTitle = Util.nameInput(JOptionPane.getFrameForComponent(panel), newTitle, ".*", "docTitleTitle",
+                "docTitleQuery");
+            if (newTitle != null && newTitle.length() > 0) {
+                panel.getSHTMLDocument().setDocumentTitle(newTitle);
+            }
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /*
+     * Created on 20.08.2006
+     * Copyright (C) 2006 Dimitri Polivaev
+     */
+    static class UnderlineAction extends StyledEditorKit.UnderlineAction implements SHTMLAction, AttributeComponent {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public UnderlineAction(final SHTMLPanelImpl panel) {
+            //Action act = new StyledEditorKit.BoldAction();
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.fontUnderlineAction);
+            putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_MASK));
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.fontUnderlineAction);
+        }
+
+        /**
+         * do the format change for the associated attribute
+         *
+         * <p>This reverses the current setting for the associated attribute</p>
+         *
+         * @param  e  the ActionEvent describing the cause for this action
+         */
+        public void actionPerformed(final ActionEvent e) {
+            //System.out.println("ToggleAction getValue=" + getValue() + "selectedValue=" + selectedValue);
+            //editor.applyAttributes(getValue(), (unselectedValue == null));
+            super.actionPerformed(e);
+            //if(unselectedValue != null) {
+            if (panel.getSHTMLEditorPane() != null) {
+                final SHTMLDocument doc = (SHTMLDocument) panel.getSHTMLEditorPane().getDocument();
+                if (doc != null) {
+                    final AttributeSet a = doc.getCharacterElement(panel.getSHTMLEditorPane().getSelectionStart())
+                        .getAttributes();
+                    final boolean isUnderlined = StyleConstants.isUnderline(a);
+                    if (isUnderlined) {
+                        putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_SELECTED);
+                    }
+                    else {
+                        putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+                    }
+                }
+            }
+            panel.updateActions();
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.fontUnderlineAction);
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        /**
+         * set the value of this <code>AttributeComponent</code>
+         *
+         * @param a  the set of attributes possibly having an
+         *          attribute this component can display
+         *
+         * @return true, if the set of attributes had a matching attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            boolean success = false;
+            boolean isUnderlined = StyleConstants.isUnderline(a);
+            if (a.isDefined(CSS.Attribute.TEXT_DECORATION)) {
+                final Object value = a.getAttribute(CSS.Attribute.TEXT_DECORATION);
+                if (value.toString()
+                    .equalsIgnoreCase(Util.CSS_ATTRIBUTE_UNDERLINE /*StyleConstants.Underline.toString()*/)) {
+                    isUnderlined = true;
+                }
+            }
+            if (isUnderlined) {
+                putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_SELECTED);
+            }
+            else {
+                putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            }
+            success = true;
+            return success;
+        }
+
+        /**
+         * get the value of this <code>AttributeComponent</code>
+         *
+         * @return the value selected from this component
+         */
+        public AttributeSet getValue() {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            if (getValue(SHTMLPanelImpl.ACTION_SELECTED_KEY).toString().equals(SHTMLPanelImpl.ACTION_SELECTED)) {
+                Util.styleSheet().addCSSAttribute(set, CSS.Attribute.TEXT_DECORATION, Util.CSS_ATTRIBUTE_UNDERLINE);
+            }
+            else {
+                Util.styleSheet().addCSSAttribute(set, CSS.Attribute.TEXT_DECORATION, Util.CSS_ATTRIBUTE_NONE);
+            }
+            return set;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            return getValue();
+        }
+    }
+
+    static class FontColorAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+        private ColorPanel hiddenColorPanel;
+
+        public FontColorAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.fontColorAction);
+            putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            getProperties();
+            hiddenColorPanel = null;
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+            final SHTMLEditorPane editorPane = panel.getSHTMLEditorPane();
+            if (editorPane != null) {
+                if (hiddenColorPanel == null) {
+                    hiddenColorPanel = new ColorPanel("Select Color", Color.BLACK, CSS.Attribute.COLOR);
+                }
+                hiddenColorPanel.setValue(panel.getMaxAttributes(editorPane, null));
+                hiddenColorPanel.actionPerformed(null); // show the color chooser
+                editorPane.applyAttributes(hiddenColorPanel.getValue(), false); // apply the color setting to the editor
+            }
+            panel.updateActions();
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.fontColorAction);
+        }
+
+        public void update() {
+        }
+    }
+
+    /**
+       * action to edit anchors inside a document
+       */
+    static class EditAnchorsAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public EditAnchorsAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.editAnchorsAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final AnchorDialog dlg = new AnchorDialog(parent, Util.getResourceString("anchorDialogTitle"),
+                panel.getSHTMLDocument());
+            Util.center(parent, dlg);
+            dlg.setModal(true);
+            dlg.setVisible(true);
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * action to edit a link
+     */
+    static class EditLinkAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public EditLinkAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.editLinkAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final LinkDialog dialog = new LinkDialog(parent, Util.getResourceString("linkDialogTitle"),
+                panel.getSHTMLEditorPane(), panel.getDocumentPane().getImageDir()/*,
+                                                                                 renderMode*/);
+            if (parent != null) {
+                Util.center(parent, dialog);
+            }
+            dialog.setModal(true);
+            dialog.setVisible(true);
+            if (dialog.getResult() == DialogShell.RESULT_OK) {
+                // apply link here
+                panel.getSHTMLEditorPane().setLink(dialog.getLinkText(), dialog.getHref(), dialog.getStyleName(),
+                    dialog.getLinkImage(), dialog.getLinkImageSize());
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                if ((panel.getSHTMLEditorPane().getSelectionEnd() > panel.getSHTMLEditorPane().getSelectionStart())
+                        || (panel.getSHTMLEditorPane().getCurrentLinkElement() != null)) {
+                    this.setEnabled(true);
+                }
+                else {
+                    this.setEnabled(false);
+                }
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Is an action to open a hyperlink.
+     */
+    static class OpenLinkAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public OpenLinkAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.openLinkAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final String linkURL = panel.getSHTMLEditorPane().getURLOfExistingLink();
+            if (linkURL != null) {
+                panel.openHyperlink(linkURL);
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                if ((panel.getSHTMLEditorPane().getSelectionEnd() > panel.getSHTMLEditorPane().getSelectionStart())
+                        || (panel.getSHTMLEditorPane().getCurrentLinkElement() != null)) {
+                    setEnabled(true);
+                }
+                else {
+                    setEnabled(false);
+                }
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * UndoAction for the edit menu
+     */
+    static class UndoAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public UndoAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.undoAction);
+            this.panel = panel;
+            setEnabled(false);
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+            if (panel.getCurrentDocumentPane().getSelectedTab() != DocumentPane.VIEW_TAB_LAYOUT) {
+                return;
+            }
+            try {
+                panel.getUndo().undo();
+                panel.getSHTMLEditorPane();
+            }
+            catch (final Exception ex) {
+                Util.errMsg((Component) e.getSource(), Util.getResourceString("unableToUndoError") + ex, ex);
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            setEnabled(panel.getUndo().canUndo());
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * action to change the paragraph style
+     */
+    static class EditNamedStyleAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public EditNamedStyleAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.editNamedStyleAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final ParaStyleDialog dlg = new ParaStyleDialog(parent, Util.getResourceString("namedStyleDialogTitle"),
+                panel.getSHTMLDocument());
+            Util.center(parent, dlg);
+            dlg.setModal(true);
+            dlg.setValue(panel.getMaxAttributes(panel.getSHTMLEditorPane(), null));
+            dlg.setVisible(true);
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    static class ClearFormatAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public ClearFormatAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.clearFormatAction);
+            putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_MASK));
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.clearFormatAction);
+        }
+
+        /**
+         * do the format change for the associated attribute
+         *
+         * <p>This reverses the current setting for the associated attribute</p>
+         *
+         * @param  e  the ActionEvent describing the cause for this action
+         */
+        public void actionPerformed(final ActionEvent e) {
+            final SHTMLEditorPane editor = panel.getSHTMLEditorPane();
+            if (editor != null) {
+                if (editor.getSelectionStart() != editor.getSelectionEnd()) {
+                    editor.removeCharacterAttributes();
+                }
+                else {
+                    editor.removeParagraphAttributes();
+                }
+            }
+            panel.updateActions();
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.clearFormatAction);
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            final SHTMLEditorPane editor = panel.getSHTMLEditorPane();
+            this.setEnabled(editor != null);
+        }
+    }
+
+    /**
+     * action to find and replace a given text
+     */
+    static class MultipleDocFindReplaceAction extends AbstractAction implements SHTMLAction, FindReplaceListener {
+        /**
+         *
+         */
+        private final SHTMLPanelMultipleDocImpl panel;
+
+        public MultipleDocFindReplaceAction(final SHTMLPanelMultipleDocImpl panel) {
+            super(SHTMLPanelMultipleDocImpl.findReplaceAction);
+            this.panel = panel;
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_MASK));
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            currentTab = panel.getTabbedPaneForDocuments().getSelectedIndex();
+            caretPos = panel.getDocumentPane().getEditor().getCaretPosition();
+            if (panel.getTabbedPaneForDocuments().getTabCount() > 1) {
+                //System.out.println("FindReplaceAction.actionPerformed with Listener");
+                new FindReplaceDialog(panel.getMainFrame(), panel.getSHTMLEditorPane(), this);
+            }
+            else {
+                //System.out.println("FindReplaceAction.actionPerformed NO Listener");
+                new FindReplaceDialog(panel.getMainFrame(), panel.getSHTMLEditorPane());
+            }
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getTabbedPaneForDocuments().getTabCount() > 0) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelMultipleDocImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+
+        public void getNextDocument(final FindReplaceEvent e) {
+            final FindReplaceDialog frd = (FindReplaceDialog) e.getSource();
+            final int tabCount = panel.getTabbedPaneForDocuments().getTabCount();
+            int curTab = panel.getTabbedPaneForDocuments().getSelectedIndex();
+            System.out.println("FindReplaceAction.getNextDocument curTab=" + curTab + ", tabCount=" + tabCount);
+            if (++curTab < tabCount) {
+                System.out.println("FindReplaceAction.getNextDocument next tab no=" + curTab);
+                resumeWithNewEditor(frd, curTab);
+            }
+            else {
+                frd.terminateOperation();
+            }
+        }
+
+        public void getFirstDocument(final FindReplaceEvent e) {
+            final FindReplaceDialog frd = (FindReplaceDialog) e.getSource();
+            resumeWithNewEditor(frd, 0);
+        }
+
+        public void findReplaceTerminated(final FindReplaceEvent e) {
+            panel.getTabbedPaneForDocuments().setSelectedIndex(currentTab);
+            final DocumentPane docPane = (DocumentPane) panel.getTabbedPaneForDocuments().getSelectedComponent();
+            final JEditorPane editor = docPane.getEditor();
+            editor.setCaretPosition(caretPos);
+            editor.requestFocus();
+        }
+
+        private void resumeWithNewEditor(final FindReplaceDialog frd, final int tabNo) {
+            panel.getTabbedPaneForDocuments().setSelectedIndex(tabNo);
+            final DocumentPane docPane = (DocumentPane) panel.getTabbedPaneForDocuments().getComponentAt(tabNo);
+            final JEditorPane editor = docPane.getEditor();
+            editor.requestFocus();
+            frd.setEditor(editor);
+            frd.resumeOperation();
+        }
+
+        private int caretPos;
+        private int currentTab;
+    }
+
+    /**
+     * action to find and replace a given text
+     */
+    static class SingleDocFindReplaceAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SingleDocFindReplaceAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.findReplaceAction);
+            this.panel = panel;
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_MASK));
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            currentDocumentPane = panel.getDocumentPane();
+            if (currentDocumentPane != null) {
+                caretPos = currentDocumentPane.getEditor().getCaretPosition();
+                new FindReplaceDialog(panel.getMainFrame(), panel.getSHTMLEditorPane());
+            }
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getDocumentPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+
+        public void findReplaceTerminated(final FindReplaceEvent e) {
+            if (currentDocumentPane.isVisible()) {
+                final JEditorPane editor = currentDocumentPane.getEditor();
+                editor.setCaretPosition(caretPos);
+                editor.requestFocus();
+            }
+        }
+
+        private int caretPos;
+        private DocumentPane currentDocumentPane;
+    }
+
+    /**
+     * Show a dialog to format fonts
+     */
+    static class FontAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public FontAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.fontAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            panel.getSHTMLEditorPane().requestFocus();
+            /** create a modal FontDialog, center and show it */
+            final FontDialog fd = new FontDialog(parent, Util.getResourceString("fontDialogTitle"),
+                panel.getMaxAttributes(panel.getSHTMLEditorPane(), null));
+            Util.center(parent, fd);
+            fd.setModal(true);
+            fd.setVisible(true);
+            /** if the user made a selection, apply it to the document */
+            if (fd.getResult() == FontDialog.RESULT_OK) {
+                panel.getSHTMLEditorPane().applyAttributes(fd.getAttributes(), false);
+                panel.updateFormatControls();
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * change a font family setting
+     */
+    static class FontFamilyAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public FontFamilyAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.fontFamilyAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final FontFamilyPicker ffp = ((FontFamilyPicker) ae.getSource());
+            if (!ffp.ignore()) {
+                panel.getSHTMLEditorPane().applyAttributes(ffp.getValue(), false);
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            setEnabled(panel.getSHTMLEditorPane() != null);
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * change a font size setting
+     */
+    static class FontSizeAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public FontSizeAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.fontSizeAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final FontSizePicker fsp = ((FontSizePicker) ae.getSource());
+            if (!fsp.ignore()) {
+                panel.getSHTMLEditorPane().applyAttributes(fsp.getValue(), false);
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    static class FormatImageAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public FormatImageAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.formatImageAction);
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final ImageDialog dlg = new ImageDialog(parent, Util.getResourceString("imageDialogTitle"), panel
+                .getDocumentPane().getImageDir(), (SHTMLDocument) panel.getDocumentPane().getDocument());
+            final Element img = panel.getSHTMLDocument().getCharacterElement(
+                panel.getSHTMLEditorPane().getCaretPosition());
+            if (img.getName().equalsIgnoreCase(HTML.Tag.IMG.toString())) {
+                Util.center(parent, dlg);
+                dlg.setImageAttributes(img.getAttributes());
+                dlg.setModal(true);
+                dlg.setVisible(true);
+                /** if the user made a selection, apply it to the document */
+                if (dlg.getResult() == DialogShell.RESULT_OK) {
+                    try {
+                        panel.getSHTMLDocument().setOuterHTML(img, dlg.getImageHTML());
+                    }
+                    catch (final Exception e) {
+                        Util.errMsg(null, e.getMessage(), e);
+                    }
+                }
+                panel.updateActions();
+            }
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                final Element img = panel.getSHTMLDocument().getCharacterElement(
+                    panel.getSHTMLEditorPane().getCaretPosition());
+                if (img.getName().equalsIgnoreCase(HTML.Tag.IMG.toString())) {
+                    this.setEnabled(true);
+                }
+                else {
+                    this.setEnabled(false);
+                }
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Change list formatting
+     */
+    static class FormatListAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public FormatListAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.formatListAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            panel.getSHTMLEditorPane().requestFocus();
+            panel.getSHTMLEditorPane().getSelectionStart();
+            final ListDialog dlg = new ListDialog(parent, Util.getResourceString("listDialogTitle"));
+            final SimpleAttributeSet set = new SimpleAttributeSet(panel.getMaxAttributes(panel.getSHTMLEditorPane(),
+                HTML.Tag.UL.toString()));
+            set.addAttributes(panel.getMaxAttributes(panel.getSHTMLEditorPane(), HTML.Tag.OL.toString()));
+            dlg.setListAttributes(set);
+            final String currentTag = dlg.getListTag();
+            Util.center(parent, dlg);
+            dlg.setModal(true);
+            dlg.setVisible(true);
+            /** if the user made a selection, apply it to the document */
+            if (dlg.getResult() == DialogShell.RESULT_OK) {
+                final AttributeSet a = dlg.getListAttributes();
+                final String newTag = dlg.getListTag();
+                if (newTag == null) {
+                    panel.getSHTMLEditorPane().toggleList(newTag, a, true);
+                }
+                else if (newTag.equalsIgnoreCase(currentTag)) {
+                    if (a.getAttributeCount() > 0) {
+                        panel.getSHTMLEditorPane().applyListAttributes(a);
+                    }
+                }
+                else {
+                    panel.getSHTMLEditorPane().toggleList(newTag, a, false);
+                }
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * action to change the paragraph style
+     */
+    static class FormatParaAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public FormatParaAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.formatParaAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final ParaStyleDialog dlg = new ParaStyleDialog(parent, Util.getResourceString("paraStyleDialogTitle"));
+            Util.center(parent, dlg);
+            dlg.setModal(true);
+            //SHTMLDocument doc = (SHTMLDocument) dp.getDocument();
+            final int caretPosition = panel.getSHTMLEditorPane().getCaretPosition();
+            dlg.setValue(panel.getMaxAttributes(caretPosition));
+            dlg.setVisible(true);
+            /** if the user made a selection, apply it to the document */
+            if (dlg.getResult() == DialogShell.RESULT_OK) {
+                panel.getSHTMLEditorPane().applyAttributes(dlg.getValue(), true);
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * format table attributes
+     */
+    static class FormatTableAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public FormatTableAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.formatTableAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final SHTMLEditorPane editor = panel.getSHTMLEditorPane();
+            editor.requestFocus();
+            editor.getSelectionStart();
+            final TableDialog td = new TableDialog(parent, Util.getResourceString("tableDialogTitle"));
+            td.setTableAttributes(panel.getMaxAttributes(editor, HTML.Tag.TABLE.toString()));
+            td.setCellAttributes(panel.getMaxAttributes(editor, HTML.Tag.TD.toString()));
+            Util.center(parent, td);
+            td.setModal(true);
+            td.setVisible(true);
+            /** if the user made a selection, apply it to the document */
+            if (td.getResult() == DialogShell.RESULT_OK) {
+                final SHTMLDocument doc = (SHTMLDocument) editor.getDocument();
+                doc.startCompoundEdit();
+                AttributeSet a = td.getTableAttributes();
+                if (a.getAttributeCount() > 0) {
+                    editor.applyTableAttributes(a);
+                }
+                a = td.getCellAttributes();
+                if (a.getAttributeCount() > 0) {
+                    editor.applyCellAttributes(a, td.getCellRange());
+                }
+                doc.endCompoundEdit();
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * force a garbage collection. This can be helpful to find out
+     * whether or not objects are properly disposed.
+     *
+     * Without forcing a garbage collection, this would happen
+     * at random intervals so although an object might be properly
+     * disposed, it might still be around until the next GC.
+     *
+     * will be hidden from menu if not in development mode (DEV_MODE = false)
+     */
+    static class GarbageCollectionAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public GarbageCollectionAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.gcAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+            System.gc();
+            panel.updateActions();
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    static class InsertImageAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public InsertImageAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.insertImageAction);
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final ImageDialog dlg = new ImageDialog(parent, Util.getResourceString("imageDialogTitle"), panel
+                .getDocumentPane().getImageDir());
+            Util.center(parent, dlg);
+            dlg.setModal(true);
+            dlg.setVisible(true);
+            /** if the user made a selection, apply it to the document */
+            if (dlg.getResult() == DialogShell.RESULT_OK) {
+                try {
+                    panel.getSHTMLDocument().insertBeforeStart(
+                        panel.getSHTMLDocument().getCharacterElement(panel.getSHTMLEditorPane().getSelectionEnd()),
+                        dlg.getImageHTML());
+                }
+                catch (final Exception e) {
+                    Util.errMsg(null, e.getMessage(), e);
+                }
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * insert a new table
+     */
+    static class InsertTableAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public InsertTableAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.insertTableAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            Object input = null;
+            final boolean showPopup = Util.preferenceIsTrue("table.popupBeforeInserting", "true");
+            if (showPopup) {
+                input = Util.nameInput(parent, "3", "\\d+", "insertTableTitle", "insertTableMsg");
+            }
+            if (input != null || !showPopup) {
+                final int choice = input != null ? Integer.parseInt(input.toString()) : 3;
+                if (choice > 0) {
+                    panel.getSHTMLEditorPane().insertNewTable(choice);
+                }
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * insert a new table column
+     */
+    static class InsertTableColAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public InsertTableColAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.insertTableColAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().insertTableColumn();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * insert a new table row
+     */
+    static class InsertTableRowAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+        private final String forcedCellName;
+
+        public InsertTableRowAction(final SHTMLPanelImpl panel, final String forcedCellName, final String titleID) {
+            super(titleID);
+            this.panel = panel;
+            this.forcedCellName = forcedCellName;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().insertTableRow(forcedCellName);
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Move theinsert a new table row
+     */
+    static class MoveTableRowUpAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public MoveTableRowUpAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.moveTableRowUpAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().moveTableRowUp();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Moves the the table row up.
+     */
+    static class MoveTableRowDownAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public MoveTableRowDownAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.moveTableRowUpAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().moveTableRowDown();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Moves the the table column left.
+     */
+    static class MoveTableColumnLeftAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public MoveTableColumnLeftAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.moveTableColumnLeftAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().moveTableColumnLeft();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Moves the the table column right.
+     */
+    static class MoveTableColumnRightAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public MoveTableColumnRightAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.moveTableColumnRightAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().moveTableColumnRight();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * Turns a table data cell into a table header cell or vice versa.
+     */
+    static class ToggleTableHeaderCellAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public ToggleTableHeaderCellAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().toggleTableHeaderCell();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    static class ItalicAction extends StyledEditorKit.ItalicAction implements SHTMLAction, AttributeComponent {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public ItalicAction(final SHTMLPanelImpl panel) {
+            //Action act = new StyledEditorKit.BoldAction();
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.fontItalicAction);
+            putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK));
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.fontItalicAction);
+        }
+
+        /**
+         * do the format change for the associated attribute
+         *
+         * <p>This reverses the current setting for the associated attribute</p>
+         *
+         * @param  e  the ActionEvent describing the cause for this action
+         */
+        public void actionPerformed(final ActionEvent e) {
+            super.actionPerformed(e);
+            if (panel.getSHTMLEditorPane() != null) {
+                final SHTMLDocument doc = (SHTMLDocument) panel.getSHTMLEditorPane().getDocument();
+                if (doc != null) {
+                    final AttributeSet a = doc.getCharacterElement(panel.getSHTMLEditorPane().getSelectionStart())
+                        .getAttributes();
+                    final boolean isItalic = StyleConstants.isItalic(a);
+                    if (isItalic) {
+                        putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_SELECTED);
+                    }
+                    else {
+                        putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+                    }
+                }
+            }
+            panel.updateActions();
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, SHTMLPanelImpl.fontItalicAction);
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        /**
+         * set the value of this <code>AttributeComponent</code>
+         *
+         * @param a  the set of attributes possibly having an
+         *          attribute this component can display
+         *
+         * @return true, if the set of attributes had a matching attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            boolean success = false;
+            boolean isItalic = StyleConstants.isItalic(a);
+            if (a.isDefined(CSS.Attribute.FONT_STYLE)) {
+                final Object value = a.getAttribute(CSS.Attribute.FONT_STYLE);
+                if (value.toString().equalsIgnoreCase(StyleConstants.Italic.toString())) {
+                    isItalic = true;
+                }
+            }
+            if (isItalic) {
+                putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_SELECTED);
+            }
+            else {
+                putValue(SHTMLPanelImpl.ACTION_SELECTED_KEY, SHTMLPanelImpl.ACTION_UNSELECTED);
+            }
+            success = true;
+            return success;
+        }
+
+        /**
+         * get the value of this <code>AttributeComponent</code>
+         *
+         * @return the value selected from this component
+         */
+        public AttributeSet getValue() {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            if (getValue(SHTMLPanelImpl.ACTION_SELECTED_KEY).toString().equals(SHTMLPanelImpl.ACTION_SELECTED)) {
+                Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE, Util.CSS_ATTRIBUTE_NORMAL.toString());
+            }
+            else {
+                Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_STYLE, StyleConstants.Italic.toString());
+            }
+            return set;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            return getValue();
+        }
+    }
+
+    /**
+     * action to move to the next cell in a table
+     */
+    static class NextTableCellAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public NextTableCellAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.nextTableCellAction);
+            this.panel = panel;
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Element cell = panel.getSHTMLEditorPane().getCurrentTableCell();
+            if (cell != null) {
+                panel.getSHTMLEditorPane().goNextCell(cell);
+                panel.updateActions();
+            }
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * action to move to the previous cell in a table
+     */
+    static class PrevTableCellAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public PrevTableCellAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.prevTableCellAction);
+            this.panel = panel;
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Element cell = panel.getSHTMLEditorPane().getCurrentTableCell();
+            if (cell != null) {
+                panel.getSHTMLEditorPane().goPrevCell(cell);
+                panel.updateActions();
+            }
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if ((panel.getSHTMLEditorPane() != null) && (panel.getSHTMLEditorPane().getCurrentTableCell() != null)) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * action to move to the previous cell in a table
+     */
+    static class PrintAction extends AbstractAction implements SHTMLAction {
+        static private Method printMethod;
+        static {
+            Method printMethod = null;
+            try {
+                printMethod = JTextComponent.class.getMethod("print", new Class[] {});
+            }
+            catch (final Exception e) {
+            }
+            PrintAction.printMethod = printMethod;
+        }
+
+        static boolean canPrint() {
+            return printMethod != null;
+        }
+
+        private final SHTMLPanelImpl panel;
+
+        public PrintAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.printAction);
+            getProperties();
+            this.panel = panel;
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+            if (PrintAction.canPrint()) {
+                try {
+                    printMethod.invoke(panel.getEditorPane(), new Object[] {});
+                }
+                catch (final Exception ex) {
+                    ex.printStackTrace();
+                }
+            }
+            else {
+                JOptionPane.showMessageDialog(panel, Util.getResourceString("printing_not_supported"));
+                setEnabled(false);
+            }
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * RedoAction for the edit menu
+     */
+    static class RedoAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public RedoAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.redoAction);
+            this.panel = panel;
+            setEnabled(false);
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Y, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+            if (panel.getCurrentDocumentPane().getSelectedTab() != DocumentPane.VIEW_TAB_LAYOUT) {
+                return;
+            }
+            try {
+                panel.getUndo().redo();
+                panel.getSHTMLEditorPane();
+            }
+            catch (final CannotRedoException ex) {
+                Util.errMsg((Component) e.getSource(), Util.getResourceString("unableToRedoError") + ex, ex);
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            setEnabled(panel.getUndo().canRedo());
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /** just adds a normal name to the superclasse's action */
+    static class SHTMLEditCopyAction extends DefaultEditorKit.CopyAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLEditCopyAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.copyAction);
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+            super.actionPerformed(e);
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.getSHTMLEditorPane() != null) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /** just adds a normal name to the superclasse's action */
+    static class SHTMLEditCutAction extends DefaultEditorKit.CutAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLEditCutAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.cutAction);
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+            super.actionPerformed(e);
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.getSHTMLEditorPane() != null) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /** just adds a normal name to the superclasse's action */
+    static class SHTMLEditPasteAction extends DefaultEditorKit.PasteAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLEditPasteAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.pasteAction);
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+        	super.actionPerformed(e);
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.getSHTMLEditorPane() != null) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+    
+    /**
+     * This action does either "Paste as HTML" or "Paste as Text", depending on default_paste_mode!
+     * @author Felix Natter
+     *
+     */
+    static class SHTMLEditPasteOtherAction extends DefaultEditorKit.PasteAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLEditPasteOtherAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            
+            updateActionName(PasteMode.getValueFromPrefs().invert());
+            //putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK));
+        }
+        
+        public void updateActionName(final PasteMode pm)
+        {
+        	if (pm == PasteMode.PASTE_HTML)
+        	{
+        		putValue(Action.NAME, Util.getResourceString("pasteHTMLLabel"));
+        	} 
+        	else if (pm == PasteMode.PASTE_PLAIN_TEXT)
+        	{
+        		putValue(Action.NAME, Util.getResourceString("pastePlainTextLabel"));
+        	}
+        	else
+        	{
+        		throw new RuntimeException("Unknown SHTMLEditorPane.PasteMode: " + pm.toString());
+        	}
+        	getProperties();
+        	panel.updateActions();
+        }
+
+        public void actionPerformed(final ActionEvent e) {
+        	PasteMode pm = panel.getSHTMLEditorPane().getPasteMode().invert();
+        	panel.getSHTMLEditorPane().setPasteMode(pm);
+        	
+            super.actionPerformed(e);
+            panel.updateActions();
+            
+            panel.getSHTMLEditorPane().setPasteModeFromPrefs();
+        }
+
+        public void update() {
+            if (panel.getSHTMLEditorPane() != null) {
+                setEnabled(true);
+            }
+            else {
+                setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+        	SHTMLPanelImpl.getActionProperties(this, "pasteOther");
+        }
+    }
+
+    static class SHTMLEditPrefsAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLEditPrefsAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.editPrefsAction);
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final PrefsDialog dlg = new PrefsDialog(parent, Util.getResourceString("prefsDialogTitle"));
+            
+            dlg.addPrefChangeListener(panel);
+            
+            Util.center(parent, dlg);
+            dlg.setModal(true);
+            dlg.setVisible(true);
+            /** if the user made a selection, apply it to the document */
+            if (dlg.getResult() == DialogShell.RESULT_OK) {
+            }
+            panel.updateActions();
+            
+            dlg.removePrefChangeListener(panel);
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    static class SHTMLEditSelectAllAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLEditSelectAllAction(final SHTMLPanelImpl panel) {
+            super();
+            this.panel = panel;
+            putValue(Action.NAME, SHTMLPanelImpl.selectAllAction);
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            if (panel.isHtmlEditorActive()) {
+                panel.getDocumentPane().getHtmlEditor().selectAll();
+            }
+            else {
+                panel.getSHTMLEditorPane().selectAll();
+                panel.updateActions();
+            }
+        }
+
+        public void update() {
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * close a document.
+     *
+     * <p>the action takes into account whether or not a document needs to be
+     * saved.</p>
+     *
+     * <p>By having the actual closing task in a separate public method of this
+     * action, the close functionality can be shared with action 'close all' or
+     * others that might need it.</p>
+     */
+    static class SHTMLFileCloseAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelMultipleDocImpl panel;
+        private boolean exitApp = false;
+
+        /** constructor
+         * @param panel TODO*/
+        public SHTMLFileCloseAction(final SHTMLPanelMultipleDocImpl panel) {
+            super(SHTMLPanelMultipleDocImpl.closeAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        /** close the currently active document, if there is one */
+        public void actionPerformed(final ActionEvent ae) {
+            if (panel.getSHTMLEditorPane() != null) { // if documents are open
+                closeDocument(panel.getActiveTabNo(), ae, false); // close the active one
+            }
+            panel.updateActions();
+        }
+
+        /**
+         * close a document by its tab index.
+         *
+         * <p>The method takes care of saving the document if necessary prior
+         * to closing.</p>
+         *
+         * @param the tab index number of the document in the tabbed pane.
+         * @return true, if the document was closed successfully.
+         */
+        public void closeDocument(final int index, final ActionEvent ae, final boolean ignoreChanges) {
+            exitApp = ae.getActionCommand().indexOf(SHTMLPanelImpl.exitAction) > -1;
+            final DocumentPane dp = (DocumentPane) panel.getTabbedPaneForDocuments().getComponentAt(index);
+            if (!dp.saveInProgress()) { // if no save is going on and..
+                if (ignoreChanges) {
+                    closeDoc(dp);
+                }
+                else {
+                    if (dp.needsSaving()) { // ..the document needs to be saved
+                        panel.selectTabbedPane(index);
+                        final String docName = dp.getDocumentName();
+                        final int choice = Util.msgChoice(JOptionPane.YES_NO_CANCEL_OPTION, "confirmClosing",
+                            "saveChangesQuery", docName, "\r\n\r\n");
+                        switch (choice) {
+                            case JOptionPane.YES_OPTION: // if the user wanted to save
+                                if (dp.isNewDoc()) { //if the document is new
+                                    panel.dynRes.getAction(SHTMLPanelMultipleDocImpl.saveAsAction).actionPerformed(ae); // 'save as'
+                                }
+                                else { // else
+                                    panel.dynRes.getAction(SHTMLPanelMultipleDocImpl.saveAction).actionPerformed(ae); // 'save'
+                                }
+                                scheduleClose(dp); //..and wait until it is finshed, then close
+                                break;
+                            case JOptionPane.NO_OPTION: // if the user don't like to save
+                                closeDoc(dp); // close the document without saving
+                                break;
+                            case JOptionPane.CANCEL_OPTION: // if the user cancelled
+                                break; // do nothing
+                        }
+                    }
+                    else { // if the document does not need to be saved
+                        closeDoc(dp); // close the document
+                    }
+                }
+            }
+            else { // save was going on upon close request, so
+                scheduleClose(dp); // wait for completion, then close
+            }
+        }
+
+        /**
+         * schedule closing of a document.
+         *
+         * <p>This creates a <code>Timer</code> thread for which a
+         * <code>TimerTask</code> is scheduled to peridically check
+         * whether or not the save process for respective document commenced
+         * successfully.</p>
+         *
+         * <p>If yes, Timer and TimerTask are disposed and the document
+         * is closed. If not, the document remains open.</p>
+         *
+         * @param dp  the document to close
+         * @param index  the number of the tab for that document
+         */
+        private void scheduleClose(final DocumentPane dp) {
+            final java.util.Timer timer = new java.util.Timer();
+            final TimerTask task = new TimerTask() {
+                public void run() {
+                    if (!dp.saveInProgress()) { // if done with saving
+                        if (dp.saveSuccessful) { // and all went fine
+                            closeDoc(dp); // close the document
+                            this.cancel(); // dispose the task
+                            timer.cancel(); // dispose the timer
+                        }
+                    }
+                }
+            };
+            timer.schedule(task, 0, 400); // try to close every 400 milliseconds
+        }
+
+        /**
+         * convenience method for closing a document
+         */
+        private void closeDoc(final DocumentPane dp) {
+            try {
+                dp.deleteTempDir();
+                panel.unregisterDocument();
+                panel.getTabbedPaneForDocuments().remove(dp);
+            }
+            catch (final IndexOutOfBoundsException e) { // if the tabs have changed meanwhile
+                catchCloseErr(dp);
+            }
+            if (exitApp) { // if the doc close was caused by a request to exit the app
+                if (panel.getTabbedPaneForDocuments().getTabCount() == 0) { // ..and if there are no open docs
+                    System.exit(0); // exit the application
+                }
+            }
+        }
+
+        private void catchCloseErr(DocumentPane dp) {
+            try {
+                int i = panel.getTabbedPaneForDocuments().indexOfComponent(dp); // get the current tab index
+                if (i < 0 && panel.getSHTMLEditorPane() != null) {
+                    panel.setActiveTabNo(panel.getTabbedPaneForDocuments().getSelectedIndex());
+                    dp = (DocumentPane) panel.getTabbedPaneForDocuments().getComponentAt(panel.getActiveTabNo());
+                    i = panel.getTabbedPaneForDocuments().indexOfComponent(dp); // get the current tab index again
+                    panel.unregisterDocument();
+                    panel.getTabbedPaneForDocuments().remove(i); //now remove it
+                }
+                else {
+                    while (i > 0 && i > panel.getTabbedPaneForDocuments().getTabCount()) { // while its still wrong
+                        i = panel.getTabbedPaneForDocuments().indexOfComponent(dp); // get the current tab index again
+                    }
+                    panel.unregisterDocument();
+                    panel.getTabbedPaneForDocuments().remove(i); //now remove it
+                }
+            }
+            catch (final IndexOutOfBoundsException e) {
+                catchCloseErr(dp);
+            }
+        }
+
+        /** update the state of this action */
+        public void update() {
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * close all documents currently shown.
+     *
+     * <p>This action simply loops through all open documents and uses an instance
+     * of SHTMLFileCloseAction to perform the actual closing on each of them.</p>
+     */
+    static class SHTMLFileCloseAllAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelMultipleDocImpl panel;
+
+        /** constructor
+         * @param panel TODO*/
+        public SHTMLFileCloseAllAction(final SHTMLPanelMultipleDocImpl panel) {
+            super(SHTMLPanelMultipleDocImpl.closeAllAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        /** close all open documents */
+        public void actionPerformed(final ActionEvent ae) {
+            final SHTMLFileCloseAction a = (SHTMLFileCloseAction) panel.dynRes
+                .getAction(SHTMLPanelMultipleDocImpl.closeAction);
+            for (int i = panel.getTabbedPaneForDocuments().getTabCount(); i > 0; i--) {
+                //System.out.println("CloseAll, close tab no " + i);
+                a.closeDocument(i - 1, ae, false);
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * exit the application.
+     *
+     * <p>This will only exit the application, if<ul>
+     * <li>no documents are open or </li>
+     * <li>documents are open that do not need to be saved or </li>
+     * <li>documents are open and are saved successfully prior to close or </li>
+     * <li>documents are open for which the user explicitly opted not
+     *        to save them </li>
+     * </ul></p>
+     */
+    static class SHTMLFileExitAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelMultipleDocImpl panel;
+
+        public SHTMLFileExitAction(final SHTMLPanelMultipleDocImpl panel) {
+            super(SHTMLPanelImpl.exitAction);
+            this.panel = panel;
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            saveRelevantPrefs();
+            new SHTMLFileCloseAllAction(panel).actionPerformed(ae);
+            if (panel.getTabbedPaneForDocuments().getTabCount() == 0) {
+                System.exit(0);
+            }
+            panel.updateActions();
+        }
+
+        public void saveRelevantPrefs() {
+            /* ---- save splitpane sizes start -------------- */
+            panel.savePrefs();
+            /* ---- save splitpane sizes end -------------- */
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /** create a new empty document and show it */
+    static class SHTMLFileNewAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelMultipleDocImpl panel;
+
+        public SHTMLFileNewAction(final SHTMLPanelMultipleDocImpl panel) {
+            super(SHTMLPanelMultipleDocImpl.newAction);
+            this.panel = panel;
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK));
+        }
+
+        /** create a new empty document and show it */
+        public void actionPerformed(final ActionEvent ae) {
+            panel.createNewDocumentPane(); // create a new empty document
+            panel.getTabbedPaneForDocuments().setSelectedComponent( // add the document to the
+                panel.getTabbedPaneForDocuments().add(panel.getDocumentPane().getDocumentName(),
+                    panel.getDocumentPane())); // tabbed pane for display
+            panel.registerDocument();
+            panel.updateActions();
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /** open an existing document from file and show it */
+    static class SHTMLFileOpenAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelMultipleDocImpl panel;
+
+        public SHTMLFileOpenAction(final SHTMLPanelMultipleDocImpl panel) {
+            super(SHTMLPanelMultipleDocImpl.openAction);
+            this.panel = panel;
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Preferences prefs = Preferences.userNodeForPackage(panel.getClass());
+            final JFileChooser chooser = new JFileChooser(); // create a file chooser
+            final ExampleFileFilter filter = new ExampleFileFilter(); // create a filter
+            filter.addExtension("htm");
+            filter.addExtension("html");
+            filter.setDescription(Util.getResourceString("htmlFileDesc"));
+            chooser.setFileFilter(filter); // apply the file filter
+            final String lastFileName = prefs.get(SHTMLPanelImpl.FILE_LAST_OPEN, "");
+            if (lastFileName.length() > 0) {
+                chooser.setCurrentDirectory(new File(lastFileName).getParentFile());
+            }
+            final int returnVal = // ..and show the file chooser
+            chooser.showOpenDialog((Component) ae.getSource());
+            if (returnVal == JFileChooser.APPROVE_OPTION) { // if a file was selected
+                final File file = chooser.getSelectedFile();
+                prefs.put(SHTMLPanelImpl.FILE_LAST_OPEN, file.getAbsolutePath());
+                openDocument(file);
+            }
+            panel.updateActions();
+        }
+
+        public void openDocument(final File file) {
+            openDocument(file, null);
+        }
+
+        public void openDocument(final File file, final DocumentPane.DocumentPaneListener listener) {
+            int openDocNo = -1;
+            try {
+                openDocNo = getOpenDocument(file.toURI().toURL().toString());
+            }
+            catch (final MalformedURLException mue) {
+            }
+            if (openDocNo > -1) {
+                panel.getTabbedPaneForDocuments().setSelectedIndex(openDocNo);
+            }
+            else {
+                final FileLoader loader = new FileLoader(file, null, listener);
+                loader.start();
+            }
+        }
+
+        public int getOpenDocument(final String url) {
+            int tabNo = -1;
+            final int openDocCount = panel.getTabbedPaneForDocuments().getTabCount();
+            int i = 0;
+            while (i < openDocCount && tabNo < 0) {
+                final URL source = ((DocumentPane) panel.getTabbedPaneForDocuments().getComponentAt(i)).getSource();
+                if (source != null) {
+                    if (source.toString().equalsIgnoreCase(url)) {
+                        tabNo = i;
+                    }
+                }
+                i++;
+            }
+            return tabNo;
+        }
+
+        /**
+         * get a FileLoader object for the document currently active
+         *
+         * @param url  the url of the file to open
+         */
+        public FileLoader createFileLoader(final URL url) {
+            return new FileLoader(new File(url.getFile()), null);
+        }
+
+        /**
+         * Helper class for being able to load a document in a separate thread.
+         * Using a separate thread will not cause the application to block during
+         * a lengthy load operation
+         */
+        class FileLoader extends Thread {
+            File file;
+            Component owner;
+            DocumentPane.DocumentPaneListener l;
+
+            public FileLoader(final File file, final Component owner) {
+                this.file = file;
+                this.owner = owner;
+            }
+
+            public FileLoader(final File file, final Component owner, final DocumentPane.DocumentPaneListener listener) {
+                this(file, owner);
+                l = listener;
+            }
+
+            public void run() {
+                try {
+                    JOptionPane.getFrameForComponent(panel);
+                    panel.setDocumentPane(new DocumentPane(file.toURI().toURL(), 0/*, renderMode*/));
+                    if (l != null) {
+                        panel.getDocumentPane().addDocumentPaneListener(l);
+                    }
+                    panel.getTabbedPaneForDocuments().setSelectedComponent(
+                        panel.getTabbedPaneForDocuments().add(panel.getDocumentPane().getDocumentName(),
+                            panel.getDocumentPane()));
+                    panel.registerDocument();
+                }
+                catch (final Exception e) {
+                    Util.errMsg(owner, Util.getResourceString("unableToOpenFileError"), e);
+                }
+            }
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /** save a document */
+    static class SHTMLFileSaveAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLFileSaveAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelMultipleDocImpl.saveAction);
+            this.panel = panel;
+            getProperties();
+            putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK));
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            if (!panel.getDocumentPane().isNewDoc()) {
+                final FileSaver saver = new FileSaver(panel.getDocumentPane());
+                saver.setName("FileSaver");
+                saver.start();
+            }
+            else {
+                panel.dynRes.getAction(SHTMLPanelMultipleDocImpl.saveAsAction).actionPerformed(ae);
+            }
+            panel.updateActions();
+        }
+
+        /**
+         * Helper class for being able to save a document in a separate thread.
+         * Using a separate thread will not cause the application to block during
+         * a lengthy save operation
+         */
+        class FileSaver extends Thread {
+            DocumentPane dp;
+            Component owner;
+
+            FileSaver(final DocumentPane dp) {
+                setPriority(Thread.MIN_PRIORITY);
+                this.dp = dp;
+            }
+
+            public void run() {
+                panel.doSave(dp);
+            }
+        }
+
+        public void update() {
+            final boolean isEnabled = panel.getSHTMLEditorPane() != null;
+            boolean saveInProgress = false;
+            boolean needsSaving = false;
+            if (isEnabled) {
+                saveInProgress = panel.getDocumentPane().saveInProgress();
+                needsSaving = panel.getDocumentPane().needsSaving();
+            }
+            this.setEnabled(isEnabled && needsSaving && !saveInProgress);
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    static class SHTMLFileSaveAllAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelMultipleDocImpl panel;
+
+        public SHTMLFileSaveAllAction(final SHTMLPanelMultipleDocImpl panel) {
+            super(SHTMLPanelMultipleDocImpl.saveAllAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final int count = panel.getTabbedPaneForDocuments().getTabCount();
+            for (int i = 0; i < count; i++) {
+                panel.getTabbedPaneForDocuments().setSelectedIndex(i);
+                panel.setDocumentPane((DocumentPane) panel.getTabbedPaneForDocuments().getSelectedComponent());
+                if (panel.getDocumentPane().needsSaving()) {
+                    panel.dynRes.getAction(SHTMLPanelMultipleDocImpl.saveAction).actionPerformed(ae);
+                }
+            }
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.getSHTMLEditorPane() != null) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * save a document under a different name and/or location
+     *
+     * <p>If a file already exists at the chosen location / name, the method
+     * will ask the user if the existing file shall be overwritten.
+     */
+    static class SHTMLFileSaveAsAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelMultipleDocImpl panel;
+
+        public SHTMLFileSaveAsAction(final SHTMLPanelMultipleDocImpl panel) {
+            super(SHTMLPanelMultipleDocImpl.saveAsAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            boolean canSave = true;
+            final Preferences prefs = Preferences.userNodeForPackage(panel.getClass());
+            final JFileChooser chooser = new JFileChooser();
+            final ExampleFileFilter filter = new ExampleFileFilter();
+            filter.addExtension("htm");
+            filter.addExtension("html");
+            filter.setDescription(Util.getResourceString("htmlFileDesc"));
+            chooser.setFileFilter(filter);
+            final String lastSaveFileName = prefs.get(SHTMLPanelImpl.FILE_LAST_SAVE, "");
+            if (lastSaveFileName.length() > 0) {
+                chooser.setCurrentDirectory(new File(lastSaveFileName).getParentFile());
+            }
+            final URL sourceUrl = panel.getDocumentPane().getSource();
+            String fName;
+            if (sourceUrl != null) {
+                fName = sourceUrl.getFile();
+            }
+            else {
+                fName = panel.getDocumentPane().getDocumentName();
+                fName = Util.removeChar(fName, ' ');
+            }
+            if (fName.indexOf(Util.CLASS_SEPARATOR) < 0) {
+                chooser.setSelectedFile(new File(fName + ".htm"));
+            }
+            else {
+                chooser.setSelectedFile(new File(fName));
+            }
+            final int result = chooser.showSaveDialog((Component) ae.getSource());
+            if (result == JFileChooser.APPROVE_OPTION) {
+                final File selection = chooser.getSelectedFile();
+                prefs.put(SHTMLPanelImpl.FILE_LAST_SAVE, selection.getAbsolutePath());
+                if (selection.exists()) {
+                    final String newName = selection.getName();
+                    canSave = Util.msg(JOptionPane.YES_NO_OPTION, "confirmSaveAs", "fileExistsQuery", newName, " ");
+                }
+                if (canSave) {
+                    try {
+                        final NewFileSaver saver = new NewFileSaver(panel.getDocumentPane(), selection.toURI().toURL(),
+                            panel.getActiveTabNo());
+                        saver.setName("NewFileSaver");
+                        saver.start();
+                    }
+                    catch (final Exception ex) {
+                        Util.errMsg((Component) ae.getSource(), Util.getResourceString("cantCreateURLError")
+                                + selection.getAbsolutePath(), ex);
+                    }
+                }
+            }
+            panel.updateActions();
+        }
+
+        /**
+         * Helper class for being able to save a document in a separate thread.
+         * Using a separate thread will not cause the application to block during
+         * a lengthy save operation
+         */
+        class NewFileSaver extends Thread {
+            DocumentPane dp;
+            URL url;
+            int activeTabNo;
+            DocumentPane.DocumentPaneListener l;
+
+            NewFileSaver(final DocumentPane dp, final URL url, final int activeTabNo) {
+                this.dp = dp;
+                this.url = url;
+                this.activeTabNo = activeTabNo;
+            }
+
+            NewFileSaver(final DocumentPane dp, final URL url, final int activeTabNo,
+                         final DocumentPane.DocumentPaneListener listener) {
+                this(dp, url, activeTabNo);
+                l = listener;
+            }
+
+            public void run() {
+                dp.setSource(url);
+                panel.doSave(dp);
+                if (dp.saveSuccessful) {
+                    panel.getTabbedPaneForDocuments().setTitleAt(
+                        panel.getTabbedPaneForDocuments().indexOfComponent(dp), dp.getDocumentName());
+                    if (l != null) {
+                        dp.addDocumentPaneListener(l);
+                    }
+                }
+            }
+        }
+
+        /**
+         * get a FileSaver object for the document currently active
+         *
+         * @param url  the url of the file to save
+         */
+        public NewFileSaver createNewFileSaver(final URL url) {
+            return new NewFileSaver(panel.getDocumentPane(), url, panel.getActiveTabNo());
+        }
+
+        /**
+         * get a FileSaver object for the document currently active
+         *
+         * @param url  the url of the file to save
+         */
+        public NewFileSaver createNewFileSaver(final URL url, final DocumentPane.DocumentPaneListener listener) {
+            return new NewFileSaver(panel.getDocumentPane(), url, panel.getActiveTabNo(), listener);
+        }
+
+        public void update() {
+            final boolean isEnabled = panel.getSHTMLEditorPane() != null;
+            boolean saveInProgress = false;
+            if (isEnabled) {
+                saveInProgress = panel.getDocumentPane().saveInProgress();
+            }
+            this.setEnabled(isEnabled && !saveInProgress);
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * a slot for testing certain things conveniently during development
+     */
+    static class SHTMLTestAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLTestAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.testAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLEditorPane().insertBreak();
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /** show information about SimplyHTML in a dialog */
+    static class SHTMLHelpAppInfoAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SHTMLHelpAppInfoAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.aboutAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            final Frame parent = JOptionPane.getFrameForComponent(panel);
+            final AboutBox dlg = new AboutBox(parent);
+            Util.center(parent, dlg);
+            dlg.setModal(true);
+            dlg.setVisible(true);
+            panel.repaint();
+            panel.updateActions();
+        }
+
+        public void update() {
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+
+    /**
+     * action to set a reference to the default style sheet
+     * (for being able to use an already existing style sheet
+     * without having to define named styles)
+     */
+    static class SetDefaultStyleRefAction extends AbstractAction implements SHTMLAction {
+        /**
+         *
+         */
+        private final SHTMLPanelImpl panel;
+
+        public SetDefaultStyleRefAction(final SHTMLPanelImpl panel) {
+            super(SHTMLPanelImpl.setDefaultStyleRefAction);
+            this.panel = panel;
+            getProperties();
+        }
+
+        public void actionPerformed(final ActionEvent ae) {
+            panel.getSHTMLDocument().insertStyleRef();
+            panel.updateActions();
+        }
+
+        public void update() {
+            if (panel.isHtmlEditorActive()) {
+                this.setEnabled(false);
+                return;
+            }
+            if (panel.getSHTMLEditorPane() != null && !panel.getSHTMLDocument().hasStyleRef()) {
+                this.setEnabled(true);
+            }
+            else {
+                this.setEnabled(false);
+            }
+        }
+
+        public void getProperties() {
+            SHTMLPanelImpl.getActionProperties(this, (String) getValue(Action.NAME));
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLEditorPane.java b/src/com/lightdev/app/shtm/SHTMLEditorPane.java
new file mode 100644
index 0000000..3dff914
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLEditorPane.java
@@ -0,0 +1,3717 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragSourceDragEvent;
+import java.awt.dnd.DragSourceDropEvent;
+import java.awt.dnd.DragSourceEvent;
+import java.awt.dnd.DragSourceListener;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+import java.awt.dnd.DropTargetListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Vector;
+import java.util.prefs.Preferences;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ActionMap;
+import javax.swing.Icon;
+import javax.swing.InputMap;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JPopupMenu;
+import javax.swing.KeyStroke;
+import javax.swing.TransferHandler;
+import javax.swing.event.CaretEvent;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Caret;
+import javax.swing.text.Element;
+import javax.swing.text.ElementIterator;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.NavigationFilter;
+import javax.swing.text.Position.Bias;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLDocument;
+
+/**
+ * An editor pane for application SimplyHTML.
+ *
+ * <p>This is extending <code>JEditorPane</code> by cut and paste
+ * and drag and drop for HTML text.
+ * <code>JEditorPane</code> inherits cut and paste from <code>
+ * JTextComponent</code> where handling for plain text is implemented only.
+ * <code>JEditorPane</code> has no additional functionality to add cut
+ * and paste for the various content types it supports
+ * (such as 'text/html').</p>
+ *
+ * <p>In stage 4 support for caret movement inside tables and
+ * table manipulation methods are added.</p>
+ *
+ * <p>In stage 6 support for list manipulation was added.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ *
+ * @see com.lightdev.app.shtm.HTMLText
+ * @see com.lightdev.app.shtm.HTMLTextSelection
+ */
+public class SHTMLEditorPane extends JEditorPane implements DropTargetListener, DragSourceListener, DragGestureListener {
+	
+	public enum PasteMode
+	{
+		PASTE_HTML("Paste as HTML"), PASTE_PLAIN_TEXT("Paste as plain-text");
+		
+		private final String displayName;
+
+		private PasteMode(final String displayName)
+		{
+			this.displayName = displayName;
+		}
+		
+		public String getDisplayName()
+		{
+			return displayName;
+		}
+		
+		public PasteMode invert()
+		{
+			if (this == PASTE_HTML)
+				return PASTE_PLAIN_TEXT;
+			else if (this == PASTE_PLAIN_TEXT)
+				return PASTE_HTML;
+			else
+				throw new RuntimeException("Expected value for SHTMLEditorPane.PasteMode: " + name());
+		}
+		
+		public static PasteMode getValueFromPrefs()
+		{
+			// try to get freeplane pref value, and use simplyhtml pref value if that fails
+			Preferences prefs = Preferences.userNodeForPackage(SHTMLEditorPane.class);
+			PasteMode pm = SHTMLEditorPane.PasteMode.valueOf(
+					SHTMLEditorPane.PasteMode.class, Util.getPreference(
+							"default_paste_mode", prefs.get(
+									PrefsDialog.PREFS_DEFAULT_PASTE_MODE,
+									SHTMLEditorPane.PasteMode.PASTE_HTML
+											.name())));
+			return pm;
+		}
+	}
+	
+    private static final boolean OLD_JAVA_VERSION = System.getProperty("java.version").compareTo("1.5.0") < 0;
+    private JPopupMenu popup;
+    private final ListManager listManager = new ListManager();
+    private PasteMode pasteMode;
+    private boolean forceConstantPasteMode;
+
+    /**
+     * construct a new <code>SHTMLEditorPane</code>
+     */
+    public SHTMLEditorPane() {
+        super();
+        setCaretColor(Color.black);
+        setNavigationFilter(new MyNavigationFilter());
+        addMouseListener(new MouseAdapter() {
+            public void mousePressed(final MouseEvent e) {
+                maybeShowPopup(e);
+            }
+
+            public void mouseReleased(final MouseEvent e) {
+                maybeShowPopup(e);
+            }
+
+            public void mouseClicked(final MouseEvent ev) {
+                if ((ev.getModifiers() & MouseEvent.CTRL_MASK) != 0) {
+                    final String linkURL = getURLOfExistingLink();
+                    if (linkURL != null) {
+                        final SHTMLPanelImpl panel = SHTMLPanelImpl.getOwnerSHTMLPanel((Component) ev.getSource());
+                        panel.openHyperlink(linkURL);
+                    }
+                }
+            }
+
+            private void maybeShowPopup(final MouseEvent e) {
+                if (popup != null && e.isPopupTrigger()) {
+                    popup.show(e.getComponent(), e.getX(), e.getY());
+                }
+            }
+        });
+        setPasteModeFromPrefs();
+        /** implement customized caret movement */
+        adjustKeyBindings();
+        /** init drag and drop */
+        initDnd();
+    }
+    
+    public PasteMode getPasteMode() {
+		if (forceConstantPasteMode)
+		{ 
+			return pasteMode;
+		}
+		else
+		{
+			return PasteMode.getValueFromPrefs();
+		}
+	}
+
+	public void setPasteMode(final PasteMode pasteMode) {
+		this.pasteMode = pasteMode;
+		this.forceConstantPasteMode = true;
+	}
+	
+	public void setPasteModeFromPrefs()
+	{
+		this.forceConstantPasteMode = false;
+	}
+
+	/**
+     * adjust the key bindings of the key map existing for this
+     * editor pane to our needs (i.e. add actions to certain keys
+     * such as tab/shift tab for caret movement inside tables, etc.)
+     *
+     * This method had to be redone for using InputMap / ActionMap
+     * instead of Keymap.
+     */
+    private void adjustKeyBindings() {
+        final ActionMap myActionMap = new ActionMap();
+        final InputMap myInputMap = new InputMap();
+        final KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
+        myActionMap.put(SHTMLPanelImpl.nextTableCellAction, new TabAction(SHTMLPanelImpl.nextTableCellAction));
+        myInputMap.put(tab, SHTMLPanelImpl.nextTableCellAction);
+        final KeyStroke shiftTab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK);
+        myActionMap.put(SHTMLPanelImpl.prevTableCellAction, new ShiftTabAction(SHTMLPanelImpl.prevTableCellAction));
+        myInputMap.put(shiftTab, SHTMLPanelImpl.prevTableCellAction);
+        final KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
+        myActionMap.put(newListItemAction, new NewParagraphAction());
+        myInputMap.put(enter, newListItemAction);
+        final KeyStroke lineBreak = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.SHIFT_MASK);
+        myActionMap.put(insertLineBreakAction, new InsertLineBreakAction());
+        myInputMap.put(lineBreak, insertLineBreakAction);
+        final KeyStroke backspace = KeyStroke.getKeyStroke('\b', 0);
+        myActionMap.put(deletePrevCharAction, new DeletePrevCharAction());
+        myInputMap.put(backspace, deletePrevCharAction);
+        final KeyStroke delete = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
+        myActionMap.put(deleteNextCharAction, new DeleteNextCharAction());
+        myInputMap.put(delete, deleteNextCharAction);
+        myActionMap.put(moveUpAction, new MoveUpAction());
+        myInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), moveUpAction);
+        myActionMap.put(moveDownAction, new MoveDownAction());
+        myInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), moveDownAction);
+        myActionMap.put(homeAction, new HomeAction());
+        myInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), homeAction);
+        myActionMap.put(endAction, new EndAction());
+        myInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), endAction);
+        myActionMap.put(shiftHomeAction, new ShiftHomeAction());
+        myInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, KeyEvent.SHIFT_MASK), shiftHomeAction);
+        myActionMap.put(shiftEndAction, new ShiftEndAction());
+        myInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, KeyEvent.SHIFT_MASK), shiftEndAction);
+        //myActionMap.put("TTH", getDnew SHTMLEditorKitActions.ToggleTableHeaderCellAction(null));
+        //myInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, KeyEvent.SHIFT_MASK), "TTH");    
+        myActionMap.setParent(getActionMap());
+        myInputMap.setParent(getInputMap());
+        setActionMap(myActionMap);
+        setInputMap(JComponent.WHEN_FOCUSED, myInputMap);
+        /*
+         implementation before 1.4.1
+         -------------------------------------
+
+        Keymap map = getKeymap();
+        KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
+        map.addActionForKeyStroke(tab, new NextTableCellAction(map.getAction(tab)));
+        KeyStroke shiftTab = KeyStroke.getKeyStroke(
+                                KeyEvent.VK_TAB, InputEvent.SHIFT_MASK);
+        map.addActionForKeyStroke(shiftTab,
+                        new PrevTableCellAction(map.getAction(shiftTab)));
+        setKeymap(map);
+        */
+    }
+
+    private static gnu.regexp.RE pattern1 = null;
+    private static gnu.regexp.RE pattern2 = null;
+
+    /* (non-Javadoc)
+    * @see javax.swing.JComponent#processKeyBinding(javax.swing.KeyStroke, java.awt.event.KeyEvent, int, boolean)
+    */
+    protected boolean processKeyBinding(final KeyStroke ks, final KeyEvent e, final int condition, final boolean pressed) {
+        final int maximumEndSelection = ((SHTMLDocument) getDocument()).getLastDocumentPosition();
+        if (getSelectionStart() >= maximumEndSelection
+                && !(ks.getKeyCode() == KeyEvent.VK_LEFT || ks.getKeyCode() == KeyEvent.VK_UP || ks.getKeyCode() == KeyEvent.VK_HOME)) {
+            return true;
+        }
+        if (getSelectionEnd() >= maximumEndSelection) {
+            setSelectionEnd(maximumEndSelection - 1);
+        }
+        return super.processKeyBinding(ks, e, condition, pressed);
+    }
+
+    /**
+       * Convenience method for setting the document text
+       * contains hack around JDK bug 4799813
+       * see http://developer.java.sun.com/developer/bugParade/bugs/4799813.html
+       * regression in 1.4.x, to be fixed in 1.5
+       * When setting the text to be "& footext", it becomes "&footext" (space disappears)
+       * same ocurrs for "</a> &amp;", it becomes "</a>&amp;" (space disappears)
+       * with the hack it now does not occur anymore.
+       * @param sText the html-text of the document
+       */
+    public void setText(String sText) {
+        try {
+            if (System.getProperty("java.version").substring(0, 3).equals("1.4")) {
+                if (pattern1 == null) {
+                    pattern1 = new gnu.regexp.RE("(&\\w+;|&#\\d+;)(\\s| | )(?=<|&\\w+;|&#\\d+;)");
+                }
+                sText = pattern1.substituteAll(sText, "$1 $3");
+                if (pattern2 == null) {
+                    pattern2 = new gnu.regexp.RE("<(/[^>])>(\\s| | |\\n\\s+)(?! )(&\\w+;|&#\\d+;)");
+                }
+                sText = pattern2.substituteAll(sText, "<$1> $3$4");
+            }
+        }
+        catch (final gnu.regexp.REException ree) {
+            ree.printStackTrace();
+        }
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        doc.startCompoundEdit();
+        if (sText == null || sText.equals("")) {
+            sText = "<html><body><p></p></body></html>";
+        }
+        doc.putProperty(SHTMLDocument.AdditionalComments, null);
+        super.setText(sText);
+        setCaretPosition(0);
+        doc.endCompoundEdit();
+        if (OLD_JAVA_VERSION) {
+            SHTMLPanelImpl.getOwnerSHTMLPanel(this).purgeUndos();
+        }
+    }
+
+    private class MyNavigationFilter extends NavigationFilter {
+        /* (non-Javadoc)
+         * @see javax.swing.text.NavigationFilter#moveDot(javax.swing.text.NavigationFilter.FilterBypass, int, javax.swing.text.Position.Bias)
+         */
+        public void moveDot(final FilterBypass fb, int dot, final Bias bias) {
+            dot = getValidPosition(dot);
+            super.moveDot(fb, dot, bias);
+        }
+
+        /* (non-Javadoc)
+         * @see javax.swing.text.NavigationFilter#setDot(javax.swing.text.NavigationFilter.FilterBypass, int, javax.swing.text.Position.Bias)
+         */
+        public void setDot(final FilterBypass fb, int dot, final Bias bias) {
+            dot = getValidPosition(dot);
+            super.setDot(fb, dot, bias);
+        }
+    }
+
+    private int getValidPosition(int position) {
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        final int lastValidPosition = doc.getLastDocumentPosition() - 1;
+        if (position > lastValidPosition) {
+            position = lastValidPosition;
+        }
+        int startPos = 0;
+        if (doc.getDefaultRootElement().getElementCount() > 1) {
+            startPos = doc.getDefaultRootElement().getElement(1).getStartOffset();
+        }
+        final int validPosition = Math.max(position, startPos);
+        return validPosition;
+    }
+
+    private class DeletePrevCharAction extends AbstractAction {
+        public void actionPerformed(final ActionEvent actionEvent) {
+            final int selectionStart = getSelectionStart();
+            final int selectionEnd = getSelectionEnd();
+            final SHTMLDocument doc = (SHTMLDocument) getDocument();
+            if (selectionEnd >= doc.getLastDocumentPosition()) {
+                return;
+            }
+            if (selectionStart == selectionEnd) {
+                final boolean intervention = listManager.deletePrevChar(actionEvent);
+                if (intervention) {
+                    return;
+                }
+                // Prevent deletion of table cell.
+                final Element tableCell = selectionStart == 0 ? null : getTableCell(selectionStart - 1);
+                if (tableCell != null && tableCell.getEndOffset() == selectionStart) {
+                    performDefaultKeyStrokeAction(KeyEvent.VK_LEFT, 0, actionEvent);
+                    return;
+                }
+            }
+            performDefaultKeyStrokeAction('\b', 0, actionEvent);
+        }
+    }
+
+    private class DeleteNextCharAction extends AbstractAction {
+        public void actionPerformed(final ActionEvent actionEvent) {
+            final int selectionStart = getSelectionStart();
+            if (selectionStart == getSelectionEnd()) {
+                final SHTMLDocument doc = (SHTMLDocument) getDocument();
+                if (selectionStart >= doc.getLastDocumentPosition() - 1) {
+                    return;
+                }
+                boolean intervention = treatTables(actionEvent);
+                if (intervention) {
+                    return;
+                }
+                intervention = listManager.deleteNextChar(actionEvent);
+                if (intervention) {
+                    return;
+                }
+            }
+            performDefaultKeyStrokeAction(KeyEvent.VK_DELETE, 0, actionEvent);
+        }
+
+        /** Treats tables. Returns true if intervention was necessary. */
+        private boolean treatTables(final ActionEvent event) {
+            final int selectionStart = getSelectionStart();
+            final int nextPosition = selectionStart + 1;
+            Element elem = null;
+            final SHTMLDocument doc = getSHTMLDocument();
+            // Table cell element at the start of the selection
+            elem = getCurrentTableCell();
+            if (elem != null && elem.getEndOffset() == nextPosition) {
+                // Do nothing to avoid deletion of the whole cell.
+                //return;
+            }
+            if (nextPosition < doc.getLength()) {
+                // Table cell element at next position
+                elem = getTableCell(nextPosition);
+                if (elem != null && elem.getStartOffset() == nextPosition) {
+                    // In most cases, do nothing to avoid deletion of parts of the following table.
+                    final Element paragraphElement = getCurrentParagraphElement();
+                    final boolean emptyParagraph = elementIsEmptyParagraph(paragraphElement);
+                    if (!caretWithinTableCell() && emptyParagraph) {
+                        // Empty paragraph outside a table, before a table.
+                        return false;
+                    }
+                    else if (caretWithinTableCell() && emptyParagraph) {
+                        // Remove empty paragraph at the end of the cell. 
+                        removeElement(paragraphElement);
+                        setCaretPosition(getCaretPosition() - 1);
+                        return true;
+                    }
+                    else {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    private class MoveUpAction extends AbstractAction {
+        public void actionPerformed(final ActionEvent e) {
+            if (caretWithinTableCell()) {
+                if (getCaretPosition() == 0) {
+                    // The table is at the top of the document.
+                    // Insert new paragraph before the table.
+                    final Element tableElement = getCurrentTableCell().getParentElement().getParentElement();
+                    try {
+                        getSHTMLDocument().insertBeforeStart(tableElement, "<p></p>");
+                    }
+                    catch (final Exception ex) {
+                    }
+                }
+                if (tryDefaultKeyStrokeActionWithinCell(KeyEvent.VK_UP, 0, e)) {
+                    return;
+                }
+                final Element cellElement = getCurrentTableCell();
+                final Element rowElement = cellElement.getParentElement();
+                final Element tableElement = rowElement.getParentElement();
+                final int cellIndexInRow = rowElement.getElementIndex(cellElement.getStartOffset());
+                final int rowIndexInTable = tableElement.getElementIndex(rowElement.getStartOffset());
+                if (rowIndexInTable > 0) {
+                    final Element previousRowElement = tableElement.getElement(rowIndexInTable - 1);
+                    final int elementCount = previousRowElement.getElementCount();
+                    if (elementCount > 0) {
+                        final Element targetCellElement = previousRowElement.getElement(Math.min(elementCount,
+                            cellIndexInRow));
+                        setCaretPosition(targetCellElement.getEndOffset());
+                    }
+                    else {
+                        setCaretPosition(tableElement.getStartOffset());
+                    }
+                }
+                else {
+                    setCaretPosition(tableElement.getStartOffset());
+                }
+                //}
+            }
+            performDefaultKeyStrokeAction(KeyEvent.VK_UP, 0, e);
+        }
+    }
+
+    private class MoveDownAction extends AbstractAction {
+        public void actionPerformed(final ActionEvent e) {
+            if (caretWithinTableCell()) {
+                if (tryDefaultKeyStrokeActionWithinCell(KeyEvent.VK_DOWN, 0, e)) {
+                    return;
+                }
+                final Element cellElement = getCurrentTableCell();
+                final Element rowElement = cellElement.getParentElement();
+                final Element tableElement = rowElement.getParentElement();
+                final int cellIndexInRow = rowElement.getElementIndex(cellElement.getStartOffset());
+                final int rowIndexInTable = tableElement.getElementIndex(rowElement.getStartOffset());
+                if (rowIndexInTable < tableElement.getElementCount() - 1) {
+                    final Element nextRowElement = tableElement.getElement(rowIndexInTable + 1);
+                    final int elementCount = nextRowElement.getElementCount();
+                    if (elementCount > 0) {
+                        final Element targetCellElement = nextRowElement.getElement(Math.min(elementCount,
+                            cellIndexInRow));
+                        //Element targetInnerElement = targetCellElement.getElement(0); // p or p-implied.
+                        setCaretPosition(targetCellElement.getStartOffset() - 1);
+                    }
+                    else {
+                        setCaretPosition(tableElement.getEndOffset() - 1);
+                    }
+                }
+                else {
+                    setCaretPosition(tableElement.getEndOffset() - 1);
+                }
+                //}
+            }
+            performDefaultKeyStrokeAction(KeyEvent.VK_DOWN, 0, e);
+        }
+    }
+
+    private class HomeAction extends AbstractAction {
+        public void actionPerformed(final ActionEvent e) {
+            if (caretWithinTableCell()) {
+                if (tryDefaultKeyStrokeActionWithinCell(KeyEvent.VK_HOME, 0, e)) {
+                    return;
+                }
+                setCaretPosition(getCurrentParagraphElement().getStartOffset());
+            }
+            else {
+                performDefaultKeyStrokeAction(KeyEvent.VK_HOME, 0, e);
+            }
+        }
+    }
+
+    private class EndAction extends AbstractAction {
+        public void actionPerformed(final ActionEvent e) {
+            if (caretWithinTableCell()) {
+                if (tryDefaultKeyStrokeActionWithinCell(KeyEvent.VK_END, 0, e)) {
+                    return;
+                }
+                setCaretPosition(getCurrentParagraphElement().getEndOffset() - 1);
+            }
+            else {
+                performDefaultKeyStrokeAction(KeyEvent.VK_END, 0, e);
+            }
+        }
+    }
+
+    private class ShiftHomeAction extends AbstractAction {
+        public void actionPerformed(final ActionEvent e) {
+            if (caretWithinTableCell()) {
+                final int originalCaretPosition = getCaretPosition();
+                if (tryDefaultKeyStrokeActionWithinCell(KeyEvent.VK_HOME, KeyEvent.SHIFT_MASK, e)) {
+                    return;
+                }
+                final int newCaretPosition = getCurrentParagraphElement().getStartOffset();
+                if (newCaretPosition > originalCaretPosition) {
+                    select(originalCaretPosition, newCaretPosition);
+                }
+                else {
+                    select(newCaretPosition, originalCaretPosition);
+                }
+            }
+            else {
+                performDefaultKeyStrokeAction(KeyEvent.VK_HOME, KeyEvent.SHIFT_MASK, e);
+            }
+        }
+    }
+
+    private class ShiftEndAction extends AbstractAction {
+        public void actionPerformed(final ActionEvent e) {
+            if (caretWithinTableCell()) {
+                final int originalCaretPosition = getCaretPosition();
+                if (tryDefaultKeyStrokeActionWithinCell(KeyEvent.VK_END, KeyEvent.SHIFT_MASK, e)) {
+                    return;
+                }
+                final int newCaretPosition = getCurrentParagraphElement().getEndOffset() - 1;
+                if (newCaretPosition > originalCaretPosition) {
+                    select(originalCaretPosition, newCaretPosition);
+                }
+                else {
+                    select(newCaretPosition, originalCaretPosition);
+                }
+            }
+            else {
+                performDefaultKeyStrokeAction(KeyEvent.VK_END, KeyEvent.SHIFT_MASK, e);
+            }
+        }
+    }
+
+    /* ------- list manipulation start ------------------- */
+    /**
+     * apply a set of attributes to the list the caret is
+     * currently in (if any)
+     *
+     * @param a  the set of attributes to apply
+     */
+    public void applyListAttributes(final AttributeSet a) {
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        final Element list = listManager.getListElement(getSelectionStart());
+        if (list != null) {
+            if (a.getAttributeCount() > 0) {
+                doc.addAttributes(list, a);
+                /**
+                 * for some reason above code does not show the changed attributes
+                 * of the table, although the element really has them (maybe somebody
+                 * could let me know why...). Therefore we update the editor pane
+                 * contents comparably rude (any other more elegant alternatives
+                 * welcome!)
+                 *
+                 * --> found out why: the swing package does not render short hand
+                 *                    properties such as MARGIN or PADDING. When
+                 *                    contained in a document inside an AttributeSet
+                 *                    they already have to be split into MARGIN-TOP,
+                 *                    MARGIN-LEFT, etc.
+                 *                    adjusted AttributeComponents accordingly so
+                 *                    we don't need refresh anymore
+                 */
+                //refresh();
+            }
+        }
+    }
+
+    /**
+     * <code>Action</code> to create a new paragraph element, which
+     * may be a paragraph proper or a list item.
+     */
+    private class NewParagraphAction extends AbstractAction {
+        /** construct a <code>NewParagraphAction</code> */
+        public NewParagraphAction() {
+        }
+
+        /**
+         * create a new list item, when the caret is inside a list
+         *
+         * <p>The new item is created after the item at the caret position</p>
+         */
+        public void actionPerformed(final ActionEvent ae) {
+            try {
+                final int caretPosition = getCaretPosition();
+                // Turn paragraph starting with "* " into a bullet list.
+                Element paragraphElement = getCurrentParagraphElement();
+                String content = elementToHTML(paragraphElement);
+                if (content.matches("(?ims)\\s*<p[^>]*>\\s*\\* .*</p>\\s*")) {
+                    final String newContent = "<ul><li>"
+                            + content.replaceAll("(?ims)\\s*<p[^>]*>\\s*\\* (.*)</p>\\s*", "$1") + "</li></ul>";
+                    getSHTMLDocument().setOuterHTML(paragraphElement, newContent);
+                    setCaretPosition(paragraphElement.getEndOffset() - 1);
+                    return;
+                }
+                // Turn paragraph starting with "1. " into a numbered list.
+                paragraphElement = getCurrentParagraphElement();
+                content = elementToHTML(paragraphElement);
+                if (content.matches("(?ims)\\s*<p[^>]*>\\s*1\\. .*</p>\\s*")) {
+                    final String newContent = "<ol><li>"
+                            + content.replaceAll("(?ims)\\s*<p[^>]*>\\s*1\\. (.*)</p>\\s*", "$1") + "</li></ol>";
+                    getSHTMLDocument().setOuterHTML(paragraphElement, newContent);
+                    setCaretPosition(paragraphElement.getEndOffset() - 1);
+                    return;
+                }
+                // if we are in a list, create a new item
+                final Element listItemElement = listManager.getListItemElement(caretPosition);
+                if (listItemElement != null) {
+                    listManager.newListItem();
+                    return;
+                }
+                // we are not in a list, call alternate action
+                else {
+                    performDefaultKeyStrokeAction(KeyEvent.VK_ENTER, 0, ae);
+                }
+            }
+            catch (final Exception e) {
+                Util.errMsg(null, e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * toggle list formatting on or off for the currently
+     * selected text portion.
+     *
+     * <p>Switches list display on for the given type, if the selection
+     * contains parts not formatted as list or parts formatted as list
+     * of another type.</p>
+     *
+     * <p>Switches list formatting off, if the selection contains
+     * only parts formatted as list of the given type.</p>
+     *
+     * @param listTag  the list tag type to toggle on or off (UL or OL)
+     * @param attributeSet  the attributes to use for the list to toggle to
+     * @param forceOff  indicator for toggle operation. If true, possibly
+     * exisiting list formatting inside the selected parts always is switched
+     * off. If false, the method decides, if list formatting for the parts
+     * inside the selection needs to be switched on or off.
+     */
+    public void toggleList(final String listTag, final AttributeSet attributeSet, final boolean forceOff) {
+        listManager.toggleList(listTag, attributeSet, forceOff);
+    }
+
+    /** range indicator for applying attributes to the current cell only */
+    public static final int THIS_CELL = 0;
+    /** range indicator for applying attributes to cells of the current column only */
+    public static final int THIS_COLUMN = 1;
+    /** range indicator for applying attributes to cells of the current row only */
+    public static final int THIS_ROW = 2;
+    /** range indicator for applying attributes to all cells */
+    public static final int ALL_CELLS = 3;
+    /** default table width */
+    public static final String DEFAULT_TABLE_WIDTH = "80%";
+    /** default vertical alignment */
+    public static final String DEFAULT_VERTICAL_ALIGN = "top";
+
+    /**
+     * Insert a new table.
+     *
+     * @param colCount the number of columns the new table shall have
+     */
+    public void insertNewTable(final int colCount) {
+        final int selectionStart = getSelectionStart();
+        final int start = selectionStart;
+        final StringWriter sw = new StringWriter();
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        final SHTMLWriter w = new SHTMLWriter(sw, doc);
+        // some needed constants
+        final String table = HTML.Tag.TABLE.toString();
+        final String tr = HTML.Tag.TR.toString();
+        final String td = HTML.Tag.TD.toString();
+        final String th = HTML.Tag.TH.toString();
+        final String p = HTML.Tag.P.toString();
+        final boolean insertPlainTable = !Util.preferenceIsTrue("table.insertStyle", "true");
+        final boolean insertTableHeader = Util.preferenceIsTrue("table.insertHeader");
+        try {
+            // the attribute set to use for applying attributes to tags
+            final SimpleAttributeSet tableAttributeSet = new SimpleAttributeSet();
+            // build table attribute
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.WIDTH, DEFAULT_TABLE_WIDTH);
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_STYLE, "solid");
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_TOP_WIDTH, "0");
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_RIGHT_WIDTH, "0");
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_BOTTOM_WIDTH, "0");
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_LEFT_WIDTH, "0");
+            tableAttributeSet.addAttribute(HTML.Attribute.BORDER, "0");
+            w.writeStartTag(table, insertPlainTable ? null : tableAttributeSet);
+            // get width of each cell according to column count
+            // build cell width attribute
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.WIDTH,
+                Integer.toString(100 / colCount) + Util.pct);
+            tableAttributeSet.addAttribute(HTML.Attribute.VALIGN, DEFAULT_VERTICAL_ALIGN);
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_TOP_WIDTH, "1");
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_RIGHT_WIDTH, "1");
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_BOTTOM_WIDTH, "1");
+            Util.styleSheet().addCSSAttribute(tableAttributeSet, CSS.Attribute.BORDER_LEFT_WIDTH, "1");
+            final SimpleAttributeSet pSet = new SimpleAttributeSet();
+            Util.styleSheet().addCSSAttribute(pSet, CSS.Attribute.MARGIN_TOP, "1");
+            Util.styleSheet().addCSSAttribute(pSet, CSS.Attribute.MARGIN_RIGHT, "1");
+            Util.styleSheet().addCSSAttribute(pSet, CSS.Attribute.MARGIN_BOTTOM, "1");
+            Util.styleSheet().addCSSAttribute(pSet, CSS.Attribute.MARGIN_LEFT, "1");
+            tableAttributeSet.removeAttribute(HTML.Attribute.BORDER);
+            if (insertTableHeader) {
+                w.writeStartTag(tr, null);
+                for (int i = 0; i < colCount; i++) {
+                    w.writeStartTag(th, insertPlainTable ? null : tableAttributeSet);
+                    w.writeStartTag(p, insertPlainTable ? null : pSet);
+                    w.writeEndTag(p);
+                    w.writeEndTag(th);
+                }
+                w.writeEndTag(tr);
+            }
+            w.writeStartTag(tr, null);
+            for (int i = 0; i < colCount; i++) {
+                w.writeStartTag(td, insertPlainTable ? null : tableAttributeSet);
+                w.writeStartTag(p, insertPlainTable ? null : pSet);
+                w.writeEndTag(p);
+                w.writeEndTag(td);
+            }
+            w.writeEndTag(tr);
+            w.writeEndTag(table);
+            // read table html into document
+            Element para = doc.getParagraphElement(selectionStart);
+            if (para == null) {
+                throw new Exception("no text selected");
+            }
+            for (Element parent = para.getParentElement(); !parent.getName().equalsIgnoreCase(HTML.Tag.BODY.toString())
+                    && !parent.getName().equalsIgnoreCase(HTML.Tag.TD.toString()); para = parent, parent = parent
+                .getParentElement()) {
+                ;
+            }
+            if (para != null) {
+                try {
+                    doc.startCompoundEdit();
+                    doc.insertBeforeStart(para, sw.getBuffer().toString());
+                }
+                catch (final Exception e) {
+                    Util.errMsg(null, e.getMessage(), e);
+                }
+                finally {
+                    doc.endCompoundEdit();
+                }
+                //      w.write(para);
+                //doc.replaceHTML(para, 1, sw.getBuffer().toString());
+            }
+        }
+        catch (final Exception ex) {
+            Util.errMsg(null, ex.getMessage(), ex);
+        }
+        select(start, start);
+    }
+
+    /**
+     * apply a new anchor to the currently selected text
+     *
+     * <p>If nothing is selected, this method does nothing</p>
+     *
+     * @param anchorName  the name of the new anchor
+     */
+    public void insertAnchor(final String anchorName) {
+        if (getSelectionStart() != getSelectionEnd()) {
+            final SimpleAttributeSet aSet = new SimpleAttributeSet();
+            aSet.addAttribute(HTML.Attribute.NAME, anchorName);
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            set.addAttribute(HTML.Tag.A, aSet);
+            applyAttributes(set, false);
+        }
+    }
+
+    /**
+     * insert a line break (i.e. a break for which paragraph
+     * spacing is not applied)
+     */
+    public void insertBreak() {
+        final int caretPos = getCaretPosition();
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        try {
+            ((SHTMLEditorKit) getEditorKit()).insertHTML(doc, caretPos, "<BR>", 0, 0, HTML.Tag.BR);
+        }
+        catch (final Exception e) {
+        }
+        setCaretPosition(caretPos + 1);
+    }
+
+    /**
+     * set a text link at the current selection replacing the selection
+     * with a given text.
+     *
+     * <p>If nothing is selected, but the caret is inside a link, this will
+     * replace the existing link. If nothing is selected and the caret
+     * is not inside a link, this method does nothing.</p>
+     *
+     * @param linkText  the text that shall appear as link at the current selection
+     * @param href  the target this link shall refer to
+     * @param className  the style class to be used
+     */
+    public void setLink(final String linkText, final String href, final String className) {
+        setLink(linkText, href, className, null, null);
+    }
+
+    /**
+     * Sets a hyperlink at the current selection, replacing the selection
+     * with the given text or image.
+     *
+     * @param linkText  the text to show as link (or null, if an image shall appear instead)
+     * @param href  the link reference
+     * @param className  the style name to be used for the link
+     * @param linkImage  the file name of the image be used for the link (or null, if a text link is to be set instead)
+     * @param size  the size of the image or null
+     */
+    public void setLink(final String linkText, final String href, final String className, final String linkImage,
+                        final Dimension size) {
+        if (linkImage == null) {
+            setTextLink(getCurrentLinkElement(), href, className, linkText, getSHTMLDocument());
+        }
+        else {
+            setImageLink(getSHTMLDocument(), getCurrentLinkElement(), href, className, linkImage, size);
+        }
+    }
+
+    /**
+     * set an image link replacing the current selection
+     *
+     * @param doc  the document to apply the link to
+     * @param e  the link element found at the selection, or null if none was found
+     * @param href  the link reference
+     * @param className  the style name to be used for the link
+     * @param linkImage  the file name of the image be used for the link
+     * @param size  the size of the image
+     */
+    private void setImageLink(final SHTMLDocument doc, final Element e, final String href, final String className,
+                              final String linkImage, final Dimension size) {
+        final String a = HTML.Tag.A.toString();
+        SimpleAttributeSet set = new SimpleAttributeSet();
+        set.addAttribute(HTML.Attribute.HREF, href);
+        final String sStyleName = Util.getResourceString("standardStyleName");
+        if (className != null && !className.equalsIgnoreCase(sStyleName)) {
+            set.addAttribute(HTML.Attribute.CLASS, className);
+        }
+        final StringWriter sw = new StringWriter();
+        final SHTMLWriter w = new SHTMLWriter(sw, doc);
+        try {
+            w.writeStartTag(a, set);
+            set = new SimpleAttributeSet();
+            set.addAttribute(HTML.Attribute.SRC,
+                Util.getRelativePath(new File(doc.getBase().getFile()), new File(linkImage)));
+            set.addAttribute(HTML.Attribute.BORDER, "0");
+            if (size != null) {
+                set.addAttribute(HTML.Attribute.WIDTH, Integer.toString(new Double(size.getWidth()).intValue()));
+                set.addAttribute(HTML.Attribute.HEIGHT, Integer.toString(new Double(size.getHeight()).intValue()));
+            }
+            w.writeStartTag(HTML.Tag.IMG.toString(), set);
+            w.writeEndTag(a);
+            if (e != null) {
+                System.out.println("SHTMLEditorPane.setImageLink setOuterHTML html='" + sw.getBuffer() + "'");
+                doc.setOuterHTML(e, sw.getBuffer().toString());
+            }
+            else {
+                final int start = getSelectionStart();
+                if (start < getSelectionEnd()) {
+                    replaceSelection("");
+                    System.out.println("SHTMLEditorPane.setImageLink insertAfterEnd html='" + sw.getBuffer() + "'");
+                    doc.insertAfterEnd(doc.getCharacterElement(start), sw.getBuffer().toString());
+                }
+            }
+        }
+        catch (final Exception ex) {
+            Util.errMsg(this, ex.getMessage(), ex);
+        }
+    }
+
+    /**
+     * set a text link replacing the current selection
+     *
+     * @param e  the link element found at the selection, or null if none was found
+     * @param href  the link reference
+     * @param className  the style name to be used for the link
+     * @param linkText  the text to show as link
+     * @param doc  the document to apply the link to
+     */
+    private void setTextLink(final Element e, final String href, final String className, String linkText,
+                             final SHTMLDocument doc) {
+        final String sStyleName = Util.getResourceString("standardStyleName");
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        final SimpleAttributeSet aSet = new SimpleAttributeSet();
+        if(href != null){
+        	aSet.addAttribute(HTML.Attribute.HREF, href);
+        	if (className != null && !className.equalsIgnoreCase(sStyleName)) {
+        		aSet.addAttribute(HTML.Attribute.CLASS, className);
+        	}
+        }
+        if (e != null) {
+            // replace existing link
+        	set.addAttributes(e.getAttributes());
+        	if(href != null){
+        		set.addAttribute(HTML.Tag.A, aSet);
+        	}
+        	else{
+        		set.removeAttribute(HTML.Tag.A);
+        	}
+            final int start = e.getStartOffset();
+            int length = e.getEndOffset() - start;
+            try {
+                if(linkText == null)
+                	linkText = doc.getText(start, length);
+				doc.replace(start, length, linkText, set);
+            }
+            catch (final BadLocationException ex) {
+                Util.errMsg(this, ex.getMessage(), ex);
+            }
+        }
+        else if(href != null){
+            // create new link for text selection
+            final int start = getSelectionStart();
+            if (start < getSelectionEnd()) {
+                set.addAttribute(HTML.Tag.A, aSet);
+                try {
+                	if(linkText == null)
+                		linkText = doc.getText(start, getSelectionEnd() - start);
+                	replaceSelection(linkText);
+                	doc.setCharacterAttributes(start, linkText.length(), set, false);
+                }
+                catch (final BadLocationException ex) {
+                	Util.errMsg(this, ex.getMessage(), ex);
+                }
+            }
+        }
+    }
+
+    /**
+     * remove an anchor with a given name
+     *
+     * @param anchorName  the name of the anchor to remove
+     */
+    public void removeAnchor(final String anchorName) {
+        //System.out.println("SHTMLEditorPane removeAnchor");
+        AttributeSet attrs;
+        Object nameAttr;
+        Object link;
+        final ElementIterator eli = new ElementIterator(getDocument());
+        Element elem = eli.first();
+        while (elem != null) {
+            attrs = elem.getAttributes();
+            link = attrs.getAttribute(HTML.Tag.A);
+            if (link != null /*&& link.toString().equalsIgnoreCase(HTML.Tag.A.toString())*/) {
+                //System.out.println("found anchor attribute");
+                nameAttr = ((AttributeSet) link).getAttribute(HTML.Attribute.NAME);
+                if (nameAttr != null && nameAttr.toString().equalsIgnoreCase(anchorName)) {
+                    // remove anchor here
+                    //System.out.println("removing anchor name=" + nameAttr);
+                    final SimpleAttributeSet newSet = new SimpleAttributeSet(attrs);
+                    newSet.removeAttribute(HTML.Tag.A);
+                    final SHTMLDocument doc = (SHTMLDocument) getDocument();
+                    final int start = elem.getStartOffset();
+                    doc.setCharacterAttributes(elem.getStartOffset(), elem.getEndOffset() - start, newSet, true);
+                }
+            }
+            elem = eli.next();
+        }
+    }
+
+    /**
+     * insert a table column before the current column
+     * (if any)
+     */
+    public void insertTableColumn() {
+        final Element cell = getCurrentTableCell();
+        if (cell != null) {
+            createTableColumn(cell, Util.getElementIndex(cell)/*getColNumber(cell)*/, true);
+        }
+    }
+
+    /**
+     * append a table column after the last column
+     * (if any)
+     */
+    public void appendTableColumn() {
+        final Element cell = getCurrentTableCell();
+        if (cell != null) {
+            final Element lastCell = getLastTableCell(cell);
+            createTableColumn(lastCell, Util.getElementIndex(cell)/*getColNumber(lastCell)*/, false);
+        }
+    }
+
+    /**
+     * create a table column before or after a given column
+     *
+     * the width of the first cell in the column
+     * (if there is a width attribute) is split into
+     * half so that the new column and the column
+     * inserted before are sharing the space originally
+     * taken by the column inserted before.
+     *
+     * @param cell  the cell to copy from
+     * @param cIndex  the number of the column 'cell' is in
+     * @param before  true indicates insert before, false append after
+     */
+    private void createTableColumn(final Element cell, final int cIndex, final boolean before) {
+        // get the new width setting for this column and the new column
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        doc.startCompoundEdit();
+        final Element table = cell.getParentElement().getParentElement();
+        Element srcCell = table.getElement(0).getElement(cIndex);
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        final Object attr = set.getAttribute(CSS.Attribute.WIDTH);
+        if (attr != null) {
+            //LengthValue lv = new LengthValue(attr);
+            //String unit = lv.getUnit();
+            //int width = (int) lv.getAttrValue(attr.toString(), unit);
+            final int width = (int) Util.getAbsoluteAttrVal(attr); // Util.getAttrValue(attr);
+            //System.out.println("SHTMLEditorPane.createTableColumn width=" + width);
+            final String unit = Util.getLastAttrUnit();
+            //System.out.println("SHTMLEditorPane.createTableColumn unit=" + unit);
+            final String widthString = Integer.toString(width / 2) + unit;
+            //System.out.println("SHTMLEditorPane.createTableColumn widthString=" + widthString);
+            Util.styleSheet().addCSSAttribute(set, CSS.Attribute.WIDTH, widthString);
+        }
+        // adjust width and insert new column
+        //SimpleAttributeSet a = new SimpleAttributeSet(set.copyAttributes());
+        //int cellIndex = getCellIndex(srcCell);
+        //boolean insertFirst = (before && (cellIndex == 0));
+        for (int rIndex = 0; rIndex < table.getElementCount(); rIndex++) {
+            srcCell = table.getElement(rIndex).getElement(cIndex);
+            /*
+            if(rIndex > 0) {
+              adjustBorder(a, a, a, CombinedAttribute.ATTR_TOP);
+            }
+            adjustBorder(a, a, a, CombinedAttribute.ATTR_LEFT);
+            */
+            doc.addAttributes(srcCell, set);
+            try {
+                if (before) {
+                    doc.insertBeforeStart(srcCell, createTableCellHTML(srcCell));
+                }
+                else {
+                    doc.insertAfterEnd(srcCell, createTableCellHTML(srcCell));
+                }
+            }
+            catch (final IOException ioe) {
+                Util.errMsg(null, ioe.getMessage(), ioe);
+            }
+            catch (final BadLocationException ble) {
+                Util.errMsg(null, ble.getMessage(), ble);
+            }
+        }
+        //adjustColumnBorders(table.getElement(0).getElement(cIndex));
+        //adjustColumnBorders(table.getElement(0).getElement(++cIndex));
+        doc.endCompoundEdit();
+    }
+
+    /**
+     * Appends a row to a table if the caret is inside a table.
+     */
+    public void appendTableRow() {
+        final Element cell = getCurrentTableCell();
+        if (cell != null) {
+            final Element table = cell.getParentElement().getParentElement();
+            final Element lastRow = table.getElement(table.getElementCount() - 1);
+            createTableRow(lastRow, Util.getRowIndex(lastRow.getElement(0)), false, null);
+        }
+    }
+
+    /**
+     * Inserts a row to a table, assuming the caret is currently
+     * inside a table.
+     */
+    public void insertTableRow(final String forcedCellName) {
+        final Element cell = getCurrentTableCell();
+        if (cell != null) {
+            createTableRow(cell.getParentElement(), Util.getRowIndex(cell), true, forcedCellName);
+        }
+    }
+
+    /**
+     * Creates a new table row, inserting it before, or appending after the given
+     * row, depending on a parameter.
+     *
+     * Is shared by appendRow and insertRow actions.
+     *
+     * @param srcRow  the row element to copy from
+     * @param before  true indicates insert before, false append after
+     * @param forcedCellName if non-null, that cell name will be used in the new table row. Values: "td", "th".
+     */
+    private void createTableRow(final Element srcRow, int rowIndex, final boolean before, final String forcedCellName) {
+        try {
+            if (before) {
+                getSHTMLDocument().insertBeforeStart(srcRow, createTableRowHTML(srcRow, forcedCellName));
+                if (rowIndex == 0) {
+                    rowIndex++;
+                }
+            }
+            else {
+                getSHTMLDocument().insertAfterEnd(srcRow, createTableRowHTML(srcRow, forcedCellName));
+                rowIndex++;
+            }
+        }
+        catch (final IOException ioe) {
+            Util.errMsg(null, ioe.getMessage(), ioe);
+        }
+        catch (final BadLocationException ble) {
+            Util.errMsg(null, ble.getMessage(), ble);
+        }
+    }
+
+    /**
+     * Returns the HTML string of the given table row, without the cell contents, possibly
+     * forcing the cell name on "td" or "th", if the parameter for forced cell name is non-null.
+     *
+     * For each table column found in srcRow, a start and end
+     * tag TD is created with the same attributes as in the
+     * column found in srcRow. The attributes of srcRow
+     * are applied to the newly created row HTML string as well.
+     *
+     * @param modelRow  the table row Element to copy from
+     * @param insert  indicates if a row is inserted before another row
+     *
+     * @return an HTML string representing the new table row
+     * (without cell contents)
+     */
+    private String createTableRowHTML(final Element modelRow, final String forcedCellName) {
+        final StringWriter stringWriter = new StringWriter();
+        final SHTMLWriter shtmlWriter = new SHTMLWriter(stringWriter, (SHTMLDocument) getDocument());
+        final String tr = HTML.Tag.TR.toString();
+        try {
+            shtmlWriter.writeStartTag(tr, modelRow.getAttributes());
+            for (int i = 0; i < modelRow.getElementCount(); i++) {
+                final Element modelCell = modelRow.getElement(i);
+                final String cellName = forcedCellName != null ? forcedCellName : modelCell.getName();
+                createTableCellHTML(shtmlWriter, modelCell, cellName);
+            }
+            shtmlWriter.writeEndTag(tr);
+        }
+        catch (final IOException ex) {
+            Util.errMsg(null, ex.getMessage(), ex);
+        }
+        return stringWriter.getBuffer().toString();
+    }
+
+    private void createTableCellHTML(final SHTMLWriter w, final Element cell, final String cellName) throws IOException {
+        {
+            w.writeStartTag(cellName, cell.getAttributes());
+            final Element paragraph = cell.getElement(0);
+            final String parName = "p"; //Was: paragraph.getName(); UL and OL are parNames not to be copied. --Dan
+            if (!parName.equalsIgnoreCase(HTML.Tag.IMPLIED.toString())) {
+                w.writeStartTag(parName, paragraph.getAttributes());
+                w.writeEndTag(parName);
+            }
+            w.writeEndTag(cellName);
+        }
+    }
+
+    /**
+     * build an HTML string copying from an existing table cell
+     *
+     * @param srcCell the cell to get the HTML for
+     * @param a  set of attributes to copy if we are inserting first table column
+     * @param insertFirst  indicates if we are inserting first table column
+     * @param rNum  number of row a cell is to be inserted to
+     *     (can be any value if insertFirst is false)
+     *
+     * @return the HTML string for the given cell (without cell contents)
+     */
+    private String createTableCellHTML(final Element srcCell) {
+        final StringWriter sw = new StringWriter();
+        final SHTMLWriter w = new SHTMLWriter(sw, (SHTMLDocument) getDocument());
+        try {
+            createTableCellHTML(w, srcCell, srcCell.getName());
+        }
+        catch (final IOException e) {
+            Util.errMsg(null, e.getMessage(), e);
+        }
+        //System.out.println("getTableCellHTML buffer='" + sw.getBuffer().toString() + "'");
+        return sw.getBuffer().toString();
+    }
+
+    /**
+     * delete the row of the table the caret is currently in (if any)
+     */
+    public void deleteTableRow() {
+        final Element cell = getCurrentTableCell();
+        final int finalCaretPosition = cell.getStartOffset();
+        if (cell != null) {
+            removeElement(cell.getParentElement());
+            final int docLength = getDocument().getLength();
+            if (docLength >= finalCaretPosition) {
+                setCaretPosition(finalCaretPosition);
+            }
+            else {
+                setCaretPosition(docLength);
+            }
+        }
+    }
+
+    /**
+     * delete the column of the table the caret is currently in (if any)
+     *
+     * <p>width of adjacent column is adjusted, if there is more than one
+     * column in the table. Width adjustment only works, if width
+     * attributes of both the column to remove and its adjacent column
+     * have the same unit (pt or %).</p>
+     *
+     * <p>If there is only one cell or if the caret is not in a table,
+     * this method does nothing</p>
+     *
+     * <p>Smart border handling automatically sets the left border of a cell
+     * to zero, if the cell on the left of that cell has a right border and
+     * both cells have no margin. In that case removing the first column
+     * will cause all cells of the new first column to have no left border.</p>
+     */
+    public void deleteTableCol() {
+        final Element cell = getCurrentTableCell();
+        if (cell == null) {
+            return;
+        }
+        Element row = cell.getParentElement();
+        final int lastColIndex = row.getElementCount() - 1;
+        if (lastColIndex <= 0) {
+            return;
+        }
+        final int cIndex = Util.getElementIndex(cell); //getColNumber(cell);
+        int offset = -1; // adjacent cell is left of current cell
+        if (cIndex == 0) { // if current cell is in first column...
+            offset *= -1; // ...adjacent cell is right of current cell
+        }
+        final Object attrC = cell.getAttributes().getAttribute(CSS.Attribute.WIDTH);
+        final Object attrA = row.getElement(cIndex + offset).getAttributes().getAttribute(CSS.Attribute.WIDTH);
+        SimpleAttributeSet set = null;
+        if (attrC != null && attrA != null) {
+            //LengthValue lvC = new LengthValue(attrC);
+            //LengthValue lvA = new LengthValue(attrA);
+            final int widthC = (int) Util.getAbsoluteAttrVal(attrC); // Util.getAttrValue(attrC);
+            final String cUnit = Util.getLastAttrUnit();
+            //String cUnit = lvC.getUnit();
+            final int widthA = (int) Util.getAbsoluteAttrVal(attrA); // Util.getAttrValue(attrA);
+            final String aUnit = Util.getLastAttrUnit();
+            if (aUnit.equalsIgnoreCase(cUnit)) {
+                int width = 0;
+                width += widthC;
+                width += widthA;
+                if (width > 0) {
+                    final String widthString = Integer.toString(width) + cUnit;
+                    set = new SimpleAttributeSet(row.getElement(cIndex + offset).getAttributes());
+                    Util.styleSheet().addCSSAttribute(set, CSS.Attribute.WIDTH, widthString);
+                }
+            }
+        }
+        final Element table = row.getParentElement();
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        doc.startCompoundEdit();
+        if (cIndex < lastColIndex) {
+            offset = 0;
+        }
+        for (int rIndex = table.getElementCount() - 1; rIndex >= 0; rIndex--) {
+            row = table.getElement(rIndex);
+            try {
+                doc.removeElements(row, cIndex, 1);
+                /*
+                    the following line does not work for the last column in a table
+                    so we use above code instead
+
+                    removeElement(row.getElement(cIndex));
+                 */
+            }
+            catch (final BadLocationException ble) {
+                Util.errMsg(null, ble.getMessage(), ble);
+            }
+            if (set != null) {
+                doc.addAttributes(row.getElement(cIndex + offset), set);
+            }
+            //adjustColumnBorders(table.getElement(0).getElement(cIndex + offset));
+        }
+        doc.endCompoundEdit();
+    }
+
+    /** For each cell within the selection, turns a table data cell into a table header cell or vice
+     * versa. */
+    public void toggleTableHeaderCell() {
+        final int originalCaretPosition = getCaretPosition();
+        final int selectionStart = getSelectionStart();
+        final int selectionEnd = getSelectionEnd();
+        Element tableCell = getTableCell(selectionStart);
+        while (tableCell != null && tableCell.getStartOffset() <= selectionEnd) {
+            final String content = elementToHTML(tableCell);
+            String newContent = content;
+            if (content.matches("(?is)\\s*<td.*")) {
+                newContent = content.replaceFirst("(?is)^\\s*<td", "<th").replaceFirst("(?is)</td>\\s*$", "</th>");
+            }
+            else if (content.matches("(?is)\\s*<th.*")) {
+                newContent = content.replaceFirst("(?is)^\\s*<th", "<td").replaceFirst("(?is)</th>\\s*$", "</td>");
+            }
+            else {
+                // Unexpected
+            }
+            final Element row = tableCell.getParentElement();
+            final int tableCellIdx = row.getElementIndex(tableCell.getStartOffset());
+            try {
+                getSHTMLDocument().setOuterHTML(tableCell, newContent);
+            }
+            catch (final Exception ex) {
+            }
+            tableCell = row.getElement(tableCellIdx); // Restore the cell reference after the operation.
+            tableCell = getNextCell(tableCell);
+        }
+        setCaretPosition(originalCaretPosition);
+    }
+
+    /** Moves the table row up. Does not treat multirow cells. */
+    void moveTableRowUp() {
+        final Element tableCell = getCurrentTableCell();
+        final Element tableRow = tableCell.getParentElement();
+        final Element table = tableRow.getParentElement();
+        final int indexOfRowInTable = table.getElementIndex(getCaretPosition());
+        if (indexOfRowInTable == 0) {
+            return;
+        }
+        try {
+            getSHTMLDocument().startCompoundEdit();
+            final SHTMLWriter writer = new SHTMLWriter(getSHTMLDocument());
+            writer.writeStartTag(table);
+            for (int i = 0; i < indexOfRowInTable - 1; i++) {
+                writer.write(table.getElement(i));
+            }
+            writer.write(tableRow);
+            writer.write(table.getElement(indexOfRowInTable - 1));
+            for (int i = indexOfRowInTable + 1; i < table.getElementCount(); i++) {
+                writer.write(table.getElement(i));
+            }
+            writer.writeEndTag(table);
+            final int offsetWithinCurrentRow = getCaretPosition() - tableRow.getStartOffset();
+            final int finalCaretPosition = table.getElement(indexOfRowInTable - 1).getStartOffset()
+                    + offsetWithinCurrentRow;
+            getSHTMLDocument().setOuterHTML(table, writer.getWrittenString());
+            setCaretPosition(finalCaretPosition);
+        }
+        catch (final Exception ex) {
+        }
+        finally {
+            getSHTMLDocument().endCompoundEdit();
+        }
+    }
+
+    /** Moves the table column left. Does not treat multicolumn cells. */
+    void moveTableColumnLeft() {
+        final Element tableCell = getCurrentTableCell();
+        final Element tableRow = tableCell.getParentElement();
+        final Element table = tableRow.getParentElement();
+        final int indexOfCellInRow = tableRow.getElementIndex(getCaretPosition());
+        if (indexOfCellInRow == 0) {
+            return;
+        }
+        try {
+            getSHTMLDocument().startCompoundEdit();
+            final SHTMLWriter writer = new SHTMLWriter(getSHTMLDocument());
+            writer.writeStartTag(table);
+            for (int rowIdx = 0; rowIdx < table.getElementCount(); rowIdx++) {
+                final Element row = table.getElement(rowIdx);
+                writer.writeStartTag(row);
+                for (int i = 0; i < indexOfCellInRow - 1; i++) {
+                    writer.write(row.getElement(i));
+                }
+                writer.write(row.getElement(indexOfCellInRow));
+                writer.write(row.getElement(indexOfCellInRow - 1));
+                for (int i = indexOfCellInRow + 1; i < row.getElementCount(); i++) {
+                    writer.write(row.getElement(i));
+                }
+                writer.writeEndTag(row);
+            }
+            writer.writeEndTag(table);
+            final int offsetWithinCurrentCell = getCaretPosition() - tableCell.getStartOffset();
+            final int finalCaretPosition = tableRow.getElement(indexOfCellInRow - 1).getStartOffset()
+                    + offsetWithinCurrentCell;
+            getSHTMLDocument().setOuterHTML(table, writer.getWrittenString());
+            setCaretPosition(finalCaretPosition);
+        }
+        catch (final Exception ex) {
+        }
+        finally {
+            getSHTMLDocument().endCompoundEdit();
+        }
+    }
+
+    /** Moves the table column right. Does not treat multicolumn cells. */
+    void moveTableColumnRight() {
+        final Element tableCell = getCurrentTableCell();
+        final Element tableRow = tableCell.getParentElement();
+        final Element table = tableRow.getParentElement();
+        final int indexOfCellInRow = tableRow.getElementIndex(getCaretPosition());
+        if (indexOfCellInRow == tableRow.getElementCount() - 1) {
+            return;
+        }
+        try {
+            getSHTMLDocument().startCompoundEdit();
+            final SHTMLWriter writer = new SHTMLWriter(getSHTMLDocument());
+            writer.writeStartTag(table);
+            for (int rowIdx = 0; rowIdx < table.getElementCount(); rowIdx++) {
+                final Element row = table.getElement(rowIdx);
+                writer.writeStartTag(row);
+                for (int i = 0; i < indexOfCellInRow; i++) {
+                    writer.write(row.getElement(i));
+                }
+                writer.write(row.getElement(indexOfCellInRow + 1));
+                writer.write(row.getElement(indexOfCellInRow));
+                for (int i = indexOfCellInRow + 2; i < row.getElementCount(); i++) {
+                    writer.write(row.getElement(i));
+                }
+                writer.writeEndTag(row);
+            }
+            final Element cellToTheRight = tableRow.getElement(indexOfCellInRow + 1);
+            final int finalCaretPosition = getCaretPosition() + cellToTheRight.getEndOffset()
+                    - cellToTheRight.getStartOffset();
+            getSHTMLDocument().setOuterHTML(table, writer.getWrittenString());
+            setCaretPosition(finalCaretPosition);
+        }
+        catch (final Exception ex) {
+        }
+        finally {
+            getSHTMLDocument().endCompoundEdit();
+        }
+    }
+
+    /** Moves the table row down. Does not treat multirow cells. */
+    void moveTableRowDown() {
+        final Element tableCell = getCurrentTableCell();
+        if (tableCell == null) {
+            return;
+        }
+        final Element tableRow = tableCell.getParentElement();
+        final Element table = tableRow.getParentElement();
+        final int indexOfRowInTable = table.getElementIndex(getCaretPosition());
+        if (indexOfRowInTable == table.getElementCount() - 1) {
+            return;
+        }
+        try {
+            getSHTMLDocument().startCompoundEdit();
+            final SHTMLWriter writer = new SHTMLWriter(getSHTMLDocument());
+            writer.writeStartTag(table);
+            for (int i = 0; i < indexOfRowInTable; i++) {
+                writer.write(table.getElement(i));
+            }
+            writer.write(table.getElement(indexOfRowInTable + 1));
+            writer.write(tableRow);
+            for (int i = indexOfRowInTable + 2; i < table.getElementCount(); i++) {
+                writer.write(table.getElement(i));
+            }
+            writer.writeEndTag(table);
+            final Element rowBelow = table.getElement(indexOfRowInTable + 1);
+            final int finalCaretPosition = getCaretPosition() + rowBelow.getEndOffset() - rowBelow.getStartOffset();
+            getSHTMLDocument().setOuterHTML(table, writer.getWrittenString());
+            setCaretPosition(finalCaretPosition);
+        }
+        catch (final Exception ex) {
+        }
+        finally {
+            getSHTMLDocument().endCompoundEdit();
+        }
+    }
+
+    /**
+     * Removes an element from the document of this editor. Removes it <i>manually</i> if the parent is not body.
+     * Leaves it to the caller to set the caret position after the removal.
+     */
+    private void removeElement(final Element element) {
+        try {
+            final int start = element.getStartOffset();
+            final Element parent = element.getParentElement();
+            if (parent.getName().equalsIgnoreCase("body")) {
+                getSHTMLDocument().remove(start, element.getEndOffset() - start);
+            }
+            else {
+                // If the parent is not body, remove manually, to avoid quirks, e.g. in tables.
+                final int indexInParent = parent.getElementIndex(element.getStartOffset());
+                final SHTMLWriter writer = new SHTMLWriter(getSHTMLDocument());
+                writer.writeStartTag(parent);
+                for (int i = 0; i < indexInParent; i++) {
+                    writer.write(parent.getElement(i));
+                }
+                for (int i = indexInParent + 1; i < parent.getElementCount(); i++) {
+                    writer.write(parent.getElement(i));
+                }
+                writer.writeEndTag(parent);
+                getSHTMLDocument().setOuterHTML(parent, writer.getWrittenString());
+            }
+        }
+        catch (final Exception ex) {
+            Util.errMsg(null, ex.getMessage(), ex);
+        }
+    }
+
+    /**
+     * apply a set of attributes to the table the caret is
+     * currently in (if any)
+     *
+     * @param a  the set of attributes to apply
+     */
+    public void applyTableAttributes(final AttributeSet a) {
+        final Element cell = getCurrentTableCell();
+        if (cell != null) {
+            final Element table = cell.getParentElement().getParentElement();
+            if (a.getAttributeCount() > 0) {
+                //System.out.println("applyTableAttributes count=" + a.getAttributeCount() + " a=" + a);
+                ((SHTMLDocument) getDocument()).addAttributes(table, a);
+                /**
+                 * for some reason above code does not show the changed attributes
+                 * of the table, although the element really has them (maybe somebody
+                 * could let me know why...). Therefore we update the editor pane
+                 * contents comparably rude (any other more elegant alternatives
+                 * welcome!)
+                 *
+                 * --> found out why: the swing package does not render short hand
+                 *                    properties such as MARGIN or PADDING. When
+                 *                    contained in a document inside an AttributeSet
+                 *                    they already have to be split into MARGIN-TOP,
+                 *                    MARGIN-LEFT, etc.
+                 *                    adjusted AttributeComponents accordingly so
+                 *                    we don't need refresh anymore
+                 */
+                //refresh();
+            }
+        }
+    }
+
+    /**
+     * refresh the whole contents of this editor pane with brute force
+     */
+    private void refresh() {
+        final int pos = getCaretPosition();
+        final String data = getText();
+        setText("");
+        setText(data);
+        setCaretPosition(pos);
+    }
+
+    /**
+     * apply a set of attributes to a given range of cells
+     * of the table the caret is currently in (if any)
+     *
+     * @param a  the set of attributes to apply
+     * @param range  the range of cells to apply attributes to
+     */
+    public void applyCellAttributes(final AttributeSet a, final int range) {
+        //System.out.println("SHTMLEditorPane applyCellAttributes a=" + a);
+        final Element cell = getCurrentTableCell();
+        int cIndex = 0;
+        int rIndex = 0;
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        if (cell != null) {
+            Element row = cell.getParentElement();
+            final Element table = row.getParentElement();
+            Element aCell;
+            switch (range) {
+                case THIS_CELL:
+                    doc.addAttributes(cell, a);
+                    break;
+                case THIS_ROW:
+                    for (cIndex = 0; cIndex < row.getElementCount(); cIndex++) {
+                        aCell = row.getElement(cIndex);
+                        doc.addAttributes(aCell, a);
+                    }
+                    break;
+                case THIS_COLUMN:
+                    cIndex = Util.getElementIndex(cell); //getColNumber(cell);
+                    for (rIndex = 0; rIndex < table.getElementCount(); rIndex++) {
+                        aCell = table.getElement(rIndex).getElement(cIndex);
+                        doc.addAttributes(aCell, a);
+                    }
+                    break;
+                case ALL_CELLS:
+                    while (rIndex < table.getElementCount()) {
+                        row = table.getElement(rIndex);
+                        cIndex = 0;
+                        while (cIndex < row.getElementCount()) {
+                            aCell = row.getElement(cIndex);
+                            //System.out.println("applyCellAttributes ALL_CELLS adjusted a=" + adjustCellBorders(aCell, a));
+                            doc.addAttributes(aCell, a);
+                            cIndex++;
+                        }
+                        rIndex++;
+                    }
+                    break;
+            }
+        }
+    }
+
+    public SHTMLDocument getSHTMLDocument() {
+        return (SHTMLDocument) getDocument();
+    }
+
+    /**
+     * Gets the number of the table column in which the given cell is located.
+     *
+     * @param cell  the cell to get the column number for
+     * @return the column number of the given cell
+     */
+    private int getColNumber(final Element cell) {
+        int i = 0;
+        final Element thisRow = cell.getParentElement();
+        final int last = thisRow.getElementCount() - 1;
+        Element aCell = thisRow.getElement(i);
+        if (aCell != cell) {
+            while ((i < last) && (aCell != cell)) {
+                aCell = thisRow.getElement(++i);
+            }
+        }
+        return i;
+    }
+
+    /* ------- table manipulation end -------------------- */
+    /* ------- table cell navigation start --------------- */
+    /**
+     * <code>Action</code> to move the caret from the current table cell
+     * to the next table cell.
+     */
+    private class TabAction extends AbstractAction {
+        /** action to use when not inside a table */
+        /* removed for changes in J2SE 1.4.1
+        private Action alternateAction;
+         */
+        /** construct a <code>NextTableCellAction</code> */
+        public TabAction(final String actionName) {
+            super(actionName);
+        }
+
+        /**
+         * construct a <code>NextTableCellAction</code>
+         *
+         * @param altAction  the action to use when the caret
+         *      is not inside a table
+         */
+        /* removed for changes in J2SE 1.4.1
+        public NextTableCellAction(Action altAction) {
+          alternateAction = altAction;
+        }
+         */
+        /**
+         * move to the previous cell or invoke an alternate action if the
+         * caret is not inside a table
+         *
+         * this will append a new table row when the caret
+         * is inside the last table cell
+         */
+        public void actionPerformed(final ActionEvent ae) {
+            if (listManager.caretAtTheBeginningOfListItem()) {
+                // Increase indent within list
+                listManager.increaseIndent(true);
+                return;
+            }
+            final Element cell = getCurrentTableCell();
+            if (cell != null) {
+                // Within a table cell.
+                goNextCell(cell);
+                return;
+            }
+            if (listManager.caretWithinListItem()) {
+                // Increase indent within list
+                listManager.increaseIndent(true);
+                return;
+            }
+            // Do nothing; above all, do not enter tab character.
+            //performDefaultKeyStrokeAction(KeyEvent.VK_TAB, 0, ae);
+            if (Util.preferenceIsTrue("table.insertNewOnTabKey", "false")) {
+                insertNewTable(3);
+            }
+        }
+    }
+
+    /**
+     * <code>Action</code> to move the caret from the current table cell
+     * to the previous table cell.
+     */
+    private class ShiftTabAction extends AbstractAction {
+        /** action to use when not inside a table */
+        /* removed for changes in J2SE 1.4.1
+        private Action alternateAction;
+        */
+        /** construct a <code>PrevTableCellAction</code> */
+        public ShiftTabAction(final String actionName) {
+            super(actionName);
+        }
+
+        /**
+         * construct a <code>PrevTableCellAction</code>
+         *
+         * @param altAction  the action to use when the caret
+         *      is not inside a table
+         */
+        /* removed for changes in J2SE 1.4.1
+        public PrevTableCellAction(Action altAction) {
+          alternateAction = altAction;
+        }
+        */
+        /**
+         * Moves to the previous cell or invokes an alternate action if the
+         * caret is not inside a table.
+         */
+        public void actionPerformed(final ActionEvent ae) {
+            // Decrease intent within list
+            if (listManager.caretAtTheBeginningOfListItem()) {
+                listManager.decreaseIndent(true);
+                return;
+            }
+            final Element cell = getCurrentTableCell();
+            if (cell != null) {
+                goPrevCell(cell);
+                return;
+            }
+            // Decrease intent within list
+            if (listManager.caretWithinListItem()) {
+                listManager.decreaseIndent(true);
+                return;
+            }
+            performDefaultKeyStrokeAction(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK, ae);
+        }
+    }
+
+    /**
+     * <code>Action</code> to create a new list item.
+     */
+    private class InsertLineBreakAction extends AbstractAction {
+        /** construct a <code>NewListItemAction</code> */
+        public InsertLineBreakAction() {
+        }
+
+        /**
+         * create a new list item, when the caret is inside a list
+         *
+         * <p>The new item is created after the item at the caret position</p>
+         */
+        public void actionPerformed(final ActionEvent ae) {
+            try {
+                final SHTMLDocument doc = (SHTMLDocument) getDocument();
+                final int caretPosition = getCaretPosition();
+                final Element paragraphElement = doc.getParagraphElement(caretPosition);
+                if (paragraphElement != null) {
+                    final int so = paragraphElement.getStartOffset();
+                    final int eo = paragraphElement.getEndOffset();
+                    if (so != eo) {
+                        final StringWriter writer = new StringWriter();
+                        if (caretPosition > so) {
+                            final SHTMLWriter htmlStartWriter = new SHTMLWriter(writer, doc, so, caretPosition - so);
+                            htmlStartWriter.writeChildElements(paragraphElement);
+                        }
+                        // Workaround: <br> is written twice by Java.
+                        if (!doc.getCharacterElement(caretPosition).getName().equalsIgnoreCase(HTML.Tag.BR.toString())) {
+                            writer.write("<br>");
+                        }
+                        if (caretPosition < eo - 1) {
+                            final SHTMLWriter htmlEndWriter = new SHTMLWriter(writer, doc, caretPosition, eo
+                                    - caretPosition);
+                            htmlEndWriter.writeChildElements(paragraphElement);
+                        }
+                        final String text = writer.toString();
+                        try {
+                            doc.startCompoundEdit();
+                            doc.setInnerHTML(paragraphElement, text);
+                        }
+                        catch (final Exception e) {
+                            Util.errMsg(null, e.getMessage(), e);
+                        }
+                        finally {
+                            doc.endCompoundEdit();
+                        }
+                        setCaretPosition(caretPosition + 1);
+                    }
+                }
+            }
+            catch (final Exception e) {
+                Util.errMsg(null, e.getMessage(), e);
+            }
+        }
+    }
+
+    public void goNextCell(final Element cell) {
+        if (cell == getLastTableCell(cell)) {
+            appendTableRow();
+            setCaretPosition(getNextCell(cell).getStartOffset());
+        }
+        else {
+            setCaretPosition(getNextCell(cell).getStartOffset());
+        }
+    }
+
+    public void goPrevCell(Element cell) {
+        int newPos;
+        if (cell != getFirstTableCell(cell)) {
+            cell = getPrevCell(cell);
+            newPos = cell.getStartOffset();
+            select(newPos, newPos);
+        }
+    }
+
+    /**
+     * Gets the table cell following the given table cell, continuing
+     * on the next row if the cell is the last one in the row, returning
+     * null if the cell is the last one in the table.
+     *
+     * @param cell  the cell whose following cell shall be found
+     * @return the Element having the cell following the given cell or null
+     *    if the given cell is the last cell in the table
+     */
+    private Element getNextCell(final Element cell) {
+        Element nextCell = null;
+        final Element row = cell.getParentElement();
+        Element nextRow = null;
+        final Element table = row.getParentElement();
+        final int lastCellIdx = row.getElementCount() - 1;
+        final Element lastCellInRow = row.getElement(lastCellIdx);
+        if (lastCellInRow != cell) {
+            // The cell is not the last one in the row.
+            Element runningCell = lastCellInRow;
+            int cellIdx = lastCellIdx;
+            while ((cellIdx > 0) && (runningCell != cell)) {
+                nextCell = runningCell;
+                runningCell = row.getElement(--cellIdx);
+            }
+        }
+        else {
+            // The cell is the last one in the row.
+            int rowIdx = table.getElementCount() - 1;
+            Element aRow = table.getElement(rowIdx);
+            while (aRow != row) {
+                nextRow = aRow;
+                aRow = table.getElement(--rowIdx);
+            }
+            nextCell = nextRow == null || nextRow.getElementCount() == 0 ? null : nextRow.getElement(0);
+        }
+        return nextCell;
+    }
+
+    /**
+     * get the table cell preceding a given table cell
+     *
+     * @param cell  the cell whose preceding cell shall be found
+     * @return the Element having the cell preceding the given cell or null
+     *    if the given cell is the first cell in the table
+     */
+    private Element getPrevCell(final Element cell) {
+        final Element thisRow = cell.getParentElement();
+        final Element table = thisRow.getParentElement();
+        Element prevCell = null;
+        int i = 0;
+        Element aCell = thisRow.getElement(i);
+        if (aCell != cell) {
+            while (aCell != cell) {
+                prevCell = aCell;
+                aCell = thisRow.getElement(i++);
+            }
+        }
+        else {
+            Element prevRow = null;
+            Element aRow = table.getElement(i);
+            while (aRow != thisRow) {
+                prevRow = aRow;
+                aRow = table.getElement(i++);
+            }
+            prevCell = prevRow.getElement(prevRow.getElementCount() - 1);
+        }
+        return prevCell;
+    }
+
+    /**
+     * get the last cell of the table a given table cell belongs to
+     *
+     * @param cell  a cell of the table to get the last cell of
+     * @return the Element having the last table cell
+     */
+    private Element getLastTableCell(final Element cell) {
+        final Element table = cell.getParentElement().getParentElement();
+        final Element lastRow = table.getElement(table.getElementCount() - 1);
+        final Element lastCell = lastRow.getElement(lastRow.getElementCount() - 1);
+        return lastCell;
+    }
+
+    /**
+     * get the first cell of the table a given table cell belongs to
+     *
+     * @param cell  a cell of the table to get the first cell of
+     * @return the Element having the first table cell
+     */
+    private Element getFirstTableCell(final Element cell) {
+        final Element table = cell.getParentElement().getParentElement();
+        final Element firstCell = table.getElement(0).getElement(0);
+        return firstCell;
+    }
+
+    /**
+     * Gets the table cell at the current caret position.
+     *
+     * @return the Element having the current table cell or null if
+     *    the caret is not inside a table cell
+     */
+    public Element getCurrentTableCell() {
+        return getTableCell(getCaretPosition());
+    }
+
+    /**
+     * 
+     */
+    public Element getCurrentLinkElement() {
+        Element element2 = null;
+        Element element = getSHTMLDocument().getCharacterElement(getSelectionStart());
+        Object linkAttribute = null; //elem.getAttributes().getAttribute(HTML.Tag.A);
+        Object href = null;
+        while (element != null && linkAttribute == null) {
+            element2 = element;
+            linkAttribute = element.getAttributes().getAttribute(HTML.Tag.A);
+            if (linkAttribute != null) {
+                href = ((AttributeSet) linkAttribute).getAttribute(HTML.Attribute.HREF);
+            }
+            element = element.getParentElement();
+        }
+        if (linkAttribute != null && href != null) {
+            return element2;
+        }
+        else {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the table cell element at the given position, or null if none.
+     */
+    public Element getTableCell(final int position) {
+        final Element element = getSHTMLDocument().getCharacterElement(position);
+        return Util.findElementUp("td", "th", element);
+    }
+
+    /** Gets the string URL of an existing link, or null if none. */
+    String getURLOfExistingLink() {
+        //setIgnoreActions(true);      
+        final Element linkElement = getCurrentLinkElement();
+        final boolean foundLink = (linkElement != null);
+        if (!foundLink) {
+            return null;
+        }
+        final AttributeSet elemAttrs = linkElement.getAttributes();
+        final Object linkAttr = elemAttrs.getAttribute(HTML.Tag.A);
+        final Object href = ((AttributeSet) linkAttr).getAttribute(HTML.Attribute.HREF);
+        return href != null ? href.toString() : null;
+    }
+
+    /** Gets the paragraph element in which the caret is located. */
+    public Element getCurrentParagraphElement() {
+        return getSHTMLDocument().getParagraphElement(getCaretPosition());
+    }
+
+    /* ---------- table cell navigation end --------------*/
+    /**
+     * Replaces the currently selected content with new content
+     * represented by the given <code>HTMLText</code>. If there is no selection
+     * this amounts to an insert of the given text.  If there
+     * is no replacement text this amounts to a removal of the
+     * current selection.
+     * This method overrides replaceSelection in <code>JEditorPane</code> for usage
+     * of our own HTMLText object.
+     *
+     * @param replacementHTMLText  the content to replace the selection with
+     */
+    public void replaceSelection(final HTMLText replacementHTMLText) {
+        final SHTMLDocument document = (SHTMLDocument) getDocument();
+        final Caret caret = getCaret();
+        if (document != null) {
+            try {
+                final int p0 = Math.min(caret.getDot(), caret.getMark());
+                final int p1 = Math.max(caret.getDot(), caret.getMark());
+                if (p0 != p1) {
+                    document.remove(p0, p1 - p0);
+                }
+                if (replacementHTMLText != null) {
+                    pasteHTML(replacementHTMLText, p0);
+                }
+            }
+            catch (final Exception e) {
+                getToolkit().beep();
+            }
+        }
+    }
+
+    /** */
+    private void pasteHTML(final HTMLText pastedHTMLText, final int position) throws Exception {
+        final SHTMLDocument sDocument = (SHTMLDocument) getDocument();
+        if (!pastedHTMLText.usesStringRepresenation()) {
+            pastedHTMLText.pasteHTML(sDocument, position);
+            return;
+        }
+        // [ Uses string representation ]
+        String pasteHtmlTextModified = pastedHTMLText.getHTMLText();
+        final Element characterElement = sDocument.getCharacterElement(position);
+        final Element paragraphElement = characterElement.getParentElement();
+        if (position == paragraphElement.getStartOffset()) {
+            if (caretWithinTableCell() && pastedHTMLText.isOneCellInOneRow()) {
+                pasteHtmlTextModified = pasteHtmlTextModified.replaceAll("(?ims).*<td.*?>", "").replaceAll(
+                    "(?ims)</td.*?>.*", "");
+            }
+            // We are at the start of the paragraph to insert at.
+            if (!HTMLText.containsParagraphTags(pasteHtmlTextModified)) {
+                sDocument.insertAfterStart(paragraphElement, pasteHtmlTextModified);
+                // Remove whitespace before the end tag of paragraph element to avoid quircky behavior.       
+                final Element newParagraph = getCurrentParagraphElement();
+                final String fixedContent = elementToHTML(newParagraph).replaceAll("(?ims)\\s*</p>", "</p>");
+                sDocument.setOuterHTML(newParagraph, fixedContent);
+                //
+                setCaretPosition(newParagraph.getEndOffset() - 1);
+                return;
+            }
+            // Contains paragraph tags.
+            if (caretWithinTableCell() && pasteHtmlTextModified.matches("(?ims).*<table.*")) {
+                // The condition above is simplistic.
+                final String strippedHTMLText = pasteHtmlTextModified.replaceAll("(?ims).*<table.*?>", "").replaceAll(
+                    "(?ims)</table.*?>.*", "");
+                final Element cellElement = getCurrentTableCell();
+                final Element tableRowElement = cellElement.getParentElement();
+                sDocument.insertBeforeStart(tableRowElement, strippedHTMLText);
+                return;
+            }
+            // Contains paragraphs tags and
+            // (a) is not within a table cell or
+            // (b) the pasted content is not a table.
+            sDocument.insertBeforeStart(paragraphElement, pasteHtmlTextModified);
+            if (caretWithinTableCell()) {
+                final Element cellElement = getCurrentTableCell();
+                final Element lastElementInCell = cellElement.getElement(cellElement.getElementCount() - 1);
+                if (elementIsEmptyParagraph(lastElementInCell)) {
+                    // Remove empty paragraph at the end of the cell. A workaround.
+                    removeElement(lastElementInCell);
+                    setCaretPosition(cellElement.getEndOffset() - 1);
+                }
+            }
+            return;
+        }
+        if (paragraphElement.getEndOffset() == position + 1) {
+            // We are at the end of the paragraph to insert at,
+            if (HTMLText.containsParagraphTags(pasteHtmlTextModified)) {
+                sDocument.insertAfterEnd(paragraphElement, pasteHtmlTextModified);
+            }
+            else {
+                sDocument.insertBeforeEnd(paragraphElement, pasteHtmlTextModified);
+            }
+            return;
+        }
+        // We are somewhere else inside the paragraph to insert at.
+        final String newHtml = pastedHTMLText.splitPaste(sDocument, characterElement, paragraphElement, position,
+            pasteHtmlTextModified, HTMLText.containsParagraphTags(pasteHtmlTextModified));
+        final int paragraphOldEndOffset = paragraphElement.getEndOffset();
+        final int oldCaretPosition = getCaretPosition();
+        sDocument.setOuterHTML(paragraphElement, newHtml);
+        final Element newParagraphElement = getSHTMLDocument().getParagraphElement(oldCaretPosition);
+        // Place the caret after the pasted text
+        setCaretPosition(oldCaretPosition + newParagraphElement.getEndOffset() - paragraphOldEndOffset);
+    }
+
+    /* ------ start of drag and drop implementation -------------------------
+                (see also constructor of this class) */
+    /** enables this component to be a Drop Target */
+    DropTarget dropTarget = null;
+    /** enables this component to be a Drag Source */
+    DragSource dragSource = null;
+    /** the last selection start */
+    private int lastSelStart = 0;
+    /** the last selection end */
+    private int lastSelEnd = 0;
+    /** the location of the last event in the text component */
+    private int dndEventLocation = 0;
+    /**
+     * <p>This flag is set by this objects dragGestureRecognizer to indicate that
+     * a drag operation has been started from this object. It is cleared once
+     * dragDropEnd is captured by this object.</p>
+     *
+     * <p>If a drop occurs in this object and this object started the drag
+     * operation, then the element to be dropped comes from this object and thus
+     * has to be removed somewhere else in this object.</p>
+     *
+     * <p>To the contrary if a drop occurs in this object and the drag operation
+     * was not started in this object, then the element to be dropped does not
+     * come from this object and has not to be removed here.</p>
+     */
+    private boolean dragStartedHere = false;
+
+    /**
+     * Initialize the drag and drop implementation for this component.
+     *
+     * <p>DropTarget, DragSource and DragGestureRecognizer are instantiated
+     * and a MouseListener is established to track the selection in drag
+     * operations</p>
+     *
+     * <p>this ideally is called in the constructor of a class which
+     * would like to implement drag and drop</p>
+     */
+    public void initDnd() {
+        dropTarget = new DropTarget(this, this);
+        dragSource = new DragSource();
+        dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this);
+        this.addMouseListener(new MouseAdapter() {
+            public void mouseReleased(final MouseEvent e) {
+                this_mouseReleased(e);
+            }
+
+            public void mouseClicked(final MouseEvent e) {
+                this_mouseClicked(e);
+            }
+        });
+    }
+
+    /** a drag gesture has been initiated */
+    public void dragGestureRecognized(final DragGestureEvent event) {
+        final int selStart = getSelectionStart();
+        try {
+            if ((lastSelEnd > lastSelStart) && (selStart >= lastSelStart) && (selStart < lastSelEnd)) {
+                dragStartedHere = true;
+                select(lastSelStart, lastSelEnd);
+                final HTMLText text = new HTMLText();
+                final int start = getSelectionStart();
+                text.copyHTML(this, start, getSelectionEnd() - start);
+                final HTMLTextSelection trans = new HTMLTextSelection(text);
+                dragSource.startDrag(event, DragSource.DefaultMoveDrop, trans, this);
+            }
+        }
+        catch (final Exception e) {
+            //getToolkit().beep();
+        }
+    }
+
+    /**
+     * this message goes to DragSourceListener, informing it that the dragging
+     * has ended
+     */
+    public void dragDropEnd(final DragSourceDropEvent event) {
+        dragStartedHere = false;
+    }
+
+    /** is invoked when a drag operation is going on */
+    public void dragOver(final DropTargetDragEvent event) {
+        dndEventLocation = viewToModel(event.getLocation());
+        try {
+            setCaretPosition(dndEventLocation);
+        }
+        catch (final Exception e) {
+            //getToolkit().beep();
+        }
+    }
+
+    /**
+     * a drop has occurred. If the dragged element has a suitable
+     * <code>DataFlavor</code>, do the drop.
+     *
+     * @param event - the event specifiying the drop operation
+     * @see java.awt.datatransfer.DataFlavor
+     */
+    public void drop(final DropTargetDropEvent event) {
+        dndEventLocation = viewToModel(event.getLocation());
+        if ((dndEventLocation >= lastSelStart) && (dndEventLocation <= lastSelEnd)) {
+            event.rejectDrop();
+            select(lastSelStart, lastSelEnd);
+        }
+        else {
+            final SHTMLDocument doc = (SHTMLDocument) getDocument();
+            doc.startCompoundEdit();
+            try {
+                final Transferable transferable = event.getTransferable();
+                /*
+                if (getPasteMode() == PasteMode.PASTE_PLAIN_TEXT)
+                {
+                    event.acceptDrop(DnDConstants.ACTION_MOVE);
+                    final String content = transferable.getTransferData(DataFlavor.stringFlavor).toString();
+                    doDrop(event, content);
+                }
+                else
+                */
+                 if (transferable.isDataFlavorSupported(htmlTextDataFlavor)) {
+                    event.acceptDrop(DnDConstants.ACTION_MOVE);
+                    final HTMLText s = (HTMLText) transferable.getTransferData(htmlTextDataFlavor);
+                    doDrop(event, s);
+                }
+                else if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+                    event.acceptDrop(DnDConstants.ACTION_MOVE);
+                    final String s = (String) transferable.getTransferData(DataFlavor.stringFlavor);
+                    doDrop(event, s);
+                }
+                else {
+                    event.rejectDrop();
+                }
+            }
+            catch (final Exception exception) {
+                exception.printStackTrace();
+                event.rejectDrop();
+            }
+            finally {
+                doc.endCompoundEdit();
+            }
+        }
+    }
+
+    /**
+     * do the drop operation consisting of adding the dragged element and
+     * necessarily removing the dragged element from the original position
+     */
+    private void doDrop(final DropTargetDropEvent event, final Object s) {
+        int removeOffset = 0;
+        int moveOffset = 0;
+        int newSelStart;
+        int newSelEnd;
+        setCaretPosition(dndEventLocation);
+        if (s instanceof HTMLText) {
+            replaceSelection((HTMLText) s);
+        }
+        else if (s instanceof String) {
+            replaceSelection((String) s);
+        }
+        if (dndEventLocation < lastSelStart) {
+            removeOffset = s.toString().length();
+        }
+        else {
+            moveOffset = s.toString().length();
+        }
+        newSelEnd = dndEventLocation + (lastSelEnd - lastSelStart) - moveOffset;
+        newSelStart = dndEventLocation - moveOffset;
+        if (dragStartedHere) {
+            lastSelStart += removeOffset;
+            lastSelEnd += removeOffset;
+            select(lastSelStart, lastSelEnd);
+            replaceSelection("");
+        }
+        lastSelEnd = newSelEnd;
+        lastSelStart = newSelStart;
+        select(lastSelStart, lastSelEnd);
+        event.getDropTargetContext().dropComplete(true);
+    }
+
+    /** A groupping of list operations, mostly related to toggling of lists. */
+    private class ListManager {
+        //private Element parentElement;
+        class SwitchListException extends Exception {
+        }
+
+        private ListManager() {
+        }
+
+        private Element getParagraphElement(final int pos) {
+            Element paragraphElement = getSHTMLDocument().getParagraphElement(pos);
+            if (paragraphElement.getName().equalsIgnoreCase("p-implied")) {
+                paragraphElement = paragraphElement.getParentElement();
+            }
+            return paragraphElement;
+        }
+
+        /** */
+        private Element getListParent(final Element elem) {
+            Element listParent = elem.getParentElement();
+            if (elem.getName().equalsIgnoreCase(HTML.Tag.LI.toString())) {
+                listParent = listParent.getParentElement();
+            }
+            return listParent;
+        }
+
+        /** Gets the list item element at the caret position, or null if the position
+         * is not within a list. */
+        private Element getListItemElement(final int caretPosition) {
+            final Element paragraphElement = getParagraphElement(caretPosition);
+            return Util.findElementUp(HTML.Tag.LI.toString(), paragraphElement);
+        }
+
+        /** Gets the innermost list element at the caret position, or null if the position is not
+         * within a list.
+         */
+        private Element getListElement(final int caretPosition) {
+            final Element paragraphElement = getParagraphElement(caretPosition);
+            final Element listElement = Util.findElementUp("ul", "ol", paragraphElement);
+            return listElement;
+        }
+
+        private boolean isValidParentElement(final Element e) {
+            final String name = e.getName();
+            return name.equalsIgnoreCase(HTML.Tag.BODY.toString()) || name.equalsIgnoreCase(HTML.Tag.TD.toString())
+                    || name.equalsIgnoreCase(HTML.Tag.LI.toString());
+        }
+
+        private boolean isValidElement(final Element e) {
+            final String name = e.getName();
+            return name.equalsIgnoreCase(HTML.Tag.P.toString()) || name.equalsIgnoreCase(HTML.Tag.UL.toString())
+                    || name.equalsIgnoreCase(HTML.Tag.OL.toString()) || name.equalsIgnoreCase(HTML.Tag.H1.toString())
+                    || name.equalsIgnoreCase(HTML.Tag.H2.toString()) || name.equalsIgnoreCase(HTML.Tag.H3.toString())
+                    || name.equalsIgnoreCase(HTML.Tag.H4.toString()) || name.equalsIgnoreCase(HTML.Tag.H5.toString())
+                    || name.equalsIgnoreCase(HTML.Tag.H6.toString());
+        }
+
+        private boolean isListRootElement(final Element e) {
+            final String name = e.getName();
+            return name.equalsIgnoreCase(HTML.Tag.UL.toString()) || name.equalsIgnoreCase(HTML.Tag.OL.toString());
+        }
+
+        /**
+         * Switches OFF list formatting for a given block of elements.
+         *
+         * <p>Switches off all list formatting inside the block for the
+         * given tag.</p>
+         *
+         * <p>Splits lists if the selection covers only part of a list.</p>
+         * @throws BadLocationException 
+         * @throws IOException 
+         */
+        private void listOff() throws IOException, BadLocationException {
+            final int selectionStart = getSelectionStart();
+            final int selectionEnd = getSelectionEnd();
+            final Element firstParagraphElement = getParagraphElement(selectionStart);
+            final int fistParagraphElementStart = firstParagraphElement.getStartOffset();
+            final int lastParagraphElementEnd = getParagraphElement(selectionEnd).getEndOffset();
+            final Element parentOfTheListElement = getListParent(firstParagraphElement);
+            if (isListElement(parentOfTheListElement)) {
+                // Currently, no support for nested lists.
+                return;
+            }
+            final SHTMLWriter sHTMLwriter = new SHTMLWriter(getSHTMLDocument());
+            int elementIdx;
+            Element nextElement = null;
+            for (elementIdx = 0; elementIdx < parentOfTheListElement.getElementCount(); elementIdx++) {
+                nextElement = parentOfTheListElement.getElement(elementIdx);
+                if (nextElement.getEndOffset() > fistParagraphElementStart) {
+                    break;
+                }
+            }
+            final Element startElementToBeReplaced = nextElement;
+            int nrElementsToBeReplaced = 1;
+            int listItemIdx = 0;
+            Element listItemElement = null;
+            if (nextElement.getStartOffset() < fistParagraphElementStart) {
+                sHTMLwriter.writeStartTag(nextElement);
+                elementIdx++;
+                // Write list item elements before the selection. 
+                for (;; listItemIdx++) {
+                    listItemElement = nextElement.getElement(listItemIdx);
+                    if (listItemElement.getStartOffset() == fistParagraphElementStart) {
+                        break;
+                    }
+                    sHTMLwriter.write(listItemElement);
+                }
+                sHTMLwriter.writeEndTag(nextElement);
+                // Turn the list item elements in the selection into paragraph element.
+                for (; listItemIdx < nextElement.getElementCount(); listItemIdx++) {
+                    listItemElement = nextElement.getElement(listItemIdx);
+                    if (listItemElement.getStartOffset() >= lastParagraphElementEnd) {
+                        break;
+                    }
+                    sHTMLwriter.writeStartTag("p", null);
+                    sHTMLwriter.writeChildElements(listItemElement);
+                    sHTMLwriter.writeEndTag("p");
+                }
+            }
+            if (nextElement.getEndOffset() <= lastParagraphElementEnd) {
+                for (; elementIdx < parentOfTheListElement.getElementCount(); elementIdx++) {
+                    nextElement = parentOfTheListElement.getElement(elementIdx);
+                    if (nextElement.getEndOffset() > lastParagraphElementEnd) {
+                        break;
+                    }
+                    if (nextElement != startElementToBeReplaced
+                            && nextElement.getStartOffset() < lastParagraphElementEnd) {
+                        nrElementsToBeReplaced++;
+                    }
+                    if (isListRootElement(nextElement)) {
+                        for (listItemIdx = 0; listItemIdx < nextElement.getElementCount(); listItemIdx++) {
+                            sHTMLwriter.writeStartTag("p", null);
+                            sHTMLwriter.writeChildElements(nextElement.getElement(listItemIdx));
+                            sHTMLwriter.writeEndTag("p");
+                        }
+                    }
+                    else {
+                        sHTMLwriter.writeStartTag("p", null);
+                        sHTMLwriter.writeChildElements(nextElement);
+                        sHTMLwriter.writeEndTag("p");
+                    }
+                }
+            }
+            // nextElement is final at this point.
+            if (elementIdx <= parentOfTheListElement.getElementCount()
+                    && nextElement.getStartOffset() < lastParagraphElementEnd) {
+                if (nextElement != startElementToBeReplaced) {
+                    nrElementsToBeReplaced++;
+                }
+                for (; listItemIdx < nextElement.getElementCount(); listItemIdx++) {
+                    listItemElement = nextElement.getElement(listItemIdx);
+                    if (listItemElement.getStartOffset() >= lastParagraphElementEnd) {
+                        break;
+                    }
+                    sHTMLwriter.writeStartTag("p", null);
+                    sHTMLwriter.writeChildElements(listItemElement);
+                    sHTMLwriter.writeEndTag("p");
+                }
+                if (listItemIdx < nextElement.getElementCount()) {
+                    sHTMLwriter.writeStartTag(nextElement);
+                    for (; listItemIdx < nextElement.getElementCount(); listItemIdx++) {
+                        listItemElement = nextElement.getElement(listItemIdx);
+                        sHTMLwriter.write(listItemElement);
+                    }
+                    sHTMLwriter.writeEndTag(nextElement);
+                }
+            }
+            getSHTMLDocument().replaceHTML(startElementToBeReplaced, nrElementsToBeReplaced,
+                sHTMLwriter.getWrittenString());
+        }
+
+        /**
+         * switch ON list formatting for a given block of elements.
+         *
+         * <p>Takes care of merging existing lists before, after and inside
+         * respective element block.</p>
+         * @throws BadLocationException 
+         * @throws IOException 
+         *
+         */
+        private void listOn(final String listTag, final AttributeSet attributeSet, final boolean forceOff)
+                throws IOException, BadLocationException {
+            final int selectionStart = getSelectionStart();
+            final int selectionEnd = getSelectionEnd();
+            final Element firstParagraphElement = getParagraphElement(selectionStart);
+            int fistParagraphElementStart = firstParagraphElement.getStartOffset();
+            int lastParagraphElementEnd = getParagraphElement(selectionEnd).getEndOffset();
+            final Element parentElement = getListParent(firstParagraphElement);
+            Element startElementToBeRemoved = null;
+            int removeCount = 0;
+            final SHTMLWriter writer = new SHTMLWriter(getSHTMLDocument());
+            if (fistParagraphElementStart > 0) {
+                final Element before = getParagraphElement(fistParagraphElementStart - 1);
+                if (before.getName().equalsIgnoreCase(HTML.Tag.LI.toString())) {
+                    final Element listRoot = before.getParentElement();
+                    if (listRoot.getParentElement() == parentElement && listRoot.getName().equalsIgnoreCase(listTag)) {
+                        fistParagraphElementStart = listRoot.getStartOffset();
+                    }
+                }
+            }
+            if (lastParagraphElementEnd < getSHTMLDocument().getLength() - 1) {
+                final Element after = getParagraphElement(lastParagraphElementEnd);
+                if (after.getName().equalsIgnoreCase(HTML.Tag.LI.toString())) {
+                    final Element listRoot = after.getParentElement();
+                    if (listRoot.getParentElement() == parentElement && listRoot.getName().equalsIgnoreCase(listTag)) {
+                        lastParagraphElementEnd = listRoot.getEndOffset();
+                    }
+                }
+            }
+            int i;
+            Element next = null;
+            for (i = 0; i < parentElement.getElementCount(); i++) {
+                next = parentElement.getElement(i);
+                if (next.getEndOffset() > fistParagraphElementStart) {
+                    break;
+                }
+            }
+            startElementToBeRemoved = next;
+            removeCount = 1;
+            int j = 0;
+            Element li = null;
+            if (next.getStartOffset() < fistParagraphElementStart) {
+                i++;
+                writer.writeStartTag(next);
+                for (;; j++) {
+                    li = next.getElement(j);
+                    if (li.getStartOffset() == fistParagraphElementStart) {
+                        break;
+                    }
+                    writer.write(li);
+                }
+                writer.writeEndTag(next);
+                writer.writeStartTag(listTag, attributeSet);
+                for (; j < next.getElementCount(); j++) {
+                    li = next.getElement(j);
+                    if (li.getStartOffset() >= lastParagraphElementEnd) {
+                        break;
+                    }
+                    writer.write(li);
+                }
+            }
+            else {
+                writer.writeStartTag(listTag, attributeSet);
+            }
+            if (next.getEndOffset() <= lastParagraphElementEnd) {
+                for (; i < parentElement.getElementCount(); i++) {
+                    next = parentElement.getElement(i);
+                    if (next.getEndOffset() > lastParagraphElementEnd) {
+                        break;
+                    }
+                    if (startElementToBeRemoved != next && next.getStartOffset() < lastParagraphElementEnd) {
+                        removeCount++;
+                    }
+                    if (isListRootElement(next)) {
+                        writer.writeChildElements(next);
+                    }
+                    else {
+                        writer.writeStartTag("li", null);
+                        writer.writeChildElements(next);
+                        writer.writeEndTag("li");
+                    }
+                }
+            }
+            if (i < parentElement.getElementCount() && next.getStartOffset() < lastParagraphElementEnd) {
+                if (startElementToBeRemoved != next) {
+                    removeCount++;
+                }
+                for (; j < next.getElementCount(); j++) {
+                    li = next.getElement(j);
+                    if (li.getStartOffset() >= lastParagraphElementEnd) {
+                        break;
+                    }
+                    writer.write(li);
+                }
+                writer.writeEndTag(listTag);
+                if (j < next.getElementCount()) {
+                    writer.writeStartTag(next);
+                    for (; j < next.getElementCount(); j++) {
+                        li = next.getElement(j);
+                        writer.write(li);
+                    }
+                    writer.writeEndTag(next);
+                }
+            }
+            else {
+                writer.writeEndTag(listTag);
+            }
+            getSHTMLDocument().replaceHTML(startElementToBeRemoved, removeCount, writer.getWrittenString());
+        }
+
+        /**
+         * decide to switch on or off list formatting
+         * @return  true, if list formatting is to be switched on, false if not
+         * @throws SwitchListException 
+         */
+        private boolean switchOn(final String listTag, final AttributeSet attributeSet, final boolean forceOff,
+                                 final int start, final int end, final Element parentElement)
+                throws SwitchListException {
+            boolean listOn = false;
+            final int count = parentElement.getElementCount();
+            for (int i = 0; i < count && !listOn; i++) {
+                final Element elem = parentElement.getElement(i);
+                if (elem.getStartOffset() >= start && elem.getEndOffset() <= end && !isValidElement(elem)) {
+                    throw new SwitchListException();
+                }
+                final int eStart = elem.getStartOffset();
+                final int eEnd = elem.getEndOffset();
+                if (!elem.getName().equalsIgnoreCase(listTag)) {
+                    if (((eStart > start) && (eStart < end)) || ((eEnd > start) && (eEnd < end))
+                            || ((start >= eStart) && (end <= eEnd))) {
+                        listOn = true;
+                    }
+                }
+            }
+            return listOn;
+        }
+
+        /** */
+        private void toggleList(final String listTag, final AttributeSet attributeSet, final boolean forceOff) {
+            try {
+                final int selectionStart = getSelectionStart();
+                final int selectionEnd = getSelectionEnd();
+                final Element firstParagraphElement = getParagraphElement(selectionStart);
+                final int fistParagraphElementStart = firstParagraphElement.getStartOffset();
+                final int lastParagraphElementEnd = getParagraphElement(selectionEnd).getEndOffset();
+                final Element parentElement = getListParent(firstParagraphElement);
+                getSHTMLDocument().startCompoundEdit();
+                // Why is OL not a valid parent element? How could a parent element be invalid? --Dan
+                //if (!isValidParentElement(parentElement))
+                //  throw new SwitchListException();
+                if (selectionStart != selectionEnd) {
+                    final Element last = getParagraphElement(lastParagraphElementEnd - 1);
+                    if (parentElement != getListParent(last)) {
+                        throw new SwitchListException();
+                    }
+                }
+                //
+                if (!switchOn(listTag, attributeSet, forceOff, fistParagraphElementStart, lastParagraphElementEnd,
+                    parentElement) || forceOff) {
+                    listOff();
+                }
+                else {
+                    listOn(listTag, attributeSet, forceOff);
+                }
+                if (selectionStart == selectionEnd) {
+                    setCaretPosition(selectionStart);
+                }
+                else {
+                    select(selectionStart, selectionEnd);
+                }
+                requestFocus();
+            }
+            catch (final SwitchListException e) {
+            }
+            catch (final Exception e) {
+                Util.errMsg(null, e.getMessage(), e);
+            }
+            finally {
+                getSHTMLDocument().endCompoundEdit();
+            }
+        }
+
+        /** */
+        private boolean isListElement(final Element element) {
+            return "ul".equalsIgnoreCase(element.getName()) || "ol".equalsIgnoreCase(element.getName());
+        }
+
+        /** */
+        private boolean isListItemElement(final Element element) {
+            return "li".equalsIgnoreCase(element.getName());
+        }
+
+        /** Determines whether the caret is currently at the beginning of a list item. */
+        private boolean caretAtTheBeginningOfListItem() {
+            final Element parent = getCurrentParagraphElement().getParentElement();
+            return ("li".equalsIgnoreCase(parent.getName()) && getCaretPosition() == parent.getStartOffset());
+        }
+
+        /** Determines whether the caret is currently at the beginning of a list item. */
+        private boolean caretWithinListItem() {
+            final Element currentParagraphElement = getCurrentParagraphElement();
+            if(currentParagraphElement == null)
+            	return false;
+			final Element parent = currentParagraphElement.getParentElement();
+            return parent != null && "li".equalsIgnoreCase(parent.getName());
+        }
+
+        /** Increases the intent of selected list items. ("Including subitems" should default to "true".) */
+        private void increaseIndent(final boolean includingSubitems) {
+            final Element paragraphElement = getCurrentParagraphElement();
+            final Element listItemElement = paragraphElement.getParentElement();
+            if (!isListItemElement(listItemElement)) {
+                return;
+            }
+            // Increase indent
+            int selectionStart = getSelectionStart();
+            int selectionEnd = getSelectionEnd();
+            if (selectionStart != selectionEnd && getListElement(selectionStart) == getListElement(selectionEnd)) {
+                // Of block
+            }
+            else {
+                // Of single list item
+                selectionStart = getCaretPosition();
+                selectionEnd = getCaretPosition();
+            }
+            // 
+            final Element list = getListElement(selectionStart);
+            final int indexOfSelectionStart = list.getElementIndex(selectionStart);
+            final int indexOfSelectionEnd = list.getElementIndex(selectionEnd);
+            try {
+                getSHTMLDocument().startCompoundEdit();
+                final SHTMLWriter writer = new SHTMLWriter(getSHTMLDocument());
+                writer.writeStartTag(list);
+                for (int i = 0; i < indexOfSelectionStart - 1; i++) {
+                    writer.write(list.getElement(i));
+                }
+                Element tagModel = null;
+                if (indexOfSelectionStart > 0 && isListElement(list.getElement(indexOfSelectionStart - 1))) {
+                    tagModel = list.getElement(indexOfSelectionStart - 1);
+                }
+                else if (indexOfSelectionEnd + 1 < list.getElementCount()
+                        && isListElement(list.getElement(indexOfSelectionEnd + 1))) {
+                    tagModel = list.getElement(indexOfSelectionEnd + 1);
+                }
+                else {
+                    tagModel = list;
+                }
+                // The list item before the selection start should be the new parent.
+                if (indexOfSelectionStart == 0) {
+                    // Cannot increase indent of the first item in a list, unlike in MSO and OOo.
+                    return;
+                }
+                final Element newParentListItem = list.getElement(indexOfSelectionStart - 1);
+                writer.writeStartTag(newParentListItem);
+                writer.writeChildElements(newParentListItem);
+                //
+                writer.writeStartTag(tagModel);
+                for (int i = indexOfSelectionStart; i <= indexOfSelectionEnd; i++) {
+                    if (includingSubitems) {
+                        writer.write(list.getElement(i));
+                    }
+                    else {
+                        final Element listItem = list.getElement(i);
+                        writer.writeStartTag(listItem);
+                        for (int j = 0; j < listItem.getElementCount(); j++) {
+                            if (!isListElement(listItem.getElement(j))) {
+                                writer.write(listItem.getElement(j));
+                            }
+                        }
+                        writer.writeEndTag(listItem);
+                        for (int j = 0; j < listItem.getElementCount(); j++) {
+                            if (isListElement(listItem.getElement(j))) {
+                                writer.writeChildElements(listItem.getElement(j));
+                            }
+                        }
+                    }
+                }
+                writer.writeEndTag(tagModel);
+                writer.writeEndTag(newParentListItem);
+                //
+                for (int i = indexOfSelectionEnd + 1; i < list.getElementCount(); i++) {
+                    writer.write(list.getElement(i));
+                }
+                writer.writeEndTag(list);
+                final String newContent = writer.getWrittenString().replaceAll("(?ims)</ul>\\s*<ul[^>]*>", "")
+                    .replaceAll("(?ims)</ol>\\s*<ol[^>]*>", "");
+                getSHTMLDocument().setOuterHTML(list, newContent);
+                select(selectionStart, selectionEnd);
+            }
+            catch (final Exception ex) {
+            }
+            finally {
+                getSHTMLDocument().endCompoundEdit();
+            }
+        }
+
+        /** Decreases the indent of selected list items. ("Including subitems" should default to "true". */
+        private void decreaseIndent(final boolean includingSubitems) {
+            // The parameter "includingSubitems should always be set to "true". The value of "false" currently causes
+            // problems, in that it leads to the creation of incorrect HTML such as 
+            // <ul><ul><li>c</li></ul></ul>; the consecutive ULs are incorrect.
+            // Example:
+            // * a                   <-- Outer list item, beginning the outer list.
+            //   * b                 <-- Inner list. Cursor here, before "b".
+            //     * c
+            // * d
+            // paragraphElement: P or P-implied.
+            // parent: LI (b)
+            // list: UL (containing LI (b))
+            // outerListItem: LI (a)
+            // outerList: UL (containing LI (a) and the rest.)
+            // Result, with "including subitems" set to "true":
+            // * a
+            // * b
+            //   * c
+            // * d
+            final Element paragraphElement = getCurrentParagraphElement();
+            final Element parent = paragraphElement.getParentElement();
+            // Guard 1
+            if (!isListItemElement(parent)) {
+                return;
+            }
+            // Guard 2
+            final Element list = parent.getParentElement();
+            final Element outerListItem = list.getParentElement();
+            if (!isListItemElement(outerListItem)) {
+                return; // Already the outermost item.
+            }
+            final Element outerList = outerListItem.getParentElement();
+            // Decrease indent
+            int selectionStart = getSelectionStart();
+            int selectionEnd = getSelectionEnd();
+            if (selectionStart != selectionEnd && getListElement(selectionStart) == getListElement(selectionEnd)) {
+                // Of block
+            }
+            else {
+                // Of single list item
+                selectionStart = getCaretPosition();
+                selectionEnd = getCaretPosition();
+            }
+            final int indexOfSelectionStart = list.getElementIndex(selectionStart);
+            final int indexOfSelectionEnd = list.getElementIndex(selectionEnd);
+            final int indexOfSelectionInOuterItem = outerListItem.getElementIndex(selectionStart);
+            final int indexOfSelectionInOuterList = outerList.getElementIndex(selectionStart);
+            try {
+                getSHTMLDocument().startCompoundEdit();
+                final SHTMLWriter writer = new SHTMLWriter(getSHTMLDocument());
+                // Write the beginning of the outer list
+                writer.writeStartTag(outerList);
+                for (int i = 0; i < indexOfSelectionInOuterList; i++) {
+                    writer.write(outerList.getElement(i));
+                }
+                // Write the beginning of the outer list item
+                writer.writeStartTag(outerListItem);
+                for (int i = 0; i < indexOfSelectionInOuterItem; i++) {
+                    writer.write(outerListItem.getElement(i));
+                }
+                // Write the beginning of the inner list
+                if (indexOfSelectionStart > 0) {
+                    writer.writeStartTag(list);
+                    for (int i = 0; i < indexOfSelectionStart; i++) {
+                        writer.write(list.getElement(i));
+                    }
+                    writer.writeEndTag(list);
+                }
+                // Close the outer list item
+                writer.writeEndTag(outerListItem);
+                // Write the promoted (moved to the left) items except for the last one
+                for (int i = indexOfSelectionStart; i <= indexOfSelectionEnd - 1; i++) {
+                    if (includingSubitems) {
+                        writer.write(list.getElement(i));
+                    }
+                    else {
+                        writeListItemForDecreaseIndent(writer, list.getElement(i), includingSubitems, false);
+                    }
+                }
+                // Write the end of the inner list into the last promoted item
+                writeListItemForDecreaseIndent(writer, list.getElement(indexOfSelectionEnd), includingSubitems, /*withoutEndTag=*/
+                true);
+                if ((indexOfSelectionEnd + 1) < list.getElementCount()) {
+                    writer.writeStartTag(list);
+                    for (int i = indexOfSelectionEnd + 1; i < list.getElementCount(); i++) {
+                        writer.write(list.getElement(i));
+                    }
+                    writer.writeEndTag(list);
+                }
+                writer.writeEndTag(list.getElement(indexOfSelectionEnd));
+                // Write the end of the outer list item, as another list item
+                if (indexOfSelectionInOuterItem + 1 < outerListItem.getElementCount()) {
+                    writer.writeStartTag(outerListItem);
+                    for (int i = indexOfSelectionInOuterItem + 1; i < outerListItem.getElementCount(); i++) {
+                        writer.write(outerListItem.getElement(i));
+                    }
+                    writer.writeEndTag(outerListItem);
+                }
+                // Write the end of the outer list
+                for (int i = indexOfSelectionInOuterList + 1; i < outerList.getElementCount(); i++) {
+                    writer.write(outerList.getElement(i));
+                }
+                writer.writeEndTag(outerList);
+                final String newContent = writer.getWrittenString().replaceAll("(?ims)</ul>\\s*<ul>", "")
+                    .replaceAll("(?ims)</ol>\\s*<ol>", "");
+                getSHTMLDocument().setOuterHTML(outerList, newContent);
+                select(selectionStart, selectionEnd);
+            }
+            catch (final Exception ex) {
+            }
+            finally {
+                getSHTMLDocument().endCompoundEdit();
+            }
+        }
+
+        /** Writes the list item for the "descrease indent" action. */
+        private void writeListItemForDecreaseIndent(final SHTMLWriter writer, final Element listItem,
+                                                    final boolean includingSubitems, final boolean withoutEndTag) {
+            try {
+                writer.writeStartTag(listItem);
+                if (includingSubitems) {
+                    writer.writeChildElements(listItem);
+                }
+                else {
+                    boolean childListItemsPresent = false;
+                    // Write all child elements that are not list items
+                    for (int j = 0; j < listItem.getElementCount(); j++) {
+                        if (isListElement(listItem.getElement(j))) {
+                            childListItemsPresent = true;
+                        }
+                        else {
+                            writer.write(listItem.getElement(j));
+                        }
+                    }
+                    //
+                    if (childListItemsPresent) {
+                        writer.writeStartTag(listItem.getParentElement());
+                        for (int j = 0; j < listItem.getElementCount(); j++) {
+                            if (isListElement(listItem.getElement(j))) {
+                                writer.write(listItem.getElement(j));
+                            }
+                        }
+                        writer.writeEndTag(listItem.getParentElement());
+                    }
+                }
+                if (!withoutEndTag) {
+                    writer.writeEndTag(listItem);
+                }
+            }
+            catch (final Exception ex) {
+            }
+        }
+
+        /** Performs the action appropriate on pressing of the key delete, as far as lists
+         *  are concerned, treating those cases that Java handles poorly. Returns whether
+         *  intervention was necessary. */
+        private boolean deleteNextChar(final ActionEvent actionEvent) {
+            final int nextPosition = getCaretPosition() + 1;
+            final SHTMLDocument doc = getSHTMLDocument();
+            final Element listAtNextPosition = getListElement(nextPosition);
+            if (listAtNextPosition != null && listAtNextPosition.getStartOffset() == nextPosition) {
+                // List element starting at the next position.
+                if (!caretWithinListItem()) {
+                    if (elementIsEmptyParagraph(getCurrentParagraphElement())) {
+                        return false;
+                    }
+                    mergeSecondElementIntoFirst(getParagraphElement(getCaretPosition()),
+                        getListItemElement(nextPosition));
+                    return true;
+                }
+                else {
+                    // Caret within list item.
+                    final Element listAtCaret = getListElement(getCaretPosition());
+                    final boolean isSurroundingList = listAtCaret.getStartOffset() <= listAtNextPosition
+                        .getStartOffset() && listAtCaret.getEndOffset() >= listAtNextPosition.getEndOffset();
+                    if (isSurroundingList) {
+                        mergeNestedListItemIntoParent(getListItemElement(getCaretPosition()),
+                            getListItemElement(nextPosition));
+                        return true;
+                    }
+                    else {
+                        // Two adjacent lists. To be merged.
+                        return false;
+                    }
+                }
+            }
+            // Empty paragraph within a list item.
+            if (caretWithinListItem()) {
+                final Element paragraphElement = getCurrentParagraphElement();
+                final boolean emptyParagraph = elementIsEmptyParagraph(paragraphElement);
+                if (emptyParagraph) {
+                    // Remove the empty paragraph manually, to avoid quircks.          
+                    removeElement(paragraphElement);
+                    //setCaretPosition(getCaretPosition() - 1);
+                    return true;
+                }
+            }
+            // List item element starting at the next position
+            final Element listItem = getListItemElement(nextPosition);
+            if (listItem != null && listItem.getStartOffset() == nextPosition) {
+                mergeSecondElementIntoFirst(getListItemElement(getCaretPosition()), listItem);
+                return true;
+            }
+            final Element listElementAtCurrentPosition = getListElement(getCaretPosition());
+            final Element parentElementOfNextPosition = doc.getParagraphElement(nextPosition).getParentElement();
+            if (listElementAtCurrentPosition != null && !isListItemElement(parentElementOfNextPosition)) {
+                // A non-list after a list.
+                // Avoid currently buggy behavior. A workaround.
+                if ("body".equalsIgnoreCase(parentElementOfNextPosition.getName())
+                        || getTableCell(getCaretPosition()) == getTableCell(nextPosition)) {
+                    mergeSecondElementIntoFirst(getListItemElement(getCaretPosition()),
+                        getParagraphElement(nextPosition));
+                }
+                else {
+                    performDefaultKeyStrokeAction(KeyEvent.VK_RIGHT, 0, actionEvent);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        /** Performs the action appropriate on pressing of the key backspace, as far as lists
+         *  are concerned, treating those cases that Java's Swing handles poorly. Returns whether
+         *  intervention was necessary. */
+        private boolean deletePrevChar(final ActionEvent actionEvent) {
+            final int selectionStart = getSelectionStart();
+            final Element list = getListElement(selectionStart);
+            if (list != null && list.getStartOffset() == selectionStart) {
+                // A list starts at the caret position.
+                final Element listAtPrevPosition = selectionStart == 0 ? null : getListElement(selectionStart - 1);
+                if (listAtPrevPosition == null) {
+                    performToggleListAction(actionEvent, list.getName());
+                    return true;
+                }
+                final boolean isSurroundingList = listAtPrevPosition.getStartOffset() <= list.getStartOffset()
+                        && listAtPrevPosition.getEndOffset() >= list.getEndOffset();
+                if (isSurroundingList) {
+                    mergeNestedListItemIntoParent(getListItemElement(selectionStart - 1),
+                        getListItemElement(selectionStart));
+                    return true;
+                }
+                else {
+                    // Two adjacent lists. To be merged.
+                    return false;
+                }
+            }
+            // Empty paragraph within a list item.
+            if (caretWithinListItem()) {
+                final Element paragraphElement = getCurrentParagraphElement();
+                final boolean emptyParagraph = elementIsEmptyParagraph(paragraphElement);
+                if (emptyParagraph) {
+                    // Remove the empty paragraph manually, to avoid quirks.          
+                    removeElement(paragraphElement);
+                    setCaretPosition(getCaretPosition() - 1);
+                    return true;
+                }
+            }
+            final Element listItem = getListItemElement(selectionStart);
+            if (listItem != null && listItem.getStartOffset() == selectionStart) {
+                // List item starts at the current position.
+                final int previousPosition = listItem.getStartOffset() - 1;
+                mergeSecondElementIntoFirst(getListItemElement(previousPosition), listItem);
+                setCaretPosition(previousPosition);
+                return true;
+            }
+            if (selectionStart > 0) {
+                final int previousPosition = selectionStart - 1;
+                final Element listElementAtPreviousPosition = getListElement(previousPosition);
+                final Element parentElement = getCurrentParagraphElement().getParentElement();
+                if (listElementAtPreviousPosition != null && !"li".equalsIgnoreCase(parentElement.getName())) {
+                    // A non-list after a list.
+                    // Avoid currently buggy behavior. A workaround.
+                    if ("body".equalsIgnoreCase(parentElement.getName())
+                            || getTableCell(previousPosition) == getTableCell(selectionStart)) {
+                        mergeSecondElementIntoFirst(getListItemElement(previousPosition),
+                            getParagraphElement(selectionStart));
+                    }
+                    else {
+                        performDefaultKeyStrokeAction(KeyEvent.VK_LEFT, 0, actionEvent);
+                    }
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /** Determines whether a list item element contains nested list items. */
+        private boolean containsNestedListItems(final Element listItem) {
+            for (int i = 0; i < listItem.getElementCount(); i++) {
+                if (isListElement(listItem.getElement(i))) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /** Merges the second paragraph element into the first one,
+         * setting the caret at the point where the two elements are newly joined. */
+        private void mergeSecondElementIntoFirst(final Element first, final Element second) {
+            final SHTMLDocument doc = (SHTMLDocument) getDocument();
+            final SHTMLWriter writer = new SHTMLWriter(doc);
+            doc.startCompoundEdit();
+            try {
+                int finalCaretPosition = first.getEndOffset() - 1;
+                writer.writeStartTag(first);
+                writer.writeChildElements(first);
+                writer.removeLastWrittenNewline();
+                writer.writeChildElements(second);
+                writer.writeEndTag(first);
+                getSHTMLDocument().setOuterHTML(first, writer.getWrittenString());
+                removeElement(second);
+                finalCaretPosition = Math.min(finalCaretPosition, first.getEndOffset() - 1);
+                setCaretPosition(finalCaretPosition);
+            }
+            catch (final IOException e) {
+                e.printStackTrace();
+            }
+            catch (final BadLocationException e) {
+                e.printStackTrace();
+            }
+            finally {
+                doc.endCompoundEdit();
+            }
+        }
+
+        /** Merges a nested list item into a list item in the parent list. (Inaccurate description.)
+         * See also {@link #mergeSecondElementIntoFirst(Element first, Element second)}. 
+         * @param parentListItem a list item
+         * @param childListItem a list item 
+         */
+        private void mergeNestedListItemIntoParent(final Element parentListItem, final Element childListItem) {
+            final SHTMLDocument doc = (SHTMLDocument) getDocument();
+            final SHTMLWriter writer = new SHTMLWriter(doc);
+            doc.startCompoundEdit();
+            try {
+                if (!isListItemElement(parentListItem)) {
+                    return;
+                }
+                final int finalCaretPosition = parentListItem.getElement(0).getEndOffset() - 1;
+                writer.writeStartTag(parentListItem);
+                for (int i = 0; i < parentListItem.getElementCount(); i++) {
+                    if (!isListElement(parentListItem.getElement(i))) {
+                        writer.write(parentListItem.getElement(i));
+                    }
+                }
+                writer.removeLastWrittenNewline();
+                writer.writeChildElements(childListItem);
+                for (int i = 0; i < parentListItem.getElementCount(); i++) {
+                    if (isListElement(parentListItem.getElement(i))) {
+                        // Write the nested list except for the merged child.
+                        final Element list = parentListItem.getElement(i);
+                        if (list.getElementCount() >= 2) {
+                            // Write the nested list only if it had at least two elements.
+                            writer.writeStartTag(list);
+                            for (int j = 0; j < list.getElementCount(); j++) {
+                                if (list.getElement(j) != childListItem) {
+                                    writer.write(list.getElement(j));
+                                }
+                            }
+                            writer.writeEndTag(list);
+                        }
+                    }
+                }
+                writer.writeEndTag(parentListItem);
+                getSHTMLDocument().setOuterHTML(parentListItem, writer.getWrittenString());
+                setCaretPosition(finalCaretPosition);
+            }
+            catch (final IOException e) {
+                e.printStackTrace();
+            }
+            catch (final BadLocationException e) {
+                e.printStackTrace();
+            }
+            finally {
+                doc.endCompoundEdit();
+            }
+        }
+
+        /** Inserts a new list item after the current list item, breaking the text in the list
+         * item into two parts if the caret is not at the end of the current list item. */
+        private void newListItem() {
+            final SHTMLDocument doc = getSHTMLDocument();
+            final int caretPosition = getCaretPosition();
+            final Element listItemElement = listManager.getListItemElement(caretPosition);
+            if (listItemElement == null) {
+                return;
+            }
+            try {
+                final String listItemContent = elementToHTML(listItemElement);
+                if (listItemContent.matches("(?ims)\\s*<li[^>]*>\\s*</li>\\s*")) {
+                    // Empty list item, so switch the list off.
+                    toggleList("", null, true);
+                    return;
+                }
+                final int so = listItemElement.getStartOffset();
+                final int eo = listItemElement.getEndOffset();
+                if (so != eo) {
+                    final StringWriter stringWriter = new StringWriter();
+                    final SHTMLWriter writer = new SHTMLWriter(stringWriter, doc);
+                    writer.writeStartTag(listItemElement);
+                    if (caretPosition > so) {
+                        final SHTMLWriter htmlStartWriter = new SHTMLWriter(stringWriter, doc, so, caretPosition - so);
+                        htmlStartWriter.writeChildElements(listItemElement);
+                    }
+                    writer.writeEndTag(listItemElement);
+                    writer.writeStartTag(listItemElement);
+                    if (containsNestedListItems(listItemElement)
+                            && (listItemElement.getElement(0).getEndOffset() - 1) == caretPosition) {
+                        // Contains nested list and the caret is at the end of the list items's paragraph.
+                        // Let it be. Workaround for the user: press undo.
+                        // ---Old:---
+                        // Block the action. User can enter new item by pressing enter when the caret
+                        // is not at the end of the list item.
+                        //return;
+                        //stringWriter.write("<p></p>");
+                        // A workaround. Otherwise, the caret cannot reach the position in the new 
+                        // list item. Ideally, Java's editor kit would create implied paragraph, which
+                        // it does not.
+                    }
+                    if (caretPosition < eo - 1) {
+                        final SHTMLWriter htmlEndWriter = new SHTMLWriter(stringWriter, doc, caretPosition, eo
+                                - caretPosition);
+                        htmlEndWriter.writeChildElements(listItemElement);
+                    }
+                    writer.writeEndTag(listItemElement);
+                    final String text = stringWriter.toString();
+                    try {
+                        doc.startCompoundEdit();
+                        doc.setOuterHTML(listItemElement, text);
+                    }
+                    catch (final Exception e) {
+                        Util.errMsg(null, e.getMessage(), e);
+                    }
+                    finally {
+                        doc.endCompoundEdit();
+                    }
+                    setCaretPosition(caretPosition + 1);
+                }
+            }
+            catch (final Exception ex) {
+            }
+        }
+    }
+
+    /** remember current selection when mouse button is released */
+    void this_mouseReleased(final MouseEvent e) {
+        lastSelStart = getSelectionStart();
+        lastSelEnd = getSelectionEnd();
+    }
+
+    /** remember current selection when mouse button is double clicked */
+    void this_mouseClicked(final MouseEvent e) {
+        if (e.getClickCount() > 1) {
+            lastSelStart = getSelectionStart();
+            lastSelEnd = getSelectionEnd();
+        }
+    }
+
+    /** is invoked if the user modifies the current drop gesture */
+    public void dropActionChanged(final DropTargetDragEvent event) {
+    }
+
+    /** is invoked when the user changes the dropAction */
+    public void dropActionChanged(final DragSourceDragEvent event) {
+    }
+
+    /** is invoked when you are dragging over the DropSite */
+    public void dragEnter(final DropTargetDragEvent event) {
+    }
+
+    /** is invoked when you are exit the DropSite without dropping */
+    public void dragExit(final DropTargetEvent event) {
+    }
+
+    /**
+     * this message goes to DragSourceListener, informing it that the dragging
+     * has entered the DropSite
+     */
+    public void dragEnter(final DragSourceDragEvent event) {
+    }
+
+    /**
+     * this message goes to DragSourceListener, informing it that the dragging
+     * has exited the DropSite
+     */
+    public void dragExit(final DragSourceEvent event) {
+    }
+
+    /**
+     * this message goes to DragSourceListener, informing it that
+     * the dragging is currently ocurring over the DropSite
+     */
+    public void dragOver(final DragSourceDragEvent event) {
+    }
+
+    // ------ end of drag and drop implementation ----------------------------
+    /* ------ start of cut, copy and paste implementation ------------------- */
+    public TransferHandler getTransferHandler() {
+        final TransferHandler defaultTransferHandler = super.getTransferHandler();
+        if (defaultTransferHandler == null) {
+            return null;
+        }
+        class LocalTransferHandler extends TransferHandler {
+            /* (non-Javadoc)
+             * @see javax.swing.TransferHandler#canImport(javax.swing.JComponent, java.awt.datatransfer.DataFlavor[])
+             */
+            public boolean canImport(final JComponent comp, final DataFlavor[] transferFlavors) {
+                return defaultTransferHandler.canImport(comp, transferFlavors);
+            }
+
+            /* (non-Javadoc)
+             * @see javax.swing.TransferHandler#exportAsDrag(javax.swing.JComponent, java.awt.event.InputEvent, int)
+             */
+            public void exportAsDrag(final JComponent comp, final InputEvent e, final int action) {
+                defaultTransferHandler.exportAsDrag(comp, e, action);
+            }
+
+            /* (non-Javadoc)
+             * @see javax.swing.TransferHandler#exportToClipboard(javax.swing.JComponent, java.awt.datatransfer.Clipboard, int)
+             */
+            public void exportToClipboard(final JComponent comp, final Clipboard clip, final int action) {
+                final SHTMLDocument document = (SHTMLDocument) getDocument();
+                if (document.getParagraphElement(getSelectionStart()) != document
+                    .getParagraphElement(getSelectionEnd())) {
+                    defaultTransferHandler.exportToClipboard(comp, clip, action);
+                    return;
+                }
+                try {
+                    final HTMLText htmlText = new HTMLText();
+                    final int start = getSelectionStart();
+                    htmlText.copyHTML(SHTMLEditorPane.this, start, getSelectionEnd() - start);
+                    final Transferable additionalContents = new HTMLTextSelection(htmlText);
+                    final Clipboard temp = new Clipboard("");
+                    defaultTransferHandler.exportToClipboard(comp, temp, action);
+                    final Transferable defaultContents = temp.getContents(this);
+                    if (defaultContents == null) {
+                        return;
+                    }
+                    clip.setContents(new Transferable() {
+                        public DataFlavor[] getTransferDataFlavors() {
+                            final DataFlavor[] defaultFlavors = defaultContents.getTransferDataFlavors();
+                            final DataFlavor[] additionalFlavors = additionalContents.getTransferDataFlavors();
+                            final DataFlavor[] resultFlavor = new DataFlavor[defaultFlavors.length
+                                    + additionalFlavors.length];
+                            System.arraycopy(defaultFlavors, 0, resultFlavor, 0, defaultFlavors.length);
+                            System.arraycopy(additionalFlavors, 0, resultFlavor, defaultFlavors.length,
+                                additionalFlavors.length);
+                            return resultFlavor;
+                        }
+
+                        public boolean isDataFlavorSupported(final DataFlavor flavor) {
+                            return additionalContents.isDataFlavorSupported(flavor)
+                                    || defaultContents.isDataFlavorSupported(flavor);
+                        }
+
+                        public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException,
+                                IOException {
+                            if (additionalContents.isDataFlavorSupported(flavor)) {
+                                return additionalContents.getTransferData(flavor);
+                            }
+                            return defaultContents.getTransferData(flavor);
+                        }
+                    }, null);
+                }
+                catch (final Exception e) {
+                    getToolkit().beep();
+                }
+            }
+
+            /* (non-Javadoc)
+             * @see javax.swing.TransferHandler#getSourceActions(javax.swing.JComponent)
+             */
+            public int getSourceActions(final JComponent c) {
+                return defaultTransferHandler.getSourceActions(c);
+            }
+
+            /* (non-Javadoc)
+             * @see javax.swing.TransferHandler#getVisualRepresentation(java.awt.datatransfer.Transferable)
+             */
+            public Icon getVisualRepresentation(final Transferable t) {
+                return defaultTransferHandler.getVisualRepresentation(t);
+            }
+
+            /* (non-Javadoc)
+             * @see javax.swing.TransferHandler#importData(javax.swing.JComponent, java.awt.datatransfer.Transferable)
+             */
+            public boolean importData(final JComponent comp, final Transferable transferable) {
+            	final SHTMLDocument doc = (SHTMLDocument) getDocument();
+                doc.startCompoundEdit();
+                boolean result = false;
+                try {
+                	//System.out.format("getPasteMode()=%s\n", getPasteMode());
+                	if (getPasteMode() == PasteMode.PASTE_PLAIN_TEXT)
+                	{
+                		final String content = transferable.getTransferData(DataFlavor.stringFlavor).toString();
+                		if (content != null)
+                		{
+                			replaceSelection(content);
+                		}
+                		result = true;           		
+                	}
+                	else if (transferable.isDataFlavorSupported(htmlTextDataFlavor)) {
+                        // This path is taken if:
+                        // (a) the copy and paste is internal, from SimplyHTML to SimplyHTML, and
+                        // (b) the copied part is not multi paragraph.
+                        final HTMLText htmlText = (HTMLText) transferable.getTransferData(htmlTextDataFlavor);
+                        replaceSelection(htmlText);
+                        result = true;
+                    }
+                    else {
+                        final DataFlavor htmlFlavor = new DataFlavor("text/html; class=java.lang.String");
+                        String stringContent = null;
+                        String htmlContent = null;
+                        if (transferable.isDataFlavorSupported(htmlFlavor)
+                                && transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+                            htmlContent = (String) transferable.getTransferData(htmlFlavor);
+                            if (htmlContent.charAt(0) == 65533) {
+                                return importDataWithoutHtmlFlavor(comp, transferable);
+                            }
+                            stringContent = (String) transferable.getTransferData(DataFlavor.stringFlavor);
+                            htmlContent = new Remover(htmlContent).removeFirstAndBefore("body").removeLastAndAfter("/body")
+                            	.getProcessedText()	
+                            	.replaceAll("<!--StartFragment-->", "")
+                                .replaceAll("<!--EndFragment-->", "");
+                            final HTMLText htmlText = new HTMLText(htmlContent, stringContent);
+                            replaceSelection(htmlText);
+                            result = true;
+                        }
+                        else {
+                            //result = defaultImportData(comp, transferable);
+                            result = importExternalData(comp, transferable);
+                        }
+                    }
+                }
+                catch (final Exception e) {
+                    getToolkit().beep();
+                }
+                doc.endCompoundEdit();
+                return result;
+            }
+
+            private boolean importExternalData(final JComponent comp, final Transferable t)
+                    throws ClassNotFoundException, UnsupportedFlavorException, IOException {
+                // workaround for java decoding bug 
+                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6740877
+                final DataFlavor htmlFlavor = new DataFlavor("text/html; class=java.lang.String");
+                if (t.isDataFlavorSupported(htmlFlavor)) {
+                    final String s = (String) t.getTransferData(htmlFlavor);
+                    if (s.charAt(0) == 65533) {
+                        return importDataWithoutHtmlFlavor(comp, t);
+                    }
+                }
+                return defaultImportData(comp, t);
+            }
+
+            private boolean importDataWithoutHtmlFlavor(final JComponent comp, final Transferable t) {
+                return defaultImportData(comp, new Transferable() {
+                    public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException,
+                            IOException {
+                        if (isValid(flavor)) {
+                            return t.getTransferData(flavor);
+                        }
+                        throw new UnsupportedFlavorException(flavor);
+                    }
+
+                    public DataFlavor[] getTransferDataFlavors() {
+                        final DataFlavor[] transferDataFlavors = t.getTransferDataFlavors();
+                        int counter = 0;
+                        for (int i = 0; i < transferDataFlavors.length; i++) {
+                            if (isValid(transferDataFlavors[i])) {
+                                counter++;
+                            }
+                        }
+                        final DataFlavor[] validDataFlavors = new DataFlavor[counter];
+                        int j = 0;
+                        for (int i = 0; i < transferDataFlavors.length; i++) {
+                            final DataFlavor flavor = transferDataFlavors[i];
+                            if (isValid(flavor)) {
+                                validDataFlavors[j++] = flavor;
+                            }
+                        }
+                        return validDataFlavors;
+                    }
+
+                    public boolean isDataFlavorSupported(final DataFlavor flavor) {
+                        return isValid(flavor) && t.isDataFlavorSupported(flavor);
+                    }
+
+                    private boolean isValid(final DataFlavor flavor) {
+                        return !flavor.isMimeTypeEqual("text/html");
+                    }
+                });
+            }
+
+            private boolean defaultImportData(final JComponent comp, final Transferable t) {
+                return defaultTransferHandler.importData(comp, t);
+            }
+        }
+        return new LocalTransferHandler();
+    }
+
+    /* ------ end of cut, copy and paste implementation --------------- */
+    /* ------ start of font/paragraph manipulation --------------- */
+    public void removeCharacterAttributes() {
+        final int p0 = getSelectionStart();
+        final int p1 = getSelectionEnd();
+        if (p0 != p1) {
+            final SHTMLDocument doc = (SHTMLDocument) getDocument();
+            doc.startCompoundEdit();
+            SHTMLEditorKit.removeCharacterAttributes(doc, null, p0, p1 - p0);
+            doc.endCompoundEdit();
+        }
+    }
+
+    public void removeParagraphAttributes() {
+        final int p0 = getSelectionStart();
+        final int p1 = getSelectionEnd();
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        doc.removeParagraphAttributes(p0, p1 - p0 + 1);
+        select(p0, p1);
+    }
+
+    public void applyAttributes(final AttributeSet attributeSet, final boolean applyToCompleteParagraph) {
+        applyAttributes(attributeSet, applyToCompleteParagraph, false);
+    }
+
+    /**
+     * Sets the attributes for a given part of this editor. If a range of
+     * text is selected, the attributes are applied to the selection.
+     * If nothing is selected, the input attributes of the given
+     * editor are set thus applying the given attributes to future
+     * inputs.
+     *
+     * @param attributeSet  the set of attributes to apply
+     * @param applyToCompleteParagraph  true, if the attributes shall be applied to the whole
+     *     paragraph, false, if only the selected range of characters shall have them
+     * @param replace  true, if existing attribtes are to be replaced, false if not
+     */
+    public void applyAttributes(final AttributeSet attributeSet, final boolean applyToCompleteParagraph,
+                                final boolean replace) {
+        final SHTMLDocument doc = getSHTMLDocument();
+        requestFocus();
+        final int selectionStart = getSelectionStart();
+        final int selectionEnd = getSelectionEnd();
+        if (applyToCompleteParagraph) {
+            doc.setParagraphAttributes(selectionStart, selectionEnd - selectionStart, attributeSet, replace);
+        }
+        else {
+            if (selectionEnd != selectionStart) {
+                doc.setCharacterAttributes(selectionStart, selectionEnd - selectionStart, attributeSet, replace);
+            }
+            else {
+                final MutableAttributeSet inputAttributes = ((SHTMLEditorKit) getEditorKit()).getInputAttributes();
+                inputAttributes.addAttributes(attributeSet);
+            }
+        }
+    }
+
+    /** (Unfinished.)*/
+    public void applyCharacterTag(final String tag) {
+        final int selectionStart = getSelectionStart();
+        final int selectionEnd = getSelectionEnd();
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        doc.startCompoundEdit();
+        doc.endCompoundEdit();
+    }
+
+    /**
+     * Switches the elements in the current selection to the given tag. If allowedTags
+     * is non-null, applies the tag only if it is contained in allowedTags.
+     * 
+     * TODO: The new parameter does not work. So the method only works for paragraph tags,
+     * like H1, H2 etc. --Dan
+     *
+     * @param tag  the tag name to switche elements to
+     * @param overwritableTags  Tags that may be overwritten by the new tag.
+     */
+    public void applyParagraphTag(final String tag, final Vector overwritableTags) {
+        final int selectionStart = getSelectionStart();
+        final int selectionEnd = getSelectionEnd();
+        final StringWriter stringWriter = new StringWriter();
+        final SHTMLDocument doc = (SHTMLDocument) getDocument();
+        try {
+            doc.startCompoundEdit();
+            final SHTMLWriter writer = new SHTMLWriter(stringWriter, doc);
+            final Element paragraphElement = doc.getParagraphElement(selectionStart);
+            final int regionStart = paragraphElement.getStartOffset();
+            final int regionEnd = Math.max(paragraphElement.getEndOffset(), selectionEnd);
+            //System.out.println("SHTMLEditorPane applyTag start=" + start + ", end=" + end);
+            final Element parentOfparagraphElement = paragraphElement.getParentElement();
+            int replaceStart = -1;
+            int replaceEnd = -1;
+            int index = -1;
+            int elementsToRemoveCount = 0;
+            final int elementCount = parentOfparagraphElement.getElementCount();
+            //System.out.println("SHTMLEditorPane applyTag parent elem=" + elem.getName() + ", eCount=" + eCount);
+            for (int i = 0; i < elementCount; i++) {
+                final Element child = parentOfparagraphElement.getElement(i);
+                //System.out.println("SHTMLEditorPane applyTag child elem=" + child.getName() + ", eCount=" + eCount);
+                final int elementStart = child.getStartOffset();
+                final int elementEnd = child.getEndOffset();
+                //System.out.println("SHTMLEditorPane applyTag eStart=" + eStart + ", eEnd=" + eEnd);
+                if ((elementStart >= regionStart && elementStart < regionEnd)
+                        || (elementEnd > regionEnd && elementEnd <= regionEnd)) {
+                    elementsToRemoveCount++;
+                    if (overwritableTags.contains(child.getName())) {
+                        //System.out.println("SHTMLEditorPane applyTag element is in selection");
+                        writer.writeStartTag(tag.toString(), child.getAttributes());
+                        writer.writeChildElements(child);
+                        writer.writeEndTag(tag.toString());
+                        if (index < 0) {
+                            index = i;
+                        }
+                        if (replaceStart < 0 || replaceStart > elementStart) {
+                            replaceStart = elementStart;
+                        }
+                        if (replaceEnd < 0 || replaceEnd < elementEnd) {
+                            replaceEnd = elementEnd;
+                        }
+                    }
+                    else {
+                        writer.write(child);
+                    }
+                }
+            }
+            //System.out.println("SHTMLEditorPane applyTag remove index=" + index + ", removeCount=" + removeCount);
+            if (index > -1) {
+                doc.insertAfterEnd(parentOfparagraphElement.getElement(index), stringWriter.getBuffer().toString());
+                doc.removeElements(parentOfparagraphElement, index, elementsToRemoveCount);
+            }
+            //SHTMLEditorKit kit = (SHTMLEditorKit) getEditorKit();
+            //System.out.println("SHTMLEditorPane applyTag new HTML=\r\n" + sw.getBuffer().toString() );
+            //kit.read(new StringReader(sw.getBuffer().toString()), doc, getCaretPosition());
+        }
+        catch (final Exception e) {
+            Util.errMsg(this, e.getMessage(), e);
+        }
+        finally {
+            doc.endCompoundEdit();
+        }
+    }
+
+    /* ------ end of font/paragraph manipulation --------------- */
+    /* ---------- class fields start -------------- */
+    static Action toggleBulletListAction = null;
+    static Action toggleNumberListAction = null;
+
+    private void performToggleListAction(final ActionEvent e, final String elemName) {
+        if (elemName.equalsIgnoreCase(HTML.Tag.UL.toString())) {
+            if (toggleBulletListAction == null) {
+                final Component c = (Component) e.getSource();
+                final SHTMLPanelImpl panel = SHTMLPanelImpl.getOwnerSHTMLPanel(c);
+                toggleBulletListAction = panel.dynRes.getAction(SHTMLPanelImpl.toggleBulletsAction);
+            }
+            toggleBulletListAction.actionPerformed(e);
+        }
+        else if (elemName.equalsIgnoreCase(HTML.Tag.OL.toString())) {
+            if (toggleNumberListAction == null) {
+                final Component c = (Component) e.getSource();
+                final SHTMLPanelImpl panel = SHTMLPanelImpl.getOwnerSHTMLPanel(c);
+                toggleNumberListAction = panel.dynRes.getAction(SHTMLPanelImpl.toggleNumbersAction);
+            }
+            toggleNumberListAction.actionPerformed(e);
+        }
+    }
+
+    public static final String newListItemAction = "newListItem";
+    public static final String insertLineBreakAction = "insertLineBreak";
+    public static final String deletePrevCharAction = "deletePrevChar";
+    public static final String deleteNextCharAction = "deleteNextChar";
+    public static final String moveUpAction = "moveUp";
+    public static final String homeAction = "home";
+    public static final String shiftHomeAction = "shiftHome";
+    public static final String shiftEndAction = "shiftEnd";
+    public static final String endAction = "end";
+    public static final String moveDownAction = "moveDown";
+    /** a data flavor for transferables processed by this component */
+    private final DataFlavor htmlTextDataFlavor = new DataFlavor(com.lightdev.app.shtm.HTMLText.class, "HTMLText");
+
+    /* Cursors for mouseovers in the editor */
+    void updateInputAttributes() {
+        ((SHTMLEditorKit) getEditorKit()).updateInputAttributes(this);
+        fireCaretUpdate(new CaretEvent(this) {
+            public int getDot() {
+                return getSelectionStart();
+            }
+
+            public int getMark() {
+                return getSelectionEnd();
+            }
+        });
+    }
+
+    public JPopupMenu getPopup() {
+        return popup;
+    }
+
+    public void setPopup(final JPopupMenu popup) {
+        this.popup = popup;
+    }
+
+    /** Determines whether the caret is currently within a table cell. */
+    private boolean caretWithinTableCell() {
+        final Element tableCell = getCurrentTableCell();
+        return tableCell != null;
+    }
+
+    /** Returns the string HTML representation of the element. */
+    public String elementToHTML(final Element element) {
+        final HTMLDocument document = (HTMLDocument) getDocument();
+        final StringWriter stringWriter = new StringWriter();
+        final SHTMLWriter shtmlWriter = new SHTMLWriter(stringWriter, document);
+        try {
+            shtmlWriter.write(element);
+        }
+        catch (final Exception ex) {
+        }
+        return stringWriter.getBuffer().toString();
+    }
+
+    /** Determines whether an element is an empty paragraph. */
+    private boolean elementIsEmptyParagraph(final Element element) {
+        final String elementContent = elementToHTML(element);
+        return elementContent.matches("(?ims)\\s*<p[^>]*>\\s*</p>\\s*");
+    }
+
+    private void performDefaultKeyStrokeAction(final int keyCode, final int modifiers, final ActionEvent event) {
+        final KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, modifiers);
+        final Object key = getInputMap().getParent().get(keyStroke);
+        if (key != null) {
+            getActionMap().getParent().get(key).actionPerformed(event);
+        }
+    }
+
+    /** Performs the default key stroke action, assuming that the caret is within
+     * a table cell and that the action is a cursor move; if the cursor leaves
+     * the current table cell, undoes the action.
+     * Returns true if the cursor stayed within the table cell. */
+    public boolean tryDefaultKeyStrokeActionWithinCell(final int keyCode, final int modifiers, final ActionEvent event) {
+        final int originalCaretPosition = getCaretPosition();
+        final Element cellElement = getCurrentTableCell();
+        performDefaultKeyStrokeAction(keyCode, modifiers, event);
+        final Element cellElementAfter = getCurrentTableCell();
+        if (cellElement == cellElementAfter) {
+            return true;
+        }
+        setCaretPosition(originalCaretPosition);
+        return false;
+    }
+    /* (non-Javadoc)
+     * @see javax.swing.JComponent#getTransferHandler()
+     */
+    /* ---------- class fields end -------------- */
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLHelpBroker.java b/src/com/lightdev/app/shtm/SHTMLHelpBroker.java
new file mode 100644
index 0000000..6dfb719
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLHelpBroker.java
@@ -0,0 +1,80 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Created on 16.12.2006
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.event.KeyEvent;
+import java.net.URL;
+
+import javax.help.CSH;
+import javax.help.HelpBroker;
+import javax.help.HelpSet;
+import javax.help.HelpSetException;
+import javax.swing.AbstractButton;
+import javax.swing.JButton;
+import javax.swing.JMenuItem;
+import javax.swing.KeyStroke;
+
+class SHTMLHelpBroker {
+    public static final String APP_HELP_NAME = "help";
+    public static final String JAVA_HELP_EXT = ".hs";
+
+    private SHTMLHelpBroker() {
+    }
+
+    /** our help broker */
+    private static HelpBroker helpBroker;
+
+    /**
+     * get the <code>HelpBroker</code> of our application
+     *
+     * @return the <code>HelpBroker</code> to be used for help display
+     */
+    private static HelpBroker getHelpBroker() {
+        if (helpBroker == null) {
+            final URL url = SHTMLPanelImpl.class.getResource(APP_HELP_NAME + Util.URL_SEPARATOR + APP_HELP_NAME
+                    + JAVA_HELP_EXT);
+            HelpSet hs;
+            try {
+                hs = new HelpSet(null, url);
+            }
+            catch (final HelpSetException e) {
+                return null;
+            }
+            helpBroker = hs.createHelpBroker();
+        }
+        return helpBroker;
+    }
+
+    static AbstractButton createHelpButton(final String helpTopicId) {
+        AbstractButton newButton;
+        newButton = new JButton();
+        CSH.setHelpIDString(newButton, helpTopicId);
+        newButton.addActionListener(new CSH.DisplayHelpFromSource(SHTMLHelpBroker.getHelpBroker()));
+        return newButton;
+    }
+
+    static void initJavaHelpItem(final JMenuItem mi, final String helpTopicId) {
+        CSH.setHelpIDString(mi, helpTopicId);
+        mi.addActionListener(new CSH.DisplayHelpFromSource(SHTMLHelpBroker.getHelpBroker()));
+        mi.setIcon(DynamicResource.getIconForCommand(SHTMLPanelImpl.getResources(), SHTMLPanelImpl.helpTopicsAction));
+        mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
+        mi.setEnabled(true);
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLMenuBar.java b/src/com/lightdev/app/shtm/SHTMLMenuBar.java
new file mode 100644
index 0000000..2a93bf3
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLMenuBar.java
@@ -0,0 +1,56 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.event.KeyEvent;
+
+import javax.swing.JComponent;
+import javax.swing.JMenuBar;
+import javax.swing.KeyStroke;
+
+/**
+ * A menu bar for handling of key events coming from its parent SHTMLPanelImpl
+ *
+ * @author Dimitri Polivaev
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class SHTMLMenuBar extends JMenuBar {
+    /* (non-Javadoc)
+     * @see javax.swing.JMenuBar#processKeyBinding(javax.swing.KeyStroke, java.awt.event.KeyEvent, int, boolean)
+     */
+    public boolean handleKeyBinding(final KeyStroke ks, final KeyEvent e, final int condition, final boolean pressed) {
+        if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
+            return super.processKeyBinding(ks, e, JComponent.WHEN_IN_FOCUSED_WINDOW, pressed);
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.JMenuBar#processKeyBinding(javax.swing.KeyStroke, java.awt.event.KeyEvent, int, boolean)
+     */
+    public boolean processKeyBinding(final KeyStroke ks, final KeyEvent e, final int condition, final boolean pressed) {
+        return false;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLPanel.java b/src/com/lightdev/app/shtm/SHTMLPanel.java
new file mode 100644
index 0000000..bb4da83
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLPanel.java
@@ -0,0 +1,113 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Created on 10.09.2006
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Dimension;
+import java.awt.LayoutManager;
+import java.awt.event.ActionListener;
+
+import javax.swing.Action;
+import javax.swing.JEditorPane;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.text.html.HTMLDocument;
+
+/**
+ * Class for using SimplyHTML as as component  
+ * 
+ * @author Dimitri Polivaev
+ * 14.01.2007
+ */
+public abstract class SHTMLPanel extends JPanel implements SHTMLPrefsChangeListener {
+    SHTMLPanel(final LayoutManager layout) {
+        super(layout);
+    }
+    
+    public void shtmlPrefChanged(String propertyName, String newValue, String oldValue)
+    {
+    	//System.out.format("SHTMLPanel.shtmlPrefChanged(%s, %s, %s)\n",
+    	// propertyName, newValue, oldValue);
+    	if (propertyName.equals("default_paste_mode"))
+    	{
+    		((SHTMLEditorKitActions.SHTMLEditPasteOtherAction)getAction("pasteOther"))
+    		.updateActionName(SHTMLEditorPane.PasteMode.valueOf(newValue).invert());
+    	}
+    }
+
+    public static SHTMLPanel createSHTMLPanel() {
+        return new SHTMLPanelSingleDocImpl();
+    }
+
+    public abstract String getDocumentText();
+
+    public abstract boolean needsSaving();
+
+    public abstract void setContentPanePreferredSize(Dimension dimension);
+
+    public abstract void setCurrentDocumentContent(String sText);
+
+    public static void setResources(final TextResources resources) {
+        SHTMLPanelImpl.setTextResources(resources);
+    }
+    
+    public static void setActionBuilder(final ActionBuilder ab){
+    	SHTMLPanelImpl.setActionBuilder(ab);
+    }
+
+    public abstract HTMLDocument getDocument();
+
+    public abstract JEditorPane getEditorPane();
+
+    public abstract JEditorPane getSourceEditorPane();
+
+    public static TextResources getResources() {
+        return SHTMLPanelImpl.getResources();
+    }
+
+    abstract public int getCaretPosition();
+
+    public abstract JMenuBar getMenuBar();
+
+    public abstract JEditorPane getMostRecentFocusOwner();
+
+    public abstract Action getAction(String actionName);
+    public abstract void addAction(String text, Action action);
+
+    /**
+     * Returns a new menu item for a named action of SimplyHTML. (Can be used for building custom
+     * popup menu, or for invoking the action externally in another way.)
+     */
+    public abstract JMenuItem newActionMenuItem(String actionName);
+
+    /**
+     * Switches between the rich text view and the source view, given
+     * tabbed panes are not used. Has no corresponding action; calling
+     * this method is up to the caller application of SimplyHTML.
+     */
+    public abstract void switchViews();
+
+    /**
+     * Sets the handler for the Open Hyperlink action. SimplyHTML itself has
+     * no ability to open hyperlinks, so it forwards the action to the caller
+     * application.
+     */
+    public abstract void setOpenHyperlinkHandler(ActionListener openHyperlinkHandler);
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLPanelImpl.java b/src/com/lightdev/app/shtm/SHTMLPanelImpl.java
new file mode 100644
index 0000000..6647945
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLPanelImpl.java
@@ -0,0 +1,1496 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2006 Ulrich Hilger, Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.net.*;
+
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.text.html.*;
+import javax.swing.undo.*;
+import java.util.*;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeEvent;
+
+import com.lightdev.app.shtm.SHTMLEditorKitActions.SetStyleAction;
+import com.lightdev.app.shtm.SHTMLEditorKitActions.SetTagAction;
+import java.util.prefs.*;
+
+/**
+ * Main component of application SimplyHTML.
+ *
+ * <p>This class constructs the main panel and all of its GUI elements
+ * such as menus, etc.</p>
+ *
+ * <p>It defines a set of inner classes creating actions which can be
+ * connected to menus, buttons or instantiated individually.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Dimitri Polivaev
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ *
+ */
+public class SHTMLPanelImpl extends SHTMLPanel implements CaretListener {
+    //private int renderMode = SHTMLEditorKit.RENDER_MODE_JAVA;
+    /* some public constants */
+    public static final String APP_TEMP_DIR = "temp";
+    public static final String IMAGE_DIR = "images";
+    public static final String ACTION_SELECTED_KEY = "selected";
+    public static final String ACTION_SELECTED = "true";
+    public static final String ACTION_UNSELECTED = "false";
+    public static final String FILE_LAST_OPEN = "lastOpenFileName";
+    public static final String FILE_LAST_SAVE = "lastSaveFileName";
+    /** single instance of a dynamic resource for use by all */
+    public DynamicResource dynRes = new DynamicResource();
+    /** SimplyHTML's main resource bundle (plug-ins use their own) */
+    private static TextResources textResources = null;
+
+    public static TextResources getResources() {
+        if (textResources == null) {
+            textResources = SHTMLPanelImpl.readDefaultResources();
+        }
+        return textResources;
+    }
+
+    /** the plug-in manager of SimplyHTML */
+    public static PluginManager pluginManager; // = new PluginManager(mainFrame);
+    protected ActionListener openHyperlinkHandler = null;
+
+    public static void setTextResources(final TextResources textResources) {
+        if (SHTMLPanelImpl.textResources != null) {
+            return;
+        }
+        SHTMLPanelImpl.textResources = textResources != null ? textResources : SHTMLPanelImpl.readDefaultResources();
+    }
+
+    private static TextResources readDefaultResources() {
+        try {
+            final String propsLoc = "com/lightdev/app/shtm/resources/SimplyHTML_common.properties";
+            final URL defaultPropsURL = ClassLoader.getSystemResource(propsLoc);
+            final Properties props = new Properties();
+            InputStream in = null;
+            in = defaultPropsURL.openStream();
+            props.load(in);
+            in.close();
+            final ResourceBundle resourceBundle = ResourceBundle.getBundle(
+                "com.lightdev.app.shtm.resources.SimplyHTML", Locale.getDefault());
+            return new DefaultTextResources(resourceBundle, props);
+        }
+        catch (final Exception ex) {
+            Util.errMsg(null, "resources not found", ex);
+            return null;
+        }
+    }
+
+    private final SHTMLMenuBar menuBar;
+    /** currently active DocumentPane */
+    private DocumentPane documentPane;
+    /** currently active SHTMLEditorPane */
+    private SHTMLEditorPane editorPane;
+    /** currently active SHTMLDocument */
+    protected SHTMLDocument doc;
+    /** tool bar for formatting commands */
+    private JToolBar formatToolBar;
+    /** tool bar for formatting commands */
+    private JToolBar paraToolBar;
+    /** plugin menu ID */
+    public final String pluginMenuId = "plugin";
+    /** help menu ID */
+    public final String helpMenuId = "help";
+    /** id in TextResources for a relative path to an empty menu icon */
+    private final String emptyIcon = "emptyIcon";
+    /** watch for repeated key events */
+    private final RepeatKeyWatcher rkw = new RepeatKeyWatcher(40);
+    /** counter for newly created documents */
+    int newDocCounter = 0;
+    /** reference to applicatin temp directory */
+    private static File appTempDir;
+	private static ActionBuilder actionBuilder;
+    /** tool bar selector for certain tags */
+    private TagSelector tagSelector;
+    /** panel for plug-in display */
+    SplitPanel splitPanel;
+    /** indicates, whether document activation shall be handled */
+    boolean ignoreActivateDoc = false;
+    private final JPopupMenu editorPopup;
+    /**
+     * action names
+     *
+     * these have to correspond with the keys in the
+     * resource bundle to allow for dynamic
+     * menu creation and control
+     */
+    public static final String exitAction = "exit";
+    public static final String undoAction = "undo";
+    public static final String redoAction = "redo";
+    public static final String cutAction = "cut";
+    public static final String copyAction = "copy";
+    public static final String pasteAction = "paste";
+    public static final String pasteOtherAction ="pasteOther";
+    public static final String selectAllAction = "selectAll";
+    public static final String clearFormatAction = "clearFormat";
+    public static final String fontAction = "font";
+    public static final String fontFamilyAction = "fontFamily";
+    public static final String fontSizeAction = "fontSize";
+    public static final String fontBoldAction = "fontBold";
+    public static final String fontStrikethroughAction = "fontStrikethrough";
+    public static final String fontItalicAction = "fontItalic";
+    public static final String fontUnderlineAction = "fontUnderline";
+    public static final String fontColorAction = "fontColor";
+    public static final String helpTopicsAction = "helpTopics";
+    public static final String aboutAction = "about";
+    public static final String gcAction = "gc";
+    public static final String elemTreeAction = "elemTree";
+    public static final String testAction = "test";
+    public static final String insertTableAction = "insertTable";
+    public static final String formatTableAction = "formatTable";
+    public static final String toggleTableHeaderCellAction = "toggleTableHeaderCell";
+    public static final String insertTableColAction = "insertTableCol";
+    public static final String insertTableRowAction = "insertTableRow";
+    public static final String insertTableRowHeaderAction = "insertTableRowHeader";
+    public static final String appendTableRowAction = "appendTableRow";
+    public static final String appendTableColAction = "appendTableCol";
+    public static final String deleteTableRowAction = "deleteTableRow";
+    public static final String deleteTableColAction = "deleteTableCol";
+    public static final String nextTableCellAction = "nextTableCell";
+    public static final String prevTableCellAction = "prevTableCell";
+    public static final String moveTableRowUpAction = "moveTableRowUp";
+    public static final String moveTableColumnLeftAction = "moveTableColumnLeft";
+    public static final String moveTableColumnRightAction = "moveTableColumnRight";
+    public static final String moveTableRowDownAction = "moveTableRowDown";
+    //public static final String nextCellAction = "nextCell";
+    //public static final String prevCellAction = "prevCell";
+    public static final String toggleBulletsAction = "toggleBullets";
+    public static final String toggleNumbersAction = "toggleNumbers";
+    public static final String formatListAction = "formatList";
+    public static final String editPrefsAction = "editPrefs";
+    public static final String insertImageAction = "insertImage";
+    public static final String formatImageAction = "formatImage";
+    public static final String formatParaAction = "formatPara";
+    public static final String editNamedStyleAction = "editNamedStyle";
+    public static final String paraAlignLeftAction = "paraAlignLeft";
+    public static final String paraAlignCenterAction = "paraAlignCenter";
+    public static final String paraAlignRightAction = "paraAlignRight";
+    public static final String insertLinkAction = "insertLink";
+    public static final String editLinkAction = "editLink";
+    public static final String openLinkAction = "openLink";
+    public static final String setTagAction = "setTag";
+    public static final String editAnchorsAction = "editAnchors";
+    public static final String saveAllAction = "saveAll";
+    public static final String documentTitleAction = "documentTitle";
+    public static final String setDefaultStyleRefAction = "setDefaultStyleRef";
+    public static final String findReplaceAction = "findReplace";
+    public static final String setStyleAction = "setStyle";
+    public static final String formatAsCodeAction = "formatAsCode";
+    public static final String printAction = "print";
+
+    public static SHTMLPanelImpl getOwnerSHTMLPanel(Component c) {
+        for (;;) {
+            if (c == null) {
+                return null;
+            }
+            if (c instanceof SHTMLPanelImpl) {
+                return (SHTMLPanelImpl) c;
+            }
+            c = c.getParent();
+        }
+    }
+
+    /** construct a new main application frame */
+    SHTMLPanelImpl() {
+        super(new BorderLayout());
+        SplashScreen.showInstance();
+        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
+        initActions();
+        if(actionBuilder != null)
+        	actionBuilder.initActions(this);
+        menuBar = dynRes.createMenubar(textResources, "menubar");
+        editorPopup = dynRes.createPopupMenu(textResources, "popup");
+        setJMenuBar(menuBar);
+        customizeFrame();
+        initAppTempDir();
+        initPlugins();
+        initDocumentPane();
+        updateActions();
+        initJavaHelp();
+        SplashScreen.hideInstance();
+    }
+
+    private void setJMenuBar(final JMenuBar bar) {
+        add(bar, BorderLayout.NORTH);
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.JComponent#processKeyBinding(javax.swing.KeyStroke, java.awt.event.KeyEvent, int, boolean)
+     */
+    protected boolean processKeyBinding(final KeyStroke ks, final KeyEvent e, final int condition, final boolean pressed) {
+        if (super.processKeyBinding(ks, e, condition, pressed)) {
+            return true;
+        }
+        return menuBar.handleKeyBinding(ks, e, condition, pressed);
+    }
+
+    public JMenuItem newActionMenuItem(final String actionName) {
+        return dynRes.createMenuItem(SHTMLPanelImpl.getResources(), actionName);
+    }
+
+    public Action getAction(final String actionName) {
+        return dynRes.getAction(actionName);
+    }
+
+    /**
+       * get the DynamicResource used in this instance of FrmMain
+       *
+       * @return the DynamicResource
+       */
+    DynamicResource getDynRes() {
+        return dynRes;
+    }
+
+    /**
+     * get the temporary directory of SimplyHTML
+     *
+     * @return the temp dir
+     */
+    static File getAppTempDir() {
+        return appTempDir;
+    }
+
+    /**
+     * get the file object for the document shown in the currently open DocumentPane
+     *
+     * @return the document file
+     */
+    File getCurrentFile() {
+        File file = null;
+        final URL url = getDocumentPane().getSource();
+        if (url != null) {
+            file = new File(url.getFile());
+        }
+        return file;
+    }
+
+    /**
+     * get the name of the file for the document shown in the currently open DocumentPane
+     *
+     * @return the document name
+     */
+    String getCurrentDocName() {
+        return getDocumentPane().getDocumentName();
+    }
+
+    /**
+     * Convenience method for obtaining the document text
+     * @return returns the document text as string.
+     */
+    public String getDocumentText() {
+        return getDocumentPane().getDocumentText();
+    }
+
+    Document getCurrentDocument() {
+        return getDocumentPane().getDocument();
+    }
+
+    /**
+     * indicates whether or not the document needs to be saved.
+     *
+     * @return  true, if changes need to be saved
+     */
+    public boolean needsSaving() {
+        return getDocumentPane().needsSaving();
+    }
+
+    /**
+     * Convenience method for clearing out the UndoManager
+     */
+    void purgeUndos() {
+        if (undo != null) {
+            undo.discardAllEdits();
+            dynRes.getAction(undoAction).putValue("enabled", Boolean.FALSE);
+            dynRes.getAction(redoAction).putValue("enabled", Boolean.FALSE);
+            updateFormatControls();
+        }
+    }
+
+    /**
+     * Convenience method for setting the document text
+     */
+    public void setCurrentDocumentContent(final String sText) {
+        getDocumentPane().setDocumentText(sText);
+        purgeUndos();
+    }
+
+    public void setContentPanePreferredSize(final Dimension prefSize) {
+        getDocumentPane().setContentPanePreferredSize(prefSize);
+    }
+
+    /**
+     * @return returns the currently used ExtendedHTMLDocument Object
+     */
+    public HTMLDocument getDocument() {
+        return doc;
+    }
+
+    /**
+     * get the DocumentPane object that is currently active
+     *
+     * @return the active DocumentPane
+     */
+    DocumentPane getCurrentDocumentPane() {
+        return getDocumentPane();
+    }
+
+    /**
+     * add a DocumentPaneListener from the currently active DocumentPane (if any)
+     */
+    void addDocumentPaneListener(final DocumentPane.DocumentPaneListener listener) {
+        if (getDocumentPane() != null) {
+            //System.out.println("FrmMain.addDocumentPaneListener documentPane.source=" + documentPane.getSource());
+            getDocumentPane().addDocumentPaneListener(listener);
+        }
+        else {
+            //System.out.println("FrmMain.addDocumentPaneListener documentPane is null, did not add");
+        }
+    }
+
+    /**
+     * remove a DocumentPaneListener from the currently active DocumentPane (if any)
+     */
+    void removeDocumentPaneListener(final DocumentPane.DocumentPaneListener listener) {
+        if (getDocumentPane() != null) {
+            getDocumentPane().removeDocumentPaneListener(listener);
+        }
+    }
+
+    /**
+     * initialize SimplyHTML's temporary directory
+     */
+    private void initAppTempDir() {
+        appTempDir = new File(System.getProperty("user.home") + File.separator + "." + FrmMain.APP_NAME.toLowerCase()
+                + File.separator + APP_TEMP_DIR + File.separator);
+    }
+
+    /**
+     * find plug-ins and load them accordingly,
+     * i.e. display / dock components and add
+     * plug-in menus.
+     */
+    void initPlugins() {
+        pluginManager = new PluginManager(this);
+        final JMenu pMenu = dynRes.getMenu(pluginMenuId);
+        final JMenu hMenu;
+        if (pMenu != null) {
+            final Container contentPane = SHTMLPanelImpl.this;
+            pluginManager.loadPlugins();
+            final Enumeration plugins = pluginManager.plugins();
+            SHTMLPlugin pi;
+            final JComponent pc;
+            final JMenuItem pluginMenu;
+            final JMenuItem helpMenu;
+            while (plugins.hasMoreElements()) {
+                pi = (SHTMLPlugin) plugins.nextElement();
+                if (pi.isActive()) {
+                    refreshPluginDisplay(pi);
+                }
+            }
+        }
+        adjustDividers();
+    }
+
+    /**
+     * adjust the divider sizes of SimplyHTML's SplitPanel
+     * according to visibility
+     */
+    public void adjustDividers() {
+        splitPanel.adjustDividerSizes();
+    }
+
+    /**
+     * watch for key events that are automatically repeated
+     * due to the user holding down a key.
+     *
+     * <p>When a key is held down by the user, every keyPressed
+     * event is followed by a keyTyped event and a keyReleased
+     * event although the key is actually still down. I.e. it
+     * can not be determined by a keyReleased event if a key
+     * actually is released, which is why this implementation
+     * is necessary.</p>
+     */
+    class RepeatKeyWatcher implements KeyListener {
+        /** timer for handling keyReleased events */
+        private final java.util.Timer releaseTimer = new java.util.Timer();
+        /** the next scheduled task for a keyReleased event */
+        private ReleaseTask nextTask;
+        /** time of the last keyPressed event */
+        private long lastWhen = 0;
+        /** time of the current KeyEvent */
+        private long when;
+        /** delay to distinguish between single and repeated events */
+        private final long delay;
+        /** indicates whether or not a KeyEvent currently occurs repeatedly */
+        private boolean repeating = false;
+
+        /**
+         * construct a <code>RepeatKeyWatcher</code>
+         *
+         * @param delay  the delay in milliseconds until a
+         * keyReleased event should be handled
+         */
+        RepeatKeyWatcher(final long delay) {
+            super();
+            this.delay = delay;
+        }
+
+        /**
+         * handle a keyPressed event by cancelling the previous
+         * release task (if any) and indicating repeated key press
+         * as applicable.
+         */
+        public void keyPressed(final KeyEvent e) {
+            if (nextTask != null) {
+                nextTask.cancel();
+            }
+            when = e.getWhen();
+            if ((when - lastWhen) <= delay) {
+                repeating = true;
+            }
+            else {
+                repeating = false;
+            }
+            lastWhen = when;
+        }
+
+        /**
+         * handle a keyReleased event by scheduling a
+         * <code>ReleaseTask</code>.
+         */
+        public void keyReleased(final KeyEvent e) {
+            nextTask = new ReleaseTask();
+            releaseTimer.schedule(nextTask, delay);
+        }
+
+        public void keyTyped(final KeyEvent e) {
+        }
+
+        /**
+         * indicate whether or not a key is being held down
+         *
+         * @return true if a key is being held down, false if not
+         */
+        boolean isRepeating() {
+            return repeating;
+        }
+
+        /**
+         * Task to be executed when a key is released
+         */
+        private class ReleaseTask extends TimerTask implements Runnable {
+            public void run() {
+                if (EventQueue.isDispatchThread()) {
+                    repeating = false;
+                    updateFormatControls();
+                }
+                else {
+                    try {
+                        EventQueue.invokeAndWait(this);
+                    }
+                    catch (final InterruptedException e) {
+                    }
+                    catch (final InvocationTargetException e) {
+                    }
+                }
+            }
+        }
+    }
+
+    public void clearDockPanels() {
+        splitPanel.removeAllOuterPanels();
+    }
+
+    /**
+     * refresh the display for a given plug-in
+     *
+     * @param pi  the plug-in to refresh
+     */
+    public void refreshPluginDisplay(final SHTMLPlugin pi) {
+        final JMenu pMenu = dynRes.getMenu(pluginMenuId);
+        final JMenu hMenu = dynRes.getMenu(helpMenuId);
+        final JMenuItem pluginMenu = pi.getPluginMenu();
+        final JMenuItem helpMenu = pi.getHelpMenu();
+        JTabbedPane p = null;
+        final Preferences prefs;
+        if (pi.isActive()) {
+            final JComponent pc = pi.getComponent();
+            if (pc != null) {
+                int panelNo = SplitPanel.WEST;
+                double loc = 0.3;
+                switch (pi.getDockLocation()) {
+                    case SHTMLPlugin.DOCK_LOCATION_LEFT:
+                        break;
+                    case SHTMLPlugin.DOCK_LOCATION_RIGHT:
+                        panelNo = SplitPanel.EAST;
+                        loc = 0.7;
+                        break;
+                    case SHTMLPlugin.DOCK_LOCATION_BOTTOM:
+                        panelNo = SplitPanel.SOUTH;
+                        loc = 0.7;
+                        break;
+                    case SHTMLPlugin.DOCK_LOCATION_TOP:
+                        panelNo = SplitPanel.NORTH;
+                        break;
+                }
+                p = (JTabbedPane) splitPanel.getPanel(panelNo);
+                p.setVisible(true);
+                p.add(pi.getGUIName(), pc);
+                if (((panelNo == SplitPanel.WEST) && splitPanel.getDivLoc(panelNo) < this.getWidth() / 10)
+                        || ((panelNo == SplitPanel.NORTH) && splitPanel.getDivLoc(panelNo) < this.getHeight() / 10)
+                        || ((panelNo == SplitPanel.EAST) && splitPanel.getDivLoc(panelNo) > this.getWidth()
+                                - (this.getWidth() / 10))
+                        || ((panelNo == SplitPanel.SOUTH) && splitPanel.getDivLoc(panelNo) > this.getHeight()
+                                - (this.getHeight() / 10))) {
+                    splitPanel.setDivLoc(panelNo, loc);
+                }
+            }
+            if (pluginMenu != null) {
+                Icon menuIcon = pluginMenu.getIcon();
+                if (menuIcon == null) {
+                    final URL url = DynamicResource.getResource(textResources, emptyIcon);
+                    if (url != null) {
+                        menuIcon = new ImageIcon(url);
+                        pluginMenu.setIcon(new ImageIcon(url));
+                    }
+                }
+                pMenu.add(pluginMenu);
+            }
+            if (helpMenu != null) {
+                //System.out.println("FrmMain.refreshPluginDisplay insert helpMenu");
+                if (helpMenu.getSubElements().length > 0) {
+                    Icon menuIcon = helpMenu.getIcon();
+                    if (menuIcon == null) {
+                        final URL url = DynamicResource.getResource(textResources, emptyIcon);
+                        if (url != null) {
+                            menuIcon = new ImageIcon(url);
+                            helpMenu.setIcon(new ImageIcon(url));
+                        }
+                    }
+                }
+                hMenu.insert(helpMenu, hMenu.getItemCount() - 2);
+            }
+            SwingUtilities.invokeLater(new PluginInfo(pi));
+        }
+        else {
+            if (pluginMenu != null) {
+                pMenu.remove(pluginMenu);
+            }
+            if (helpMenu != null) {
+                hMenu.remove(helpMenu);
+            }
+        }
+    }
+
+    class PluginInfo implements Runnable {
+        SHTMLPlugin pi;
+
+        PluginInfo(final SHTMLPlugin pi) {
+            this.pi = pi;
+        }
+
+        public void run() {
+            pi.showInitialInfo();
+        }
+    }
+
+    /**
+     * get a <code>HelpBroker</code> for our application,
+     * store it for later use and connect it to the help menu.
+     */
+    private void initJavaHelp() {
+        try {
+            final JMenuItem mi = dynRes.getMenuItem(helpTopicsAction);
+            if (mi == null) {
+                return;
+            }
+            SHTMLHelpBroker.initJavaHelpItem(mi, "item15");
+        }
+        catch (final Throwable e) {
+            System.err.println("Simply HTML : Warning : loading help failed.");
+            // --Dan
+            //Util.errMsg(this,
+            //            Util.getResourceString("helpNotFoundError"),
+            //            e);
+        }
+    }
+
+    protected void initDocumentPane() {
+        //TODO
+    }
+
+    /**
+    * instantiate Actions and put them into the commands
+    * Hashtable for later use along with their action commands.
+    *
+    * This is hard coded as Actions need to be instantiated
+    * hard coded anyway, so we do the storage in <code>commands</code>
+    * right away.
+    */
+    protected void initActions() {
+        addAction(setDefaultStyleRefAction, new SHTMLEditorKitActions.SetDefaultStyleRefAction(this));
+        addAction(documentTitleAction, new SHTMLEditorKitActions.DocumentTitleAction(this));
+        addAction(editAnchorsAction, new SHTMLEditorKitActions.EditAnchorsAction(this));
+        addAction(setTagAction, new SHTMLEditorKitActions.SetTagAction(this));
+        addAction(formatAsCodeAction, new SHTMLEditorKitActions.SetTagAction(this, "code"));
+        addAction(editLinkAction, new SHTMLEditorKitActions.EditLinkAction(this));
+        addAction(openLinkAction, new SHTMLEditorKitActions.OpenLinkAction(this));
+        addAction(prevTableCellAction, new SHTMLEditorKitActions.PrevTableCellAction(this));
+        addAction(nextTableCellAction, new SHTMLEditorKitActions.NextTableCellAction(this));
+        addAction(editNamedStyleAction, new SHTMLEditorKitActions.EditNamedStyleAction(this));
+        addAction(clearFormatAction, new SHTMLEditorKitActions.ClearFormatAction(this));
+        addAction(formatParaAction, new SHTMLEditorKitActions.FormatParaAction(this));
+        addAction(formatImageAction, new SHTMLEditorKitActions.FormatImageAction(this));
+        addAction(insertImageAction, new SHTMLEditorKitActions.InsertImageAction(this));
+        addAction(editPrefsAction, new SHTMLEditorKitActions.SHTMLEditPrefsAction(this));
+        addAction(toggleBulletsAction, new SHTMLEditorKitActions.ToggleListAction(this, toggleBulletsAction,
+            HTML.Tag.UL));
+        addAction(toggleNumbersAction, new SHTMLEditorKitActions.ToggleListAction(this, toggleNumbersAction,
+            HTML.Tag.OL));
+        addAction(formatListAction, new SHTMLEditorKitActions.FormatListAction(this));
+        addAction(ManagePluginsAction.managePluginsAction, new ManagePluginsAction());
+        addAction(elemTreeAction, new SHTMLEditorKitActions.ShowElementTreeAction(this));
+        addAction(gcAction, new SHTMLEditorKitActions.GarbageCollectionAction(this));
+        addAction(undoAction, new SHTMLEditorKitActions.UndoAction(this));
+        addAction(redoAction, new SHTMLEditorKitActions.RedoAction(this));
+        addAction(cutAction, new SHTMLEditorKitActions.SHTMLEditCutAction(this));
+        addAction(copyAction, new SHTMLEditorKitActions.SHTMLEditCopyAction(this));
+        addAction(pasteAction, new SHTMLEditorKitActions.SHTMLEditPasteAction(this));
+        addAction(pasteOtherAction, new SHTMLEditorKitActions.SHTMLEditPasteOtherAction(this));
+        addAction(selectAllAction, new SHTMLEditorKitActions.SHTMLEditSelectAllAction(this));
+        addAction(aboutAction, new SHTMLEditorKitActions.SHTMLHelpAppInfoAction(this));
+        addAction(fontAction, new SHTMLEditorKitActions.FontAction(this));
+        addAction(fontFamilyAction, new SHTMLEditorKitActions.FontFamilyAction(this));
+        addAction(fontSizeAction, new SHTMLEditorKitActions.FontSizeAction(this));
+        addAction(insertTableAction, new SHTMLEditorKitActions.InsertTableAction(this));
+        addAction(insertTableRowAction, new SHTMLEditorKitActions.InsertTableRowAction(this, null,
+            insertTableRowAction));
+        addAction(insertTableRowHeaderAction, new SHTMLEditorKitActions.InsertTableRowAction(this, "th",
+            insertTableRowHeaderAction));
+        addAction(insertTableColAction, new SHTMLEditorKitActions.InsertTableColAction(this));
+        addAction(appendTableColAction, new SHTMLEditorKitActions.AppendTableColAction(this));
+        addAction(appendTableRowAction, new SHTMLEditorKitActions.AppendTableRowAction(this));
+        addAction(deleteTableRowAction, new SHTMLEditorKitActions.DeleteTableRowAction(this));
+        addAction(deleteTableColAction, new SHTMLEditorKitActions.DeleteTableColAction(this));
+        addAction(moveTableRowUpAction, new SHTMLEditorKitActions.MoveTableRowUpAction(this));
+        addAction(moveTableRowDownAction, new SHTMLEditorKitActions.MoveTableRowDownAction(this));
+        addAction(moveTableColumnLeftAction, new SHTMLEditorKitActions.MoveTableColumnLeftAction(this));
+        addAction(moveTableColumnRightAction, new SHTMLEditorKitActions.MoveTableColumnRightAction(this));
+        addAction(formatTableAction, new SHTMLEditorKitActions.FormatTableAction(this));
+        addAction(toggleTableHeaderCellAction, new SHTMLEditorKitActions.ToggleTableHeaderCellAction(this));
+        addAction(fontBoldAction, new SHTMLEditorKitActions.BoldAction(this));
+        addAction(fontItalicAction, new SHTMLEditorKitActions.ItalicAction(this));
+        addAction(fontUnderlineAction, new SHTMLEditorKitActions.UnderlineAction(this));
+        addAction(fontColorAction, new SHTMLEditorKitActions.FontColorAction(this));
+        addAction(fontStrikethroughAction, new SHTMLEditorKitActions.ApplyCSSAttributeAction(this,
+            fontStrikethroughAction, CSS.Attribute.TEXT_DECORATION, "line-through", false));
+        addAction(paraAlignLeftAction, new SHTMLEditorKitActions.ApplyCSSAttributeAction(this,
+            paraAlignLeftAction, CSS.Attribute.TEXT_ALIGN, Util.CSS_ATTRIBUTE_ALIGN_LEFT, true));
+        addAction(paraAlignCenterAction, new SHTMLEditorKitActions.ApplyCSSAttributeAction(this,
+            paraAlignCenterAction, CSS.Attribute.TEXT_ALIGN, Util.CSS_ATTRIBUTE_ALIGN_CENTER, true));
+        addAction(paraAlignRightAction, new SHTMLEditorKitActions.ApplyCSSAttributeAction(this,
+            paraAlignRightAction, CSS.Attribute.TEXT_ALIGN, Util.CSS_ATTRIBUTE_ALIGN_RIGHT, true));
+        addAction(testAction, new SHTMLEditorKitActions.SHTMLTestAction(this));
+        addAction(printAction, new SHTMLEditorKitActions.PrintAction(this));
+    }
+
+    public static void setActionBuilder(final ActionBuilder ab){
+    	SHTMLPanelImpl.actionBuilder = ab;
+    }
+
+    public void addAction(String text, Action action) {
+		dynRes.addAction(text, action);
+		
+	}
+
+	/**
+     * update all actions
+     */
+    public void updateActions() {
+        Action action;
+        final Enumeration actions = dynRes.getActions();
+        while (actions.hasMoreElements()) {
+            action = (Action) actions.nextElement();
+            if (action instanceof SHTMLAction) {
+                ((SHTMLAction) action).update();
+            }
+        }
+    }
+
+    /** customize the frame to our needs */
+    protected void customizeFrame() {
+        splitPanel = new SplitPanel();
+        for (int i = 0; i < 4; i++) {
+            final JTabbedPane p = new JTabbedPane();
+            p.setVisible(false);
+            splitPanel.addComponent(p, i);
+        }
+        final JPanel toolBarPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)) {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 1L;
+
+            public Dimension getPreferredSize() {
+                final int maxWidth = splitPanel.getWidth();
+                int height = 0;
+                int rowHeight = 0;
+                int width = 0;
+                for (int i = 0; i < getComponentCount(); i++) {
+                    final Component component = getComponent(i);
+                    final Dimension compPreferredSize = component.getPreferredSize();
+                    if (maxWidth < compPreferredSize.width) {
+                        height += rowHeight + compPreferredSize.height;
+                        rowHeight = 0;
+                        width = 0;
+                    }
+                    else if (maxWidth < width + compPreferredSize.width) {
+                        height += rowHeight;
+                        rowHeight = compPreferredSize.height;
+                        width = compPreferredSize.width;
+                    }
+                    else {
+                        rowHeight = Math.max(rowHeight, compPreferredSize.height);
+                        width += compPreferredSize.width;
+                    }
+                }
+                height += rowHeight;
+                return new Dimension(maxWidth, height);
+            }
+        };
+        final Container contentPane = new JPanel() {
+            /**
+            * 
+            */
+            private static final long serialVersionUID = 1L;
+
+            public Dimension getPreferredSize() {
+                final Dimension splitPreferredSize = splitPanel.getPreferredSize();
+                final Dimension toolbaPreferredSize = toolBarPanel.getPreferredSize();
+                return new Dimension(splitPreferredSize.width, splitPreferredSize.height + toolbaPreferredSize.height);
+            }
+        };
+        contentPane.setLayout(new BorderLayout());
+        toolBarPanel.add(createToolBar("toolBar"));
+        formatToolBar = createToolBar("formatToolBar");
+        paraToolBar = createToolBar("paraToolBar");
+        toolBarPanel.add(formatToolBar);
+        toolBarPanel.add(paraToolBar);
+        if (Util.getPreference("show_toolbars", "true").equalsIgnoreCase("true")) {
+            contentPane.add(toolBarPanel, BorderLayout.NORTH);
+        }
+        //contentPane.add(workPanel, BorderLayout.CENTER);
+        contentPane.add(splitPanel, BorderLayout.CENTER);
+        //contentPane.add(workPanel);
+        add(contentPane, BorderLayout.CENTER);
+        splitPanel.addComponentListener(new ComponentListener() {
+            public void componentHidden(final ComponentEvent e) {
+            }
+
+            public void componentMoved(final ComponentEvent e) {
+            }
+
+            public void componentResized(final ComponentEvent e) {
+                resizeToolbarPane(toolBarPanel);
+            }
+
+            public void componentShown(final ComponentEvent e) {
+            }
+        });
+        toolBarPanel.addContainerListener(new ContainerListener() {
+            public void componentAdded(final ContainerEvent e) {
+                resizeToolbarPane(toolBarPanel);
+            }
+
+            public void componentRemoved(final ContainerEvent e) {
+                resizeToolbarPane(toolBarPanel);
+            }
+        });
+    }
+
+    private void resizeToolbarPane(final JComponent toolBarPanel) {
+        if (toolBarPanel.getPreferredSize().height != toolBarPanel.getHeight()) {
+            toolBarPanel.revalidate();
+        }
+    }
+
+    /**
+     * Create a tool bar.  This reads the definition of a tool bar
+     * from the associated resource file.
+     *
+     * @param nm  the name of the tool bar definition in the resource file
+     *
+     * @return the created tool bar
+     */
+    JToolBar createToolBar(final String nm) {
+        final String[] itemKeys = Util.tokenize(Util.getResourceString(textResources, nm), " ");
+        final JToolBar toolBar = new JToolBar();
+        toolBar.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
+        for (int i = 0; i < itemKeys.length; i++) {
+            /** special handling for separators */
+            final String itemKey = itemKeys[i];
+            createToolbarItem(toolBar, itemKey);
+        }
+        return toolBar;
+    }
+
+    protected void createToolbarItem(final JToolBar toolBar, final String itemKey) {
+        final ToggleBorderListener tbl = new ToggleBorderListener();
+        final Dimension buttonSize = new Dimension(24, 24);
+        final Dimension comboBoxSize = new Dimension(300, 24);
+        final Dimension separatorSize = new Dimension(3, 24);
+        JSeparator separator;
+        if (itemKey.equals(DynamicResource.menuSeparatorKey)) {
+            separator = new JSeparator(JSeparator.VERTICAL);
+            separator.setMaximumSize(separatorSize);
+            toolBar.add(separator);
+        }
+        /**
+         * special handling for list elements in the
+         * tool bar
+         */
+        else if (itemKey.equalsIgnoreCase(fontFamilyAction)) {
+            final FontFamilyPicker fontFamily = new FontFamilyPicker();
+            fontFamily.setPreferredSize(new Dimension(180, 23));
+            fontFamily.setAction(dynRes.getAction(fontFamilyAction));
+            fontFamily.setMaximumSize(comboBoxSize);
+            toolBar.add(fontFamily);
+        }
+        else if (itemKey.equalsIgnoreCase(fontSizeAction)) {
+            final FontSizePicker fontSize = new FontSizePicker();
+            fontSize.setPreferredSize(new Dimension(50, 23));
+            fontSize.setAction(dynRes.getAction(fontSizeAction));
+            fontSize.setMaximumSize(comboBoxSize);
+            toolBar.add(fontSize);
+        }
+        else if (itemKey.equalsIgnoreCase(setTagAction)) {
+            tagSelector = new TagSelector();
+            tagSelector.setAction(dynRes.getAction(setTagAction));
+            /*
+             styleSelector = new StyleSelector(HTML.Attribute.CLASS);
+             styleSelector.setPreferredSize(new Dimension(110, 23));
+             styleSelector.setAction(dynRes.getAction(setStyleAction));
+             styleSelector.setMaximumSize(comboBoxSize);
+             jtpDocs.addChangeListener(styleSelector);
+             */
+            toolBar.add(tagSelector);
+        }
+        else {
+            AbstractButton newButton;
+            try {
+                if (itemKey.equalsIgnoreCase(helpTopicsAction)) {
+                    newButton = SHTMLHelpBroker.createHelpButton("item15");
+                    final Icon icon = DynamicResource
+                        .getIconForCommand(SHTMLPanelImpl.getResources(), helpTopicsAction);
+                    newButton.setIcon(icon);
+                    newButton.setToolTipText(Util.getResourceString(helpTopicsAction + DynamicResource.toolTipSuffix));
+                    toolBar.add(newButton);
+                }
+                else {
+                    /**
+                     * special handling for JToggleButtons in the tool bar
+                     */
+                    final Action action = dynRes.getAction(itemKey);
+                    if (action instanceof AttributeComponent) {
+                        newButton = new JToggleButton("", (Icon) action.getValue(Action.SMALL_ICON));
+                        newButton.addMouseListener(tbl);
+                        newButton.setAction(action);
+                        newButton.setText("");
+                        //newButton.setActionCommand("");
+                        newButton.setBorderPainted(false);
+                        action.addPropertyChangeListener(new ToggleActionChangedListener((JToggleButton) newButton));
+                        final Icon si = DynamicResource.getIconForName(textResources, action.getValue(Action.NAME)
+                                + DynamicResource.selectedIconSuffix);
+                        if (si != null) {
+                            newButton.setSelectedIcon(si);
+                        }
+                        newButton.setMargin(new Insets(0, 0, 0, 0));
+                        newButton.setIconTextGap(0);
+                        newButton.setContentAreaFilled(false);
+                        newButton.setHorizontalAlignment(SwingConstants.CENTER);
+                        newButton.setVerticalAlignment(SwingConstants.CENTER);
+                        toolBar.add(newButton);
+                    }
+                    /**
+                     * this is the usual way to add tool bar buttons finally
+                     */
+                    else {
+                        newButton = toolBar.add(action);
+                    }
+                }
+                newButton.setMinimumSize(buttonSize);
+                newButton.setPreferredSize(buttonSize);
+                newButton.setMaximumSize(buttonSize);
+                newButton.setFocusPainted(false);
+                newButton.setRequestFocusEnabled(false);
+                if (System.getProperty("os.name").equals("Mac OS X")) {
+                    newButton.putClientProperty("JButton.buttonType", "segmented");
+                    newButton.putClientProperty("JButton.segmentPosition", "middle");
+                }
+            }
+            catch (final Exception ex) {
+            }
+            catch (final java.lang.NoClassDefFoundError e) {
+            } //When one of the help components is not there
+        }
+    }
+
+    /**
+     * displays or removes an etched border around JToggleButtons
+    * this listener is registered with.
+    */
+    private class ToggleBorderListener implements MouseListener {
+        private final EtchedBorder border = new EtchedBorder(EtchedBorder.LOWERED);
+        private JToggleButton button;
+
+        public void mouseClicked(final MouseEvent e) {
+        }
+
+        public void mouseEntered(final MouseEvent e) {
+            final Object src = e.getSource();
+            if (src instanceof JToggleButton) {
+                button = (JToggleButton) src;
+                if (button.isEnabled()) {
+                    ((JToggleButton) src).setBorder(border);
+                }
+            }
+        }
+
+        public void mouseExited(final MouseEvent e) {
+            final Object src = e.getSource();
+            if (src instanceof JToggleButton) {
+                ((JToggleButton) src).setBorder(null);
+            }
+        }
+
+        public void mousePressed(final MouseEvent e) {
+        }
+
+        public void mouseReleased(final MouseEvent e) {
+        }
+    }
+
+    /**
+     * register FrmMain as an object which has interest
+     * in events from a given document pane
+     */
+    protected void registerDocument() {
+        doc.addUndoableEditListener(undoHandler);
+        getSHTMLEditorPane().addCaretListener(this);
+        getSHTMLEditorPane().addKeyListener(rkw);
+    }
+
+    /**
+     * remove FrmMain as a registered object from a given
+     * document pane and its components
+     *
+     * remove all plug-ins owned by this FrmMain from
+     * SimplyHTML objects too
+     */
+    protected void unregisterDocument() {
+        getSHTMLEditorPane().removeCaretListener(this);
+        getSHTMLEditorPane().removeKeyListener(rkw);
+        if (doc != null) {
+            doc.removeUndoableEditListener(undoHandler);
+        }
+        getDocumentPane().removeAllListeners(); // for plug-in removal from any documentPane that is about to close
+        //System.out.println("FrmMain unregister document documentPane.name=" + documentPane.getDocumentName());
+    }
+
+    /**
+     * save a document and catch possible errors
+     *
+     * this is shared by save and saveAs so we put it here to avoid redundancy
+     *
+     * @param documentPane  the document pane containing the document to save
+     */
+    void doSave(final DocumentPane documentPane) {
+    try {
+      documentPane.saveDocument();
+    }
+    /**
+     * this exception should never happen as the menu allows to save a
+     * document only if a name has been set. For new documents, whose
+     * name is not set, only save as is enabled anyway.
+     *
+     * Just in case this is changed without remembering why it was designed
+     * that way, we catch the exception here.
+     */
+    catch(DocNameMissingException e) {
+      Util.errMsg(this, Util.getResourceString(textResources, "docNameMissingError"), e);
+    }
+  }
+
+    public boolean isHtmlEditorActive() {
+        return getDocumentPane() != null && getDocumentPane().getSelectedTab() == DocumentPane.VIEW_TAB_HTML;
+    }
+
+    /**
+     * get action properties from the associated resource bundle
+     *
+     * @param action the action to apply properties to
+     * @param cmd the name of the action to get properties for
+     */
+    public static void getActionProperties(final Action action, final String cmd) {
+        final Icon icon = DynamicResource.getIconForCommand(textResources, cmd);
+        if (icon != null) {
+            action.putValue(Action.SMALL_ICON, icon);
+        }
+        /*else {
+          action.putValue(Action.SMALL_ICON, emptyIcon);
+        }*/
+        final String name = Util.getResourceString(textResources, cmd + DynamicResource.labelSuffix);
+        if (name != null) {
+            action.putValue(Action.NAME, name);
+        }
+        final String toolTip = Util.getResourceString(textResources, cmd + DynamicResource.toolTipSuffix);
+        if (toolTip != null) {
+            action.putValue(Action.SHORT_DESCRIPTION, toolTip);
+        }
+        
+    }
+
+    /* ---------- undo/redo implementation ----------------------- */
+    /** Listener for edits on a document. */
+    private final UndoableEditListener undoHandler = new UndoHandler();
+    /** UndoManager that we add edits to. */
+    private UndoManager undo = new UndoManager();
+
+    /** inner class for handling undoable edit events */
+    class UndoHandler implements UndoableEditListener {
+        /**
+         * Messaged when the Document has created an edit, the edit is
+         * added to <code>undo</code>, an instance of UndoManager.
+         */
+        public void undoableEditHappened(final UndoableEditEvent e) {
+            // ignore all events happened when the html source code pane is open
+            if (getCurrentDocumentPane().getSelectedTab() != DocumentPane.VIEW_TAB_LAYOUT) {
+                return;
+            }
+            getUndo().addEdit(e.getEdit());
+        }
+    }
+
+    /**
+     * caret listener implementation to track format changes
+     */
+    public void caretUpdate(final CaretEvent e) {
+        if (!rkw.isRepeating()) {
+            EventQueue.invokeLater(new Runnable() {
+                public void run() {
+                    updateFormatControls();
+                }
+            });
+        }
+    }
+
+    /**
+     * update any controls that relate to formats at the
+     * current caret position
+     */
+    void updateFormatControls() {
+        updateAToolBar(formatToolBar);
+        updateAToolBar(paraToolBar);
+        if (tagSelector != null) {
+            final SetTagAction sta = (SetTagAction) tagSelector.getAction();
+            sta.setIgnoreActions(true);
+            final Element e = doc.getParagraphElement(getSHTMLEditorPane().getCaretPosition());
+            tagSelector.setSelectedTag(e.getName());
+            sta.setIgnoreActions(false);
+        }
+    }
+
+    private void updateAToolBar(final JToolBar bar) {
+        Component c;
+        Action action;
+        final int count = bar.getComponentCount();
+        final AttributeSet a = getMaxAttributes(getSHTMLEditorPane(), null);
+        for (int i = 0; i < count; i++) {
+            c = bar.getComponentAtIndex(i);
+            if (c instanceof AttributeComponent) {
+                if (c instanceof StyleSelector) {
+                    final SetStyleAction ssa = (SetStyleAction) ((StyleSelector) c).getAction();
+                    final AttributeSet oldAttibuteSet = ((AttributeComponent) c).getValue();
+                    if (!a.isEqual(oldAttibuteSet)) {
+                        ssa.setIgnoreActions(true);
+                        ((AttributeComponent) c).setValue(a);
+                        ssa.setIgnoreActions(false);
+                    }
+                }
+                else {
+                    ((AttributeComponent) c).setValue(a);
+                }
+            }
+            else if (c instanceof AbstractButton) {
+                action = ((AbstractButton) c).getAction();
+                if ((action != null) && (action instanceof AttributeComponent)) {
+                    ((AttributeComponent) action).setValue(a);
+                }
+            }
+        }
+    }
+
+    /**
+    * a JComboBox for selecting a font family names
+    * from those available in the system.
+    */
+    class FontFamilyPicker extends JComboBox implements AttributeComponent {
+        /** switch for the action listener */
+        private boolean ignoreActions = false;
+
+        FontFamilyPicker() {
+            /**
+             * add the font family names available in the system
+             * to the combo box
+             */
+            super(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
+        }
+
+        boolean ignore() {
+            return ignoreActions;
+        }
+
+        /**
+         * set the value of this <code>AttributeComponent</code>
+         *
+         * @param a  the set of attributes possibly having an
+         *          attribute this component can display
+         *
+         * @return true, if the set of attributes had a matching attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            ignoreActions = true;
+            final String newSelection = Util.styleSheet().getFont(a).getFamily();
+            setSelectedItem(newSelection);
+            ignoreActions = false;
+            return true;
+        }
+
+        /**
+         * get the value of this <code>AttributeComponent</code>
+         *
+         * @return the value selected from this component
+         */
+        public AttributeSet getValue() {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            Util.styleSheet().addCSSAttribute(set, CSS.Attribute.FONT_FAMILY, (String) getSelectedItem());
+            set.addAttribute(HTML.Attribute.FACE, (String) getSelectedItem());
+            return set;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            return getValue();
+        }
+    }
+
+    /**
+    * a JComboBox for selecting a font size
+    */
+    static final String[] FONT_SIZES = new String[] { "8", "10", "12", "14", "18", "24" };
+
+    class FontSizePicker extends JComboBox implements AttributeComponent {
+        private boolean ignoreActions = false;
+        final private Object key;
+
+        FontSizePicker() {
+            /**
+             * add font sizes to the combo box
+             */
+            super(FONT_SIZES);
+            key = CSS.Attribute.FONT_SIZE;
+        }
+
+        boolean ignore() {
+            return ignoreActions;
+        }
+
+        /**
+         * set the value of this combo box
+         *
+         * @param a  the set of attributes possibly having a
+         *          font size attribute this pick list could display
+         *
+         * @return true, if the set of attributes had a font size attribute,
+         *            false if not
+         */
+        public boolean setValue(final AttributeSet a) {
+            ignoreActions = true;
+            final int size = Util.styleSheet().getFont(a).getSize();
+            final String newSelection = Integer.toString(size);
+            setEditable(true);
+            setSelectedItem(newSelection);
+            setEditable(false);
+            ignoreActions = false;
+            return true;
+        }
+
+        /**
+         * get the value of this <code>AttributeComponent</code>
+         *
+         * @return the value selected from this component
+         */
+        public AttributeSet getValue() {
+            final SimpleAttributeSet set = new SimpleAttributeSet();
+            final String relativeSize = Integer.toString(getSelectedIndex() + 1);
+            set.addAttribute(HTML.Attribute.SIZE, relativeSize);
+            Util.styleSheet().addCSSAttributeFromHTML(set, CSS.Attribute.FONT_SIZE, relativeSize /*+ "pt"*/);
+            return set;
+        }
+
+        public AttributeSet getValue(final boolean includeUnchanged) {
+            return getValue();
+        }
+    }
+
+    /**
+     * a listener for property change events on ToggleFontActions
+     */
+    private class ToggleActionChangedListener implements PropertyChangeListener {
+        JToggleButton button;
+
+        ToggleActionChangedListener(final JToggleButton button) {
+            super();
+            this.button = button;
+        }
+
+        public void propertyChange(final PropertyChangeEvent e) {
+            final String propertyName = e.getPropertyName();
+            if (e.getPropertyName().equals(SHTMLPanelImpl.ACTION_SELECTED_KEY)) {
+                //System.out.println("propertyName=" + propertyName + " newValue=" + e.getNewValue());
+                if (e.getNewValue().toString().equals(SHTMLPanelImpl.ACTION_SELECTED)) {
+                    button.setSelected(true);
+                }
+                else {
+                    button.setSelected(false);
+                }
+            }
+        }
+    }
+
+    public AttributeSet getMaxAttributes(final int caretPosition) {
+        final Element paragraphElement = getSHTMLDocument().getParagraphElement(caretPosition);
+        final StyleSheet styleSheet = getSHTMLDocument().getStyleSheet();
+        return SHTMLPanelImpl.getMaxAttributes(paragraphElement, styleSheet);
+    }
+
+    /**
+     * Gets all the attributes that can be found in the element tree
+     * starting at the highest parent down to the character element
+     * at the current position in the document. Combine element
+     * attributes with attributes from the style sheet.
+     *
+     * @param editorPane  the editor pane to combine attributes from
+     *
+     * @return the resulting set of combined attributes
+     */
+    AttributeSet getMaxAttributes(final SHTMLEditorPane editorPane, final String elemName) {
+        Element element = doc.getCharacterElement(editorPane.getSelectionStart());
+        final StyleSheet styleSheet = doc.getStyleSheet();
+        if (elemName != null && elemName.length() > 0) {
+            element = Util.findElementUp(elemName, element);
+            return SHTMLPanelImpl.getMaxAttributes(element, styleSheet);
+        }
+        final MutableAttributeSet maxAttributes = (MutableAttributeSet) SHTMLPanelImpl.getMaxAttributes(element,
+            styleSheet);
+        final StyledEditorKit editorKit = (StyledEditorKit) editorPane.getEditorKit();
+        final MutableAttributeSet inputAttributes = editorKit.getInputAttributes();
+        maxAttributes.addAttributes(inputAttributes);
+        return maxAttributes;
+    }
+
+    Frame getMainFrame() {
+        return JOptionPane.getFrameForComponent(SHTMLPanelImpl.this);
+    }
+
+    static AttributeSet getMaxAttributes(Element e, final StyleSheet s) {
+        final SimpleAttributeSet a = new SimpleAttributeSet();
+        final Element cElem = e;
+        AttributeSet attrs;
+        final Vector elements = new Vector();
+        Object classAttr;
+        String styleName;
+        String elemName;
+        while (e != null) {
+            elements.insertElementAt(e, 0);
+            e = e.getParentElement();
+        }
+        for (int i = 0; i < elements.size(); i++) {
+            e = (Element) elements.elementAt(i);
+            classAttr = e.getAttributes().getAttribute(HTML.Attribute.CLASS);
+            elemName = e.getName();
+            styleName = elemName;
+            if (classAttr != null) {
+                styleName = elemName + "." + classAttr.toString();
+                a.addAttribute(HTML.Attribute.CLASS, classAttr);
+            }
+            //System.out.println("getMaxAttributes name=" + styleName);
+            attrs = s.getStyle(styleName);
+            if (attrs != null) {
+                a.addAttributes(Util.resolveAttributes(attrs));
+            }
+            else {
+                attrs = s.getStyle(elemName);
+                if (attrs != null) {
+                    a.addAttributes(Util.resolveAttributes(attrs));
+                }
+            }
+            a.addAttributes(Util.resolveAttributes(e.getAttributes()));
+        }
+        if (cElem != null) {
+            //System.out.println("getMaxAttributes cElem.name=" + cElem.getName());
+            a.addAttributes(cElem.getAttributes());
+        }
+        //System.out.println(" ");
+        //de.calcom.cclib.html.HTMLDiag hd = new de.calcom.cclib.html.HTMLDiag();
+        //hd.listAttributes(a, 4);
+        return new AttributeMapper(a).getMappedAttributes(AttributeMapper.toJava);
+    }
+
+    /**
+     * @param documentPane The documentPane to set.
+     */
+    void setDocumentPane(final DocumentPane documentPane) {
+        this.documentPane = documentPane;
+    }
+
+    /**
+     * @return Returns the documentPane.
+     */
+    public DocumentPane getDocumentPane() {
+        return documentPane;
+    }
+
+    protected void setEditorPane(final SHTMLEditorPane editorPane) {
+        if (editorPane != null) {
+            editorPane.setPopup(editorPopup);
+        }
+        this.editorPane = editorPane;
+    }
+
+    /**
+     * @return Returns the editorPane.
+     */
+    public SHTMLEditorPane getSHTMLEditorPane() {
+        return (SHTMLEditorPane) getEditorPane();
+    }
+
+    public JEditorPane getEditorPane() {
+        return editorPane;
+    }
+
+    public JEditorPane getSourceEditorPane() {
+        return (JEditorPane) getDocumentPane().getHtmlEditor();
+    }
+
+    /**
+     * @return Returns the doc.
+     */
+    SHTMLDocument getSHTMLDocument() {
+        return doc;
+    }
+
+    /**
+     * @param undo The undo to set.
+     */
+    void setUndo(final UndoManager undo) {
+        this.undo = undo;
+    }
+
+    /**
+     * @return Returns the undo.
+     */
+    UndoManager getUndo() {
+        return undo;
+    }
+
+    /**
+     * @param tagSelector The tagSelector to set.
+     */
+    void setTagSelector(final TagSelector tagSelector) {
+        this.tagSelector = tagSelector;
+    }
+
+    /**
+     * @return Returns the tagSelector.
+     */
+    TagSelector getTagSelector() {
+        return tagSelector;
+    }
+
+    void savePrefs() {
+        splitPanel.savePrefs();
+    }
+
+    boolean close() {
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.JComponent#requestFocus()
+     */
+    public JEditorPane getMostRecentFocusOwner() {
+        if (getDocumentPane() != null) {
+            return getDocumentPane().getMostRecentFocusOwner();
+        }
+        return null;
+    }
+
+    /* ---------- font manipulation code end ------------------ */
+    public int getCaretPosition() {
+        return getSHTMLEditorPane().getCaretPosition();
+    }
+
+    public JMenuBar getMenuBar() {
+        return menuBar;
+    }
+
+    public void switchViews() {
+        getDocumentPane().switchViews();
+    }
+
+    public void setOpenHyperlinkHandler(final ActionListener openHyperlinkHandler) {
+        this.openHyperlinkHandler = openHyperlinkHandler;
+    }
+
+    public void openHyperlink(final String linkURL) {
+        if (openHyperlinkHandler != null) {
+            openHyperlinkHandler.actionPerformed(new ActionEvent(this, 0, linkURL));
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLPanelMultipleDocImpl.java b/src/com/lightdev/app/shtm/SHTMLPanelMultipleDocImpl.java
new file mode 100644
index 0000000..aee8c8e
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLPanelMultipleDocImpl.java
@@ -0,0 +1,188 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Created on 04.10.2006
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+
+import javax.swing.JTabbedPane;
+import javax.swing.JToolBar;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.text.html.HTML;
+
+class SHTMLPanelMultipleDocImpl extends SHTMLPanelImpl implements ChangeListener {
+    public static final String newAction = "new";
+    public static final String openAction = "open";
+    public static final String closeAction = "close";
+    public static final String closeAllAction = "closeAll";
+    public static final String saveAction = "save";
+    public static final String saveAsAction = "saveAs";
+    /** the tabbed pane for adding documents to show to */
+    private JTabbedPane jtpDocs;
+    /** tool bar selector for styles */
+    private StyleSelector styleSelector;
+    /** number of currently active tab */
+    private int activeTabNo;
+
+    public SHTMLPanelMultipleDocImpl() {
+        super();
+    }
+
+    protected void initDocumentPane() {
+        dynRes.getAction(newAction).actionPerformed(null);
+        getDocumentPane().getEditor().setCaretPosition(0);
+    }
+
+    /* (non-Javadoc)
+     * @see com.lightdev.app.shtm.SHTMLPanelImpl#initActions()
+     */
+    protected void initActions() {
+        super.initActions();
+        addAction(findReplaceAction, new SHTMLEditorKitActions.MultipleDocFindReplaceAction(this));
+        addAction(setStyleAction, new SHTMLEditorKitActions.SetStyleAction(this));
+        addAction(newAction, new SHTMLEditorKitActions.SHTMLFileNewAction(this));
+        addAction(openAction, new SHTMLEditorKitActions.SHTMLFileOpenAction(this));
+        addAction(closeAction, new SHTMLEditorKitActions.SHTMLFileCloseAction(this));
+        addAction(closeAllAction, new SHTMLEditorKitActions.SHTMLFileCloseAllAction(this));
+        addAction(saveAction, new SHTMLEditorKitActions.SHTMLFileSaveAction(this));
+        addAction(saveAllAction, new SHTMLEditorKitActions.SHTMLFileSaveAllAction(this));
+        addAction(saveAsAction, new SHTMLEditorKitActions.SHTMLFileSaveAsAction(this));
+        addAction(exitAction, new SHTMLEditorKitActions.SHTMLFileExitAction(this));
+    }
+
+    /* (non-Javadoc)
+     * @see com.lightdev.app.shtm.SHTMLPanelImpl#customizeFrame()
+     */
+    protected void customizeFrame() {
+        jtpDocs = new JTabbedPane();
+        super.customizeFrame();
+        jtpDocs.addChangeListener(this);
+        splitPanel.addComponent(jtpDocs, SplitPanel.CENTER);
+    }
+
+    /* (non-Javadoc)
+     * @see com.lightdev.app.shtm.SHTMLPanelImpl#createToolbarItem(javax.swing.JToolBar, java.lang.String)
+     */
+    protected void createToolbarItem(final JToolBar toolBar, final String itemKey) {
+        if (itemKey.equalsIgnoreCase(setStyleAction)) {
+            styleSelector = new StyleSelector(this, HTML.Attribute.CLASS);
+            styleSelector.setPreferredSize(new Dimension(110, 23));
+            styleSelector.setAction(dynRes.getAction(setStyleAction));
+            final Dimension comboBoxSize = new Dimension(300, 24);
+            styleSelector.setMaximumSize(comboBoxSize);
+            jtpDocs.addChangeListener(styleSelector);
+            toolBar.add(styleSelector);
+        }
+        else {
+            super.createToolbarItem(toolBar, itemKey);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see com.lightdev.app.shtm.SHTMLPanelImpl#registerDocument()
+     */
+    protected void registerDocument() {
+        super.registerDocument();
+        ((SHTMLDocument) getDocumentPane().getDocument()).getStyleSheet().addChangeListener(styleSelector);
+    }
+
+    /* (non-Javadoc)
+     * @see com.lightdev.app.shtm.SHTMLPanelImpl#unregisterDocument()
+     */
+    protected void unregisterDocument() {
+        super.unregisterDocument();
+        ((SHTMLDocument) getDocumentPane().getDocument()).getStyleSheet().removeChangeListener(styleSelector);
+    }
+
+    /**
+     * catch requests to close the application's main frame to
+     * ensure proper clean up before the application is
+     * actually terminated.
+     */
+    boolean close() {
+        dynRes.getAction(exitAction).actionPerformed(new ActionEvent(this, 0, exitAction));
+        return jtpDocs.getTabCount() == 0;
+    }
+
+    /**
+     * change listener to be applied to our tabbed pane
+     * so that always the currently active components
+     * are known
+     */
+    public void stateChanged(final ChangeEvent e) {
+        activeTabNo = jtpDocs.getSelectedIndex();
+        if (activeTabNo >= 0) {
+            setDocumentPane((DocumentPane) jtpDocs.getComponentAt(activeTabNo));
+            setEditorPane(getDocumentPane().getEditor());
+            //System.out.println("FrmMain stateChanged docName now " + documentPane.getDocumentName());
+            doc = (SHTMLDocument) getSHTMLEditorPane().getDocument();
+            //fireDocumentChanged();
+            if (!ignoreActivateDoc) {
+                getDocumentPane().fireActivated();
+            }
+        }
+        else {
+            setDocumentPane(null);
+            setEditorPane(null);
+            doc = null;
+        }
+    }
+
+    /**
+     * @return Returns the jtpDocs.
+     */
+    JTabbedPane getTabbedPaneForDocuments() {
+        return jtpDocs;
+    }
+
+    /* (non-Javadoc)
+     * @see com.lightdev.app.shtm.SHTMLPanelImpl#updateFormatControls()
+     */
+    void updateFormatControls() {
+        super.updateFormatControls();
+        styleSelector.update();
+    }
+
+    void incNewDocCounter() {
+        newDocCounter++;
+    }
+
+    void createNewDocumentPane() {
+        setDocumentPane(new DocumentPane(null, ++newDocCounter));
+    }
+
+    void selectTabbedPane(final int index) {
+        ignoreActivateDoc = true;
+        getTabbedPaneForDocuments().setSelectedIndex(index);
+        ignoreActivateDoc = false;
+    }
+
+    int getActiveTabNo() {
+        return activeTabNo;
+    }
+
+    /**
+     * @param activeTabNo The activeTabNo to set.
+     */
+    void setActiveTabNo(final int activeTabNo) {
+        this.activeTabNo = activeTabNo;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLPanelSingleDocImpl.java b/src/com/lightdev/app/shtm/SHTMLPanelSingleDocImpl.java
new file mode 100644
index 0000000..c71a884
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLPanelSingleDocImpl.java
@@ -0,0 +1,44 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Created on 07.10.2006
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+class SHTMLPanelSingleDocImpl extends SHTMLPanelImpl {
+    public SHTMLPanelSingleDocImpl() {
+        super();
+    }
+
+    /* (non-Javadoc)
+     * @see com.lightdev.app.shtm.SHTMLPanelImpl#initDocumentPane()
+     */
+    protected void initDocumentPane() {
+        super.initDocumentPane();
+        setDocumentPane(new DocumentPane(null, 1));
+        setEditorPane(getDocumentPane().getEditor());
+        doc = (SHTMLDocument) getEditorPane().getDocument();
+        registerDocument();
+        getDocumentPane().getEditor().setCaretPosition(0);
+        splitPanel.addComponent(getDocumentPane(), SplitPanel.CENTER);
+    }
+
+    protected void initActions() {
+        super.initActions();
+        addAction(findReplaceAction, new SHTMLEditorKitActions.SingleDocFindReplaceAction(this));
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLPlugin.java b/src/com/lightdev/app/shtm/SHTMLPlugin.java
new file mode 100644
index 0000000..9858fb7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLPlugin.java
@@ -0,0 +1,180 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JMenuItem;
+
+/**
+ * Defines an interface all plug-ins for application SimplyHTML
+ * have to implement.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+public interface SHTMLPlugin {
+    /** indicates docking is not requested */
+    public static final int DOCK_LOCATION_NONE = 0;
+    /** indicates docking requested on top of a given container */
+    public static final int DOCK_LOCATION_TOP = 1;
+    /** indicates docking requested on the right of a given container */
+    public static final int DOCK_LOCATION_RIGHT = 2;
+    /** indicates docking requested on bottom of a given container */
+    public static final int DOCK_LOCATION_BOTTOM = 3;
+    /** indicates docking requested on the left of a given container */
+    public static final int DOCK_LOCATION_LEFT = 4;
+
+    /**
+     * get the name of the plug-in as it shall appear
+     * on a GUI.
+     *
+     * @return the name of the plug-in
+     */
+    public String getGUIName();
+
+    /**
+     * get the name used internally for this plug-in
+     *
+     * @return the internal name of this plug-in
+     */
+    public String getInternalName();
+
+    /**
+     * get a menu of actions this plug-in provides.
+     *
+     * <p><code>JMenu</code> is a decendant of <code>JMenuItem</code>
+     * so this method may return a single menu item up to a whole
+     * structure of submenus in its return value.</p>
+     *
+     * @return the plug-in menu
+     */
+    public JMenuItem getPluginMenu();
+
+    /**
+     * get a menu item providing documentation about this
+     * plug-in.
+     *
+     * <p><code>JMenu</code> is a decendant of <code>JMenuItem</code>
+     * so this method may return a single menu item up to a whole
+     * structure of submenus in its return value.</p>
+     *
+     * @return a menu item with help for this plug-in
+     */
+    public JMenuItem getHelpMenu();
+
+    /**
+     * get the location the component returned by getDockComponent()
+     * shall be docked at.
+     *
+     * @return the dock location, one of DOCK_LOCATION_TOP, DOCK_LOCATION_BOTTOM,
+     * DOCK_LOCATION.LEFT, DOCK_LOCATION_RIGHT or DOCK_LOCATION_NONE, if the
+     * component shall not dock.
+     */
+    public int getDockLocation();
+
+    /**
+     * set the location the component returned by getDockComponent()
+     * shall be docked at.
+     *
+     * @param location the dock location, one of DOCK_LOCATION_TOP, DOCK_LOCATION_BOTTOM,
+     * DOCK_LOCATION.LEFT, DOCK_LOCATION_RIGHT or DOCK_LOCATION_NONE, if the
+     * component shall not dock.
+     */
+    public void setDockLocation(int location);
+
+    /**
+     * get the component that this plug-in produces, if any
+     *
+     * @return the component produced by this plug-in, or null if none
+     * is produced
+     */
+    public JComponent getComponent();
+
+    /**
+     * get the status of the plug-in
+     *
+     * @return true, if activated, false if not
+     */
+    public boolean isActive();
+
+    /**
+     * set status of plug-in
+     *
+     * @param isActive  indicates whether or not the plug-in shall be activated
+     */
+    public void setStatus(boolean isActive);
+
+    /**
+     * set the owner of this plug-in
+     *
+     * @param owner  the main frame of the instance of SimplyHTML creating the plug-in
+     */
+    public void setOwner(SHTMLPanelImpl owner);
+
+    /**
+     * get the owner of this plug-in
+     *
+     * @return   the main frame of the instance of SimplyHTML that created the plug-in
+     */
+    public SHTMLPanelImpl getOwner();
+
+    /**
+     * get a string from the resource bundle of the owner of this plug-in
+     *
+     * @param nm  the name of the string resource to get
+     *
+     * @return the string with the given name or null, if none is found
+     */
+    public String getOwnerResString(String nm);
+
+    /**
+     * get an action from the resource bundle of the owner of this plug-in
+     *
+     * @param cmd  the name of the action to get
+     *
+     * @return the action with the given name or null, if none is found
+     */
+    public Action getOwnerAction(String cmd);
+
+    /**
+     * init the plug-in
+     *
+     * this is called by the PluginManager directly after instantiating the plug-in
+     * @param owner  the owner of this plug-in
+     * @param internalName  the internal name this plug-in shall have
+     * @param pluginMenuId  the id of the plug-in menu in the TextResources,
+     * or null if no plugin-in menu is to be created
+     * @param helpMenuId  the id of the help menu for this plug-in in the
+     * TextResources, or null if no help menu is to be created
+     */
+    public void initPlugin(SHTMLPanelImpl owner, String internalName, String pluginMenuId, String helpMenuId);
+
+    public void initHelpMenu();
+
+    public void showInitialInfo();
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLPrefsChangeListener.java b/src/com/lightdev/app/shtm/SHTMLPrefsChangeListener.java
new file mode 100644
index 0000000..4b25bd4
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLPrefsChangeListener.java
@@ -0,0 +1,5 @@
+package com.lightdev.app.shtm;
+
+public interface SHTMLPrefsChangeListener {
+	void shtmlPrefChanged(String propertyName, String newValue, String oldValue);
+}
diff --git a/src/com/lightdev/app/shtm/SHTMLWriter.java b/src/com/lightdev/app/shtm/SHTMLWriter.java
new file mode 100644
index 0000000..ace3534
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SHTMLWriter.java
@@ -0,0 +1,376 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Enumeration;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.ElementIterator;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLWriter;
+
+/**
+ * FixedHTMLWriter
+ *
+ * 
+ */
+public class SHTMLWriter extends HTMLWriter {
+    private Element element;
+    private Writer writer = null;
+    private boolean replaceEntities;
+    private boolean inTextArea;
+    //final private MutableAttributeSet oConvAttr  = new SimpleAttributeSet();
+    //final private MutableAttributeSet convertedAttributeSet  = new SimpleAttributeSet();
+    private boolean inPre;
+
+    public SHTMLWriter(final Writer w, final HTMLDocument doc, final int pos, final int len) {
+        super(w, doc, pos, len);
+        writer = w;
+    }
+
+    /** Constructs the SHTMLWriter with a new StringWriter. See also the method
+     * getWrittenString. */
+    public SHTMLWriter(final HTMLDocument doc) {
+        this(new StringWriter(), doc, 0, doc.getLength());
+    }
+
+    public SHTMLWriter(final Writer w, final HTMLDocument doc) {
+        this(w, doc, 0, doc.getLength());
+    }
+
+    protected ElementIterator getElementIterator() {
+        if (element == null) {
+            return super.getElementIterator();
+        }
+        return new ElementIterator(element);
+    }
+
+    protected void output(final char[] chars, final int start, final int length) throws IOException {
+        if (replaceEntities) {
+            if (chars[start] == ' ') {
+                chars[start] = '\u00A0';
+            }
+            final int last = start + length - 1;
+            for (int i = start + 1; i < last; i++) {
+                if (chars[i] == ' ' && (chars[i - 1] == '\u00A0' || chars[i + 1] == ' ')) {
+                    chars[i] = '\u00A0';
+                }
+            }
+            //			if(chars[last] == ' '){
+            //				chars[last] = '\u00A0';
+            //			}
+        }
+        super.output(chars, start, length);
+    }
+
+    protected void startTag(final Element elem) throws IOException, BadLocationException {
+        if (matchNameAttribute(elem.getAttributes(), HTML.Tag.PRE)) {
+            inPre = true;
+        }
+        super.startTag(elem);
+    }
+
+    protected void endTag(final Element elem) throws IOException {
+        if (matchNameAttribute(elem.getAttributes(), HTML.Tag.PRE)) {
+            inPre = false;
+        }
+        super.endTag(elem);
+    }
+
+    protected void text(final Element elem) throws BadLocationException, IOException {
+        replaceEntities = !inPre;
+        super.text(elem);
+        replaceEntities = false;
+    }
+
+    protected void textAreaContent(final AttributeSet attr) throws BadLocationException, IOException {
+        inTextArea = true;
+        super.textAreaContent(attr);
+        inTextArea = false;
+    }
+
+    public void write() throws IOException, BadLocationException {
+        replaceEntities = false;
+        super.write();
+    }
+
+    protected void writeLineSeparator() throws IOException {
+        final boolean pre = replaceEntities;
+        replaceEntities = false;
+        super.writeLineSeparator();
+        replaceEntities = pre;
+    }
+
+    protected void indent() throws IOException {
+        if (inTextArea) {
+            return;
+        }
+        final boolean pre = replaceEntities;
+        replaceEntities = false;
+        super.indent();
+        replaceEntities = pre;
+    }
+
+    /**
+     * Iterates over the
+     * Element tree and controls the writing out of
+     * all the tags and its attributes.
+     *
+     * @exception IOException on any I/O error
+     * @exception BadLocationException if pos represents an invalid
+     *            location within the document.
+     *
+     */
+    synchronized void write(Element element) throws IOException, BadLocationException {
+        this.element = element;
+        try {
+            write();
+        }
+        catch (final BadLocationException e) {
+            element = null;
+            throw e;
+        }
+        catch (final IOException e) {
+            element = null;
+            throw e;
+        }
+    }
+
+    /**
+     * invoke HTML creation for all children of a given element.
+     *
+     * @param elem  the element which children are to be written as HTML
+     */
+    public void writeChildElements(final Element parentElement) throws IOException, BadLocationException {
+        Element childElement; //Not necessarily a paragraph element.
+        for (int i = 0; i < parentElement.getElementCount(); i++) {
+            childElement = parentElement.getElement(i);
+            write(childElement);
+        }
+    }
+
+    protected boolean inRange(final Element next) {
+        final Document document = next.getDocument();
+        if (document instanceof SHTMLDocument
+                && next.getStartOffset() >= ((SHTMLDocument) document).getLastDocumentPosition()) {
+            return false;
+        }
+        final int startOffset = getStartOffset();
+        final int endOffset = getEndOffset();
+        if ((next.getStartOffset() >= startOffset && (next.getStartOffset() < endOffset) || next.getEndOffset() - 1 == endOffset)
+                || (startOffset >= next.getStartOffset() && startOffset < next.getEndOffset())) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Create an older style of HTML attributes.  This will 
+     * convert character level attributes that have a StyleConstants
+     * mapping over to an HTML tag/attribute.  Other CSS attributes
+     * will be placed in an HTML style attribute.
+     */
+    private static void convertStyleToHTMLStyle(final AttributeSet source, final MutableAttributeSet target) {
+        if (source == null) {
+            return;
+        }
+        final Enumeration sourceAttributeNames = source.getAttributeNames();
+        String value = "";
+        while (sourceAttributeNames.hasMoreElements()) {
+            final Object sourceAttributeName = sourceAttributeNames.nextElement();
+            if (sourceAttributeName instanceof CSS.Attribute) {
+                // default is to store in a HTML style attribute
+                if (value.length() > 0) {
+                    value += "; ";
+                }
+                value += sourceAttributeName + ": " + source.getAttribute(sourceAttributeName);
+            }
+            else {
+                target.addAttribute(sourceAttributeName, source.getAttribute(sourceAttributeName));
+            }
+        }
+        if (value.length() > 0) {
+            target.addAttribute(HTML.Attribute.STYLE, value);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLWriter#writeAttributes(javax.swing.text.AttributeSet)
+     */
+    protected void writeAttributes(final AttributeSet attributeSet) throws IOException {
+        final Object nameTag = (attributeSet != null) ? attributeSet.getAttribute(StyleConstants.NameAttribute) : null;
+        final Object endTag = (attributeSet != null) ? attributeSet.getAttribute(HTML.Attribute.ENDTAG) : null;
+        // write no attributes for end tags
+        if (nameTag != null && endTag != null && (endTag instanceof String) && ((String) endTag).equals("true")) {
+            return;
+        }
+        if (attributeSet instanceof Element) {
+            final Element element = (Element) attributeSet;
+            if (element.isLeaf() || element.getName().equalsIgnoreCase("p-implied")) {
+                super.writeAttributes(attributeSet);
+                return;
+            }
+        }
+        //convertedAttributeSet.removeAttributes(convertedAttributeSet);
+        final MutableAttributeSet convertedAttributeSet = new SimpleAttributeSet();
+        SHTMLWriter.convertStyleToHTMLStyle(attributeSet, convertedAttributeSet);
+        final Enumeration attributeNames = convertedAttributeSet.getAttributeNames();
+        while (attributeNames.hasMoreElements()) {
+            final Object attributeName = attributeNames.nextElement();
+            if (attributeName instanceof HTML.Tag || attributeName instanceof StyleConstants
+                    || attributeName == HTML.Attribute.ENDTAG) {
+                continue;
+            }
+            write(" " + attributeName + "=\"" + convertedAttributeSet.getAttribute(attributeName) + "\"");
+        }
+    }
+
+    /**
+     * write an element and all its children. If a given element is reached,
+     * writing stops with this element. If the end element is a leaf,
+     * it is written as the last element, otherwise it is not written.
+     *
+     * @param e  the element to write including its children (if any)
+     * @param end  the last leaf element to write or the branch element
+     * to stop writing at (whatever applies)
+     */
+    private void writeElementsUntil(final Element e, final Element end) throws IOException, BadLocationException {
+        if (e.isLeaf()) {
+            write(e);
+        }
+        else {
+            if (e != end) {
+                startTag(e);
+                final int childCount = e.getElementCount();
+                int index = 0;
+                while (index < childCount) {
+                    writeElementsUntil(e.getElement(index), end); // drill down in recursion
+                    index++;
+                }
+                endTag(e);
+            }
+        }
+    }
+
+    /**
+     * write elements and their children starting at a
+     * given element until a given element is reached.
+     * The end element is written as the last element,
+     * if it is a leaf element.
+     *
+     * @param startElement  the element to start writing with
+     * @param endElement  the last element to write
+     */
+    void write(final Element startElement, final Element endElement) throws IOException, BadLocationException {
+        final Element parentElement = startElement.getParentElement();
+        final int count = parentElement.getElementCount();
+        int i = 0;
+        Element e = parentElement.getElement(i);
+        while (i < count && e != startElement) {
+            e = parentElement.getElement(i++);
+        }
+        while (i < count) {
+            writeElementsUntil(e, endElement);
+            e = parentElement.getElement(i++);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLWriter#startTag(javax.swing.text.Element)
+     */
+    void writeStartTag(final Element elem) throws IOException, BadLocationException {
+        // TODO Auto-generated method stub
+        super.startTag(elem);
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.text.html.HTMLWriter#endTag(javax.swing.text.Element)
+     */
+    void writeEndTag(final Element elem) throws IOException {
+        // TODO Auto-generated method stub
+        super.endTag(elem);
+    }
+
+    void writeEndTag(final String elementName) throws IOException {
+        indent();
+        write('<');
+        write('/');
+        write(elementName);
+        write('>');
+        writeLineSeparator();
+    }
+
+    void writeStartTag(final String elementName, final AttributeSet attributes) throws IOException {
+        indent();
+        write('<');
+        write(elementName);
+        if (attributes != null) {
+            writeAttributes(attributes);
+        }
+        write('>');
+        writeLineSeparator();
+    }
+
+    public void write(final String string) {
+        try {
+            writer.write(string);
+        }
+        catch (final IOException ex) {
+        }
+    }
+
+    public String toString() {
+        if (writer instanceof StringWriter) {
+            final StringWriter stringWriter = (StringWriter) writer;
+            return stringWriter.getBuffer().toString();
+        }
+        return super.toString();
+    }
+
+    /** Gets the written string if the writer is a StringWriter, null otherwise. */
+    String getWrittenString() {
+        if (writer instanceof StringWriter) {
+            final StringWriter stringWriter = (StringWriter) writer;
+            return stringWriter.getBuffer().toString();
+        }
+        return null;
+    }
+
+    void removeLastWrittenNewline() {
+        if (writer instanceof StringWriter) {
+            final StringWriter stringWriter = (StringWriter) writer;
+            int charIdx = stringWriter.getBuffer().length();
+            while (stringWriter.getBuffer().charAt(--charIdx) <= 13) {
+                stringWriter.getBuffer().deleteCharAt(charIdx);
+            }
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/ScaledStyleSheet.java b/src/com/lightdev/app/shtm/ScaledStyleSheet.java
new file mode 100644
index 0000000..2361220
--- /dev/null
+++ b/src/com/lightdev/app/shtm/ScaledStyleSheet.java
@@ -0,0 +1,72 @@
+/*
+ *  Freeplane - mind map editor
+ *  Copyright (C) 2012 Freeplane team and others
+ *
+ *  this file is created by Dimitry Polivaev in 2012.
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Font;
+import java.awt.Toolkit;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.StyleSheet;
+
+
+public class ScaledStyleSheet extends StyleSheet{
+	
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+	public Font getFont(AttributeSet a) {
+	    final Font font = super.getFont(a);
+	    final float fontScaleFactor = getFontScaleFactor(a);
+	    return super.getFont(font.getFamily(), font.getStyle(), Math.round(font.getSize2D() * fontScaleFactor));
+    }
+
+	public static float FONT_SCALE_FACTOR;
+	static {
+		float factor = 1f; 
+		try {
+	        factor = Toolkit.getDefaultToolkit().getScreenResolution()  / 72f;
+        }
+        catch (Exception e) {
+        }
+		FONT_SCALE_FACTOR = factor;
+	}
+	
+	private float getFontScaleFactor(AttributeSet a) {
+		final Object attribute = a.getAttribute(CSS.Attribute.FONT_SIZE);
+		if(attribute == null)
+			return FONT_SCALE_FACTOR;
+		final String fontSize = attribute.toString();
+		final int fsLength = fontSize.length();
+		if(fsLength <= 1 
+				|| Character.isDigit(fontSize.charAt(fsLength-1))
+				|| fontSize.endsWith("pt"))
+			return FONT_SCALE_FACTOR;
+		if(fontSize.endsWith("px"))
+			return 1/1.3f;
+		if(fontSize.endsWith("%") || fontSize.endsWith("em") || fontSize.endsWith("ex")
+				|| fontSize.endsWith("er"))
+			return getFontScaleFactor(a.getResolveParent());
+		return FONT_SCALE_FACTOR;
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/com/lightdev/app/shtm/SizeSelectorPanel.java b/src/com/lightdev/app/shtm/SizeSelectorPanel.java
new file mode 100644
index 0000000..dbeca8a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SizeSelectorPanel.java
@@ -0,0 +1,309 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.CSS;
+
+/**
+ * Panel to show and manipulate a CSS size value
+ *
+ * <p>Added support for negative integers in stage 8.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class SizeSelectorPanel extends JPanel implements AttributeComponent, ActionListener {
+    private final Object attributeKey;
+    private final Object htmlAttrKey;
+    private final JSpinner valueSelector;
+    private JComboBox unitSelector;
+    private JLabel unitName;
+    //private LengthValue lv;
+    private int setValueCalls = 0;
+    private int originalValue = 0;
+    private String originalUnit;
+    private boolean allowNegative = false;
+    public static final String UNIT_PT = "pt";
+    public static final String UNIT_PERCENT = "%";
+    public static final String[] UNIT_VALUES = { UNIT_PT, UNIT_PERCENT };
+    public static final int UNIT_TYPE_PT = 0;
+    public static final int UNIT_TYPE_PERCENT = 1;
+    public static final int TYPE_NONE = 0;
+    public static final int TYPE_LABEL = 1;
+    public static final int TYPE_COMBO = 2;
+
+    /**
+     * construct a basic SizeSelectorPanel with a
+     * JSpinner to select a value
+     *
+     * @param key  the attribute key this instance of SizeSelectionPanel
+     *      represents
+     * @param allowNegative  true, if negative values are to be allowed in the
+     *      panel, false if not
+     */
+    public SizeSelectorPanel(final Object key, final Object htmlKey, final boolean allowNegative) {
+        super(new FlowLayout());
+        attributeKey = key;
+        htmlAttrKey = htmlKey;
+        valueSelector = new JSpinner(new SpinnerNumberModel());
+        final Dimension dim = new Dimension(50, 24);
+        valueSelector.setMinimumSize(dim);
+        valueSelector.setPreferredSize(dim);
+        add(valueSelector);
+        originalUnit = getUnit();
+        this.allowNegative = allowNegative;
+    }
+
+    /**
+     * construct a SizeSelectorPanel with a
+     * JSpinner to select a value and either a JComboBox to select a given
+     * unit for the selection value or a JLabel showing a fixed unit.
+     *
+     * @param key  the attribute key this instance of SizeSelectionPanel
+     *      represents
+     * @param allowNegative  true, if negative values are to be allowed in the
+     *      panel, false if not
+     * @param type  the type of unit indicator, one of TYPE_LABEL and
+     *      TYPE_COMBO
+     */
+    public SizeSelectorPanel(final Object key, final Object htmlKey, final boolean allowNegative, final int type) {
+        this(key, htmlKey, allowNegative);
+        switch (type) {
+            case TYPE_LABEL:
+                //System.out.println("SizeSelectorPanel constructor setting Label");
+                unitName = new JLabel(UNIT_PT);
+                add(unitName);
+                break;
+            case TYPE_COMBO:
+                //System.out.println("SizeSelectorPanel constructor setting COMBO");
+                unitSelector = new JComboBox(UNIT_VALUES);
+                unitSelector.addActionListener(this);
+                add(unitSelector);
+                break;
+        }
+        originalUnit = getUnit();
+    }
+
+    public void actionPerformed(final ActionEvent ae) {
+        if (ae.getSource().equals(unitSelector)) {
+            //System.out.println("actionPerformed is unitSelector new value = " + unitSelector.getSelectedItem().toString());
+            adjustMinMax(unitSelector.getSelectedItem().toString());
+        }
+    }
+
+    public void setValue(final String val) {
+        //System.out.println("SizeSelectorPanel setValue STRING, val=" + val);
+        String unit = null;
+        int newVal = 0;
+        //if(attributeKey instanceof CSS.Attribute) {
+        //lv = new LengthValue(val);
+        final float aVal = Util.getAbsoluteAttrVal(val);
+        //System.out.println("SizeSelectorPanel aVal=" + aVal);
+        unit = Util.getLastAttrUnit(); //lv.getUnit();
+        //System.out.println("SizeSelectorPanel unit=" + unit);
+        adjustMinMax(unit);
+        if (unitSelector != null) {
+            //System.out.println("SizeSelectorPanel setValue setting combo");
+            unitSelector.setSelectedItem(unit);
+        }
+        else if (unitName != null) {
+            //System.out.println("SizeSelectorPanel setValue setting label");
+            unitName.setText(unit);
+        }
+        newVal = (int) aVal; // new Float(lv.getValue(100)).intValue();
+        //System.out.println("SizeSelectorPanel setValue newVal=" + newVal);
+        valueSelector.setValue(new Integer(newVal));
+        //}
+        /*
+        else {
+          newVal = Integer.parseInt(val);
+          valueSelector.setValue(new Integer(val));
+          unit = UNIT_PT;
+        }
+        */
+        if (++setValueCalls < 2) {
+            originalValue = newVal;
+            originalUnit = unit;
+        }
+    }
+
+    /**
+     * set the value of this <code>AttributeComponent</code>
+     *
+     * @param a  the set of attributes possibly having an
+     *          attribute this component can display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(final AttributeSet a) {
+        boolean success = false;
+        //System.out.println("SizeSelectorPanel setValue SET attributeKey=" + attributeKey + ", htmlAttrKey=" + htmlAttrKey);
+        Object valObj = a.getAttribute(attributeKey);
+        if (valObj != null) {
+            //System.out.println("SizeSelectorPanel CSS valObj=" + valObj);
+            setValue(valObj.toString());
+            success = true;
+        }
+        else {
+            if (htmlAttrKey != null) {
+                valObj = a.getAttribute(htmlAttrKey);
+                if (valObj != null) {
+                    //System.out.println("SizeSelectorPanel HTML valObj=" + valObj);
+                    setValue(valObj.toString());
+                    success = true;
+                }
+            }
+        }
+        return success;
+    }
+
+    /**
+     * adjust the minimum and maximum values of the component
+     * according to the unit
+     */
+    private void adjustMinMax(final String unit) {
+        //if(lv != null) {
+        final SpinnerNumberModel model = (SpinnerNumberModel) valueSelector.getModel();
+        int minVal = 0;
+        if (allowNegative) {
+            minVal = Integer.MIN_VALUE;
+        }
+        if (unit.equalsIgnoreCase(UNIT_PERCENT)) {
+            //System.out.println("adjustMinMax percent");
+            model.setMinimum(new Integer(minVal));
+            model.setMaximum(new Integer(100));
+        }
+        else {
+            //System.out.println("adjustMinMax pt");
+            model.setMinimum(new Integer(minVal));
+            model.setMaximum(new Integer(Integer.MAX_VALUE));
+        }
+        //}
+    }
+
+    /**
+     * get the unit string of this SizeSelectorPanel
+     *
+     * @return the unit string (one of UNIT_PT and UNIT_PERCENT)
+     */
+    public String getUnit() {
+        String unit = "";
+        if (unitSelector != null) {
+            unit = unitSelector.getSelectedItem().toString();
+        }
+        else if (unitName != null) {
+            unit = unitName.getText();
+        }
+        else {
+            unit = UNIT_PT;
+        }
+        if (unit.equalsIgnoreCase(UNIT_PT)) {
+            unit = "";
+        }
+        return unit;
+    }
+
+    public boolean valueChanged() {
+        final Integer value = (Integer) valueSelector.getValue();
+        return ((value.intValue() != originalValue) || (getUnit() != originalUnit));
+    }
+
+    public String getAttr() {
+        final Integer value = (Integer) valueSelector.getValue();
+        final String unit = getUnit();
+        return value.toString() + unit;
+    }
+
+    public Integer getIntValue() {
+        return (Integer) valueSelector.getValue();
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        final SimpleAttributeSet a = new SimpleAttributeSet();
+        final Integer value = getIntValue();
+        final String unit = getUnit();
+        if (valueChanged()) {
+            if (attributeKey instanceof CSS.Attribute) {
+                //a.addAttribute(attributeKey, value.toString() + unit);
+                Util.styleSheet().addCSSAttribute(a, (CSS.Attribute) attributeKey, value.toString() + unit);
+            }
+            else {
+                a.addAttribute(attributeKey, value.toString());
+                if (htmlAttrKey != null) {
+                    a.addAttribute(htmlAttrKey, value.toString());
+                }
+            }
+        }
+        //System.out.println("SizeSelectorPanel getValue()='" + a + "'");
+        return a;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        if (includeUnchanged) {
+            final SimpleAttributeSet a = new SimpleAttributeSet();
+            final Integer value = getIntValue();
+            final String unit = getUnit();
+            if (attributeKey instanceof CSS.Attribute) {
+                //a.addAttribute(attributeKey, value.toString() + unit);
+                Util.styleSheet().addCSSAttribute(a, (CSS.Attribute) attributeKey, value.toString() + unit);
+            }
+            else {
+                a.addAttribute(attributeKey, value.toString());
+                if (htmlAttrKey != null) {
+                    a.addAttribute(htmlAttrKey, value.toString());
+                }
+            }
+            //System.out.println("SizeSelectorPanel getValue()='" + a + "'");
+            return a;
+        }
+        else {
+            return getValue();
+        }
+    }
+
+    public JSpinner getValueSelector() {
+        return valueSelector;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SplashScreen.java b/src/com/lightdev/app/shtm/SplashScreen.java
new file mode 100644
index 0000000..8d4ccc1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SplashScreen.java
@@ -0,0 +1,92 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ * Copyright (C) 2006 Karsten Pawlik
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JWindow;
+
+/**
+ * Class that displays a splash screen
+ * Is run in a separate thread so that the applet continues to load in the background
+ * @author Karsten Pawlik
+ * 
+ */
+public class SplashScreen extends JWindow {
+    private static SplashScreen instance = null;
+    private static int counter;
+
+    private SplashScreen() {
+        try {
+            final JPanel panel = new JPanel(new BorderLayout());
+            final ImageIcon icon = new ImageIcon(SplashScreen.class.getResource(Util.getResourceString("splashImage")));
+            panel.add(new JLabel(icon), BorderLayout.CENTER);
+            panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
+            getContentPane().add(panel);
+            getRootPane().setOpaque(true);
+            pack();
+            final Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
+            setLocation((int) (d.getWidth() - getWidth()) / 2, (int) (d.getHeight() - getHeight()) / 2);
+        }
+        catch (final Exception e) {
+        }
+    }
+
+    /**
+     * Hides the splash screen.
+     */
+    synchronized public static void hideInstance() {
+        if (!Util.getPreference("show_splash_screen", "true").equalsIgnoreCase("true")) {
+            return;
+        }
+        if (counter > 0) {
+            counter--;
+        }
+        if (counter == 0) {
+            instance.setVisible(false);
+        }
+    }
+
+    /**
+     * Shows the splash screen.
+     */
+    synchronized public static void showInstance() {
+        if (!Util.getPreference("show_splash_screen", "true").equalsIgnoreCase("true")) {
+            return;
+        }
+        if (instance == null) {
+            instance = new SplashScreen();
+            counter = 0;
+        }
+        if (counter == 0) {
+            instance.setVisible(true);
+            instance.getRootPane().paintImmediately(0, 0, instance.getWidth(), instance.getHeight());
+        }
+        counter++;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/SplitPanel.java b/src/com/lightdev/app/shtm/SplitPanel.java
new file mode 100644
index 0000000..8d35d8e
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SplitPanel.java
@@ -0,0 +1,312 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.util.prefs.Preferences;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.border.EmptyBorder;
+
+/**
+ * A panel to manage a pluggable panel layout, i.e. around
+ * a center panel, other panels can be placed very similar
+ * to BorderLayout. The difference of this class to BorderLayout is
+ * that it creates JSplitPanes for each panel.
+ *
+ * (Dan: This class is a JPanel somehow trying to achieve what would
+ * better be achieved with Layout. Ideally, it would be removed
+ * altogether.)
+ *
+ * <p>This uses JTabbedPanes for each of the panels surrounding
+ * the center panel.</p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class SplitPanel extends JPanel {
+    /* --------------- class fields start --------------- */
+    /** constant for the major axis being the horizontal one */
+    public static final int MAJOR_AXIS_HORIZONTAL = 1; // NOT SUPPORTED
+    /** constant for the major axis being the vertical one */
+    public static final int MAJOR_AXIS_VERTICAL = 2;
+    /** constant for the north plug-in container of this SplitPanel */
+    public static final int NORTH = 0;
+    /** constant for the east plug-in container of this SplitPanel */
+    public static final int EAST = 1;
+    /** constant for the south plug-in container of this SplitPanel */
+    public static final int SOUTH = 2;
+    /** constant for the west plug-in container of this SplitPanel */
+    public static final int WEST = 3;
+    /** constant for the center panel of this SplitPanel */
+    public static final int CENTER = 4;
+    /** the outer panels of this SplitPanel */
+    private final JSplitPane[] outerPanels;
+    /** current setting for major axis of this SplitPanel */
+    private final int majorAxis = SplitPanel.MAJOR_AXIS_VERTICAL;
+
+    /* ------ class fields end ------------------ */
+    /**
+     * Constructor
+     */
+    public SplitPanel() {
+        super();
+        setLayout(new BorderLayout());
+        final int[] directions = new int[] { NORTH, EAST, SOUTH, WEST };
+        outerPanels = new JSplitPane[directions.length];
+        for (int i = 0; i < directions.length; i++) {
+            outerPanels[directions[i]] = new JSplitPane();
+            outerPanels[directions[i]].setBorder(new EmptyBorder(0, 0, 0, 0));
+            outerPanels[directions[i]].setContinuousLayout(true);
+        }
+        buildLayout();
+        restorePrefs();
+    }
+
+    /**
+     * Sets up the outer panels.
+     */
+    private void buildLayout() {
+        removeAll();
+        outerPanels[NORTH].setOrientation(JSplitPane.VERTICAL_SPLIT);
+        outerPanels[SOUTH].setOrientation(JSplitPane.VERTICAL_SPLIT);
+        outerPanels[WEST].setOrientation(JSplitPane.HORIZONTAL_SPLIT);
+        outerPanels[EAST].setOrientation(JSplitPane.HORIZONTAL_SPLIT);
+        if (majorAxis == SplitPanel.MAJOR_AXIS_VERTICAL) {
+            // [ ALWAYS THE CASE ]
+            //System.out.println("SplitPanel.buildLayout majorAxis = vertical");
+            outerPanels[SOUTH].setTopComponent(outerPanels[NORTH]);
+            outerPanels[WEST].setRightComponent(outerPanels[SOUTH]);
+            outerPanels[EAST].setLeftComponent(outerPanels[WEST]);
+            this.add(outerPanels[EAST], BorderLayout.CENTER);
+        }
+        else {
+            // [ NOT SUPPORTED ]
+            //System.out.println("SplitPanel.buildLayout majorAxis = horizontal");
+            outerPanels[SOUTH].setTopComponent(outerPanels[NORTH]);
+            outerPanels[WEST].setRightComponent(outerPanels[SOUTH]);
+            outerPanels[EAST].setLeftComponent(outerPanels[WEST]);
+            this.add(outerPanels[SOUTH], BorderLayout.CENTER);
+        }
+    }
+
+    /**
+     * Removes panels surrounding the center panel.
+     */
+    public void removeAllOuterPanels() {
+        // Warning: it does not really remove the outer panels per se.
+        JComponent p;
+        if (majorAxis == MAJOR_AXIS_VERTICAL) {
+            p = (JComponent) outerPanels[NORTH].getTopComponent();
+            p.removeAll();
+            p.setVisible(false);
+            p = (JComponent) outerPanels[WEST].getLeftComponent();
+            p.removeAll();
+            p.setVisible(false);
+            p = (JComponent) outerPanels[SOUTH].getBottomComponent();
+            p.removeAll();
+            p.setVisible(false);
+            p = (JComponent) outerPanels[EAST].getRightComponent();
+            p.removeAll();
+            p.setVisible(false);
+        }
+        else {
+            // pending...
+        }
+    }
+
+    /**
+     * Sets the location of a given divider.
+     *
+     * @param panel  the panel to set the location for
+     * @param loc  the relative location of the divider (0, 0.1, ..., 0.9, 1)
+     */
+    public void setDivLoc(final int panel, final double loc) {
+        //System.out.println("SplitPanel.setDivLoc panel=" + panel + ", loc=" + loc);
+        outerPanels[panel].setDividerLocation(loc);
+    }
+
+    /**
+     * Gets the divider location for a given panel.
+     *
+     * @param panel the panel to get the divider location for
+     *
+     * @return the divider location
+     */
+    public int getDivLoc(final int panel) {
+        //System.out.println("SplitPanel.getDivLoc panel=" + panel + ", loc=" + outerPanels[panel].getDividerLocation());
+        return outerPanels[panel].getDividerLocation();
+    }
+
+    /**
+     * Saves divider locations to preferences.
+     */
+    public void savePrefs() {
+        final Preferences prefs = Preferences.userNodeForPackage(getClass());
+        for (int i = 0; i < 4; i++) {
+            prefs.putInt("divLoc" + i, outerPanels[i].getDividerLocation());
+            //System.out.println("SplitPanel.savePrefs divLoc" + i + "=" + outerPanels[i].getDividerLocation());
+        }
+    }
+
+    /**
+     * Restores divider locations from preferences.
+     */
+    public void restorePrefs() {
+        final Preferences prefs = Preferences.userNodeForPackage(getClass());
+        for (int i = 0; i < 4; i++) {
+            outerPanels[i].setDividerLocation(prefs.getInt("divLoc" + i, 300));
+            //System.out.println("SplitPanel.restorePrefs divLoc" + i + "=" + prefs.getInt("divLoc" + i, 300));
+        }
+    }
+
+    /**
+     * Gets the plug-in container for a given panel.
+     *
+     * @param location  the location of the desired container (SplitPanel.NORTH, SOUTH, etc.)
+     *
+     * @return the plug-in container
+     */
+    public JTabbedPane getPanel(final int location) {
+        Component component;
+        switch (location) {
+            case NORTH:
+                component = outerPanels[NORTH].getTopComponent();
+                break;
+            case EAST:
+                component = outerPanels[EAST].getRightComponent();
+                break;
+            case SOUTH:
+                component = outerPanels[SOUTH].getBottomComponent();
+                break;
+            case WEST:
+                component = outerPanels[WEST].getLeftComponent();
+                break;
+            default:
+                component = null;
+        }
+        return (JTabbedPane) component;
+    }
+
+    /**
+     * Shows/hides dividers according to visibility of
+     * their associated plug-in containers.
+     */
+    public void adjustDividerSizes() {
+        JSplitPane splitPane;
+        splitPane = outerPanels[NORTH];
+        if (splitPane.getTopComponent().isVisible()) {
+            //System.out.println("north panel top is visible, showing divider");
+            splitPane.setDividerSize(2);
+        }
+        else {
+            splitPane.setDividerSize(0);
+        }
+        splitPane = outerPanels[WEST];
+        if (splitPane.getLeftComponent().isVisible()) {
+            //System.out.println("west panel left is visible, showing divider");
+            splitPane.setDividerSize(2);
+        }
+        else {
+            splitPane.setDividerSize(0);
+        }
+        splitPane = outerPanels[SOUTH];
+        if (splitPane.getBottomComponent().isVisible()) {
+            //System.out.println("south panel bottom is visible, showing divider");
+            splitPane.setDividerSize(2);
+        }
+        else {
+            splitPane.setDividerSize(0);
+        }
+        splitPane = outerPanels[EAST];
+        if (splitPane.getRightComponent().isVisible()) {
+            //System.out.println("south panel right is visible, showing divider");
+            splitPane.setDividerSize(2);
+        }
+        else {
+            splitPane.setDividerSize(0);
+        }
+    }
+
+    /**
+     * Adds a plug-in container to this SplitPanel ata given location.
+     *
+     * @param c  the plug-in container to add
+     * @param location  the location to add to (SplitPanel.NORTH, SOUTH, etc.)
+     */
+    public void addComponent(final JComponent component, final int location) {
+        if (majorAxis == SplitPanel.MAJOR_AXIS_VERTICAL) {
+            //System.out.println("SplitPanel.addComponent majorAxis = vertical");
+            switch (location) {
+                case CENTER:
+                    //System.out.println("SplitPanel.addComponent CENTER");
+                    outerPanels[NORTH].remove(outerPanels[NORTH].getBottomComponent());
+                    outerPanels[NORTH].setBottomComponent(component);
+                    break;
+                case NORTH:
+                    //System.out.println("SplitPanel.addComponent NORTH");
+                    outerPanels[NORTH].remove(outerPanels[NORTH].getTopComponent());
+                    outerPanels[NORTH].setTopComponent(component);
+                    break;
+                case WEST:
+                    //System.out.println("SplitPanel.addComponent WEST");
+                    outerPanels[WEST].remove(outerPanels[WEST].getLeftComponent());
+                    outerPanels[WEST].setLeftComponent(component);
+                    break;
+                case SOUTH:
+                    //System.out.println("SplitPanel.addComponent SOUTH");
+                    outerPanels[SOUTH].remove(outerPanels[SOUTH].getBottomComponent());
+                    outerPanels[SOUTH].setBottomComponent(component);
+                    break;
+                case EAST:
+                    //System.out.println("SplitPanel.addComponent EAST");
+                    outerPanels[EAST].remove(outerPanels[EAST].getRightComponent());
+                    outerPanels[EAST].setRightComponent(component);
+                    break;
+            }
+        }
+        else {
+            // pending...
+            switch (location) {
+                case CENTER:
+                    break;
+                case NORTH:
+                    break;
+                case WEST:
+                    break;
+                case SOUTH:
+                    break;
+                case EAST:
+                    break;
+            }
+        }
+    }
+}
diff --git a/src/com/lightdev/app/shtm/StylePanel.java b/src/com/lightdev/app/shtm/StylePanel.java
new file mode 100644
index 0000000..8abe9ed
--- /dev/null
+++ b/src/com/lightdev/app/shtm/StylePanel.java
@@ -0,0 +1,107 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JLabel;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+
+/**
+ * Panel to set general text style attributes such as indent or alignment.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class StylePanel extends AttributePanel {
+    public static final int TYPE_PARAGRAPH = 1;
+    public static final int TYPE_TABLE_CELL = 2;
+    private final AttributeComboBox ctAlgn;
+    private final AttributeComboBox cAlgn;
+
+    public StylePanel(final int type) {
+        super();
+        JLabel lb;
+        // have a grid bag layout ready to use
+        final GridBagLayout g = new GridBagLayout();
+        final GridBagConstraints c = new GridBagConstraints();
+        this.setLayout(g);
+        if (type == TYPE_TABLE_CELL) {
+            // background color label
+            lb = new JLabel(Util.getResourceString("tableBgColLabel"));
+            Util.addGridBagComponent(this, lb, g, c, 0, 0, GridBagConstraints.EAST);
+            // background color panel
+            final ColorPanel cp = new ColorPanel(null, Color.white, CSS.Attribute.BACKGROUND_COLOR);
+            Util.addGridBagComponent(this, cp, g, c, 1, 0, GridBagConstraints.WEST);
+        }
+        // text alignment label
+        lb = new JLabel(Util.getResourceString("alignLabel"));
+        Util.addGridBagComponent(this, lb, g, c, 0, 1, GridBagConstraints.EAST);
+        // text align combo box
+        String[] items = new String[] { Util.getResourceString("alignLeft"), Util.getResourceString("alignCenter"),
+                Util.getResourceString("alignRight") };
+        String[] names = new String[] { "left", "center", "right" };
+        ctAlgn = new AttributeComboBox(items, names, CSS.Attribute.TEXT_ALIGN, HTML.Attribute.ALIGN);
+        Util.addGridBagComponent(this, ctAlgn, g, c, 1, 1, GridBagConstraints.WEST);
+        // vertical alignment label
+        lb = new JLabel(Util.getResourceString("valignLabel"));
+        Util.addGridBagComponent(this, lb, g, c, 0, 2, GridBagConstraints.EAST);
+        // vertical alignment combo box
+        items = new String[] { Util.getResourceString("valignTop"), Util.getResourceString("valignMiddle"),
+                Util.getResourceString("valignBottom"), Util.getResourceString("valignBaseline") };
+        names = new String[] { "top", "middle", "bottom", "baseline" };
+        cAlgn = new AttributeComboBox(items, names, CSS.Attribute.VERTICAL_ALIGN, HTML.Attribute.VALIGN);
+        Util.addGridBagComponent(this, cAlgn, g, c, 1, 2, GridBagConstraints.WEST);
+        switch (type) {
+            case TYPE_PARAGRAPH:
+                addSizeSelector(Util.getResourceString("textIndentLabel"), CSS.Attribute.TEXT_INDENT, null, true, g, c);
+                break;
+            case TYPE_TABLE_CELL:
+                addSizeSelector(Util.getResourceString("tableWidthLabel"), CSS.Attribute.WIDTH, HTML.Attribute.WIDTH,
+                    false, g, c);
+                break;
+        }
+    }
+
+    public void reset() {
+        ctAlgn.reset();
+        cAlgn.reset();
+    }
+
+    private void addSizeSelector(final String text, final CSS.Attribute ca, final HTML.Attribute ha,
+                                 final boolean negVals, final GridBagLayout g, final GridBagConstraints c) {
+        // label
+        final JLabel lb = new JLabel(text);
+        Util.addGridBagComponent(this, lb, g, c, 0, 3, GridBagConstraints.EAST);
+        // selector
+        final SizeSelectorPanel ssp = new SizeSelectorPanel(ca, ha, negVals, SizeSelectorPanel.TYPE_COMBO);
+        Util.addGridBagComponent(this, ssp, g, c, 1, 3, GridBagConstraints.WEST);
+    }
+}
diff --git a/src/com/lightdev/app/shtm/StyleSelector.java b/src/com/lightdev/app/shtm/StyleSelector.java
new file mode 100644
index 0000000..f7895e5
--- /dev/null
+++ b/src/com/lightdev/app/shtm/StyleSelector.java
@@ -0,0 +1,147 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.util.Vector;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.HTML;
+
+/**
+ * Component to select styles
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class StyleSelector extends JComboBox implements AttributeComponent, ChangeListener {
+    private final SHTMLPanelImpl shtmlPanel;
+    /** the CSS attribute key this AttributeComponent object represents */
+    private final HTML.Attribute key;
+    /** indicates whether or not to ignore change events */
+    private final boolean ignoreChanges = false;
+    private final String standardStyleName = Util.getResourceString("standardStyleName");
+    private String paragraphType;
+    private boolean updateRunning;
+
+    /**
+     * construct a <code>StyleSelector</code>
+     *
+     * @param key  the attribute this component represents
+     */
+    public StyleSelector(final SHTMLPanelImpl shtmlPanel, final HTML.Attribute key) {
+        this.key = key;
+        this.shtmlPanel = shtmlPanel;
+        updateRunning = false;
+    }
+
+    /**
+     * set the value of this combo box
+     *
+     * @param a  the set of attributes possibly having a
+     *          font size attribute this pick list could display
+     *
+     * @return true, if the set of attributes had a matching attribute,
+     *            false if not
+     */
+    public boolean setValue(final AttributeSet a) {
+        boolean success = false;
+        final Object attr = a.getAttribute(key);
+        if (attr != null) {
+            setSelectedItem(attr.toString());
+            success = true;
+        }
+        else {
+            setSelectedItem(standardStyleName);
+        }
+        return success;
+    }
+
+    /**
+     * get the value of this <code>AttributeComponent</code>
+     *
+     * @return the value selected from this component
+     */
+    public AttributeSet getValue() {
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        set.addAttribute(key, getSelectedItem());
+        return set;
+    }
+
+    public AttributeSet getValue(final boolean includeUnchanged) {
+        return getValue();
+    }
+
+    /* --------------- ChangeListener implementation start --------------- */
+    /**
+     * this method listens and reacts to changes to either the JTabbedPane of FrmMain or
+     * a given StyleSheet this component was registered with. Once either one changes
+     * the list of styles of this componment is refreshed accordingly.
+     */
+    public void stateChanged(final ChangeEvent e) {
+        paragraphType = null;
+        update();
+    }
+
+    /* (non-Javadoc)
+     * @see javax.swing.JComboBox#fireActionEvent()
+     */
+    protected void fireActionEvent() {
+        if (updateRunning) {
+            return;
+        }
+        super.fireActionEvent();
+    }
+
+    public void update() {
+        try {
+            updateRunning = true;
+            final DocumentPane currentDocumentPane = shtmlPanel.getCurrentDocumentPane();
+            final int selectionStart = currentDocumentPane.getEditor().getSelectionStart();
+            final SHTMLDocument document = (SHTMLDocument) currentDocumentPane.getDocument();
+            final String newParagraphType = document.getParagraphElement(selectionStart, true).getName();
+            if (paragraphType == newParagraphType) {
+                return;
+            }
+            paragraphType = newParagraphType;
+            final Vector styleNames = Util.getStyleNamesForTag((document).getStyleSheet(), paragraphType);
+            styleNames.insertElementAt(standardStyleName, 0);
+            setModel(new DefaultComboBoxModel(styleNames));
+        }
+        catch (final NullPointerException ex) {
+            setModel(new DefaultComboBoxModel());
+        }
+        finally {
+            updateRunning = false;
+        }
+    }
+    /* --------------- ChangeListener implementation end ----------------- */
+}
diff --git a/src/com/lightdev/app/shtm/SyntaxPane.java b/src/com/lightdev/app/shtm/SyntaxPane.java
new file mode 100644
index 0000000..c5ab8c7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/SyntaxPane.java
@@ -0,0 +1,335 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002, 2003 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.swing.JEditorPane;
+import javax.swing.JRootPane;
+import javax.swing.SwingUtilities;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyledDocument;
+import javax.swing.text.StyledEditorKit;
+
+/**
+ * An editor pane with syntax highlighting for HTML tags.
+ *
+ * <p>This is a basic approach to syntax highlighting
+ * using regular expressions. It is used to make the plain
+ * HTML view of application SimplyHTML more legible by
+ * separating tags and attributes from content.</p>
+ *
+ * <p>The method doing the actual highlighting work
+ * is put into an implementation of the Runnable interface
+ * so that it can be called without conflicts.</p>
+ *
+ * <p>Can be refined in the way Patterns are set up, i.e.
+ * not hard wire pattern setup and a GUI to let the
+ * use choose styles for patterns.</p>
+ *
+ * <p>Recommended readings:<br>
+ * 'Regular Expressions and the JavaTM Programming Language' at<br>
+ * <a href="http://developer.java.sun.com/developer/technicalArticles/releases/1.4regex/" target="_blank">http://developer.java.sun.com/developer/technicalArticles/releases/1.4regex/</a><br>
+ * and<br>
+ * Presentation slides 'Rich Clients for Web Services' from JavaOne 2002 at<br>
+ * <a href="http://servlet.java.sun.com/javaone/resources/content/sf2002/conf/sessions/pdfs/2274.pdf" target="_blank">http://servlet.java.sun.com/javaone/resources/content/sf2002/conf/sessions/pdfs/2274.pdf</a>
+ * </p>
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ *
+ */
+class SyntaxPane extends JEditorPane implements CaretListener {
+    /**
+     * Creates a new <code>SyntaxPane</code>.
+     */
+    public SyntaxPane() {
+        super();
+        setEditorKit(new StyledEditorKit());
+        setupPatterns();
+    }
+
+    /**
+     * set up HTML patterns and attributes
+     */
+    private void setupPatterns() {
+        Pattern p;
+        SimpleAttributeSet set;
+        patterns = new Vector();
+        // content text
+        p = Pattern.compile("\\b\\w+");
+        set = new SimpleAttributeSet();
+        StyleConstants.setForeground(set, Color.BLACK);
+        StyleConstants.setBold(set, false);
+        patterns.addElement(new RegExStyle(p, set));
+        // a tag
+        p = Pattern.compile("<[/a-zA-Z0-9\\s]+");
+        set = new SimpleAttributeSet();
+        StyleConstants.setForeground(set, new Color(0, 0, 128));
+        StyleConstants.setBold(set, true);
+        patterns.addElement(new RegExStyle(p, set));
+        // a tag end
+        p = Pattern.compile(">");
+        patterns.addElement(new RegExStyle(p, set));
+        // an attribute
+        p = Pattern.compile("\\s[/a-zA-Z0-9]+=");
+        set = new SimpleAttributeSet();
+        StyleConstants.setForeground(set, new Color(158, 119, 0));
+        StyleConstants.setBold(set, true);
+        patterns.addElement(new RegExStyle(p, set));
+        // attribute values
+        p = Pattern.compile("\"[\\x2D;:/.%#?=,\\w\\s]+\"");
+        set = new SimpleAttributeSet();
+        StyleConstants.setForeground(set, Color.BLUE);
+        StyleConstants.setBold(set, false);
+        patterns.addElement(new RegExStyle(p, set));
+    }
+
+    /**
+     * apply syntax highlighting to all HTML tags found in the given
+     * area of the given document
+     *
+     * @param doc  the document to apply syntax highlighting to
+     * @param offset  the position inside the given document to start to apply syntax highlighting to
+     * @param len  the number of characters to apply syntax highlighting to
+     */
+    public void setMarks(final StyledDocument sDoc, final int offset, final int len) {
+        SwingUtilities.invokeLater(new StyleUpdater(this, sDoc, offset, len));
+    }
+
+    /**
+     * overridden from JEditorPane
+     * to suppress line wraps
+     *
+     * @see setSize
+     */
+    public boolean getScrollableTracksViewportWidth() {
+        return false;
+    }
+
+    /**
+     * overridden from JEditorPane
+     * to suppress line wraps
+     *
+     * @see getScrollableTracksViewportWidth
+     */
+    public void setSize(final Dimension d) {
+        if (d.width < getParent().getSize().width) {
+            d.width = getParent().getSize().width;
+        }
+        super.setSize(d);
+    }
+
+    /**
+     * display a wait cursor for lengthy operations
+     */
+    private void cursor() {
+        final JRootPane rootPane = getRootPane();
+        if (rootPane != null) {
+            final Component gp = rootPane.getGlassPane();
+            if (!gp.isVisible()) {
+                gp.setCursor(waitCursor);
+                gp.setVisible(true);
+            }
+            else {
+                gp.setVisible(false);
+            }
+        }
+    }
+
+    /**
+     * StyleUpdater does the actual syntax highlighting work
+     * and can be used in SwingUtilities.invokeLater()
+     */
+    private class StyleUpdater implements Runnable {
+        /**
+         * construct a <code>StyleUpdater</code>
+         *
+         * @param sp  the SyntaxPane this StyleUpdater works on
+         * @param doc  the document to apply syntax highlighting to
+         * @param offset  the position inside the given document to start to apply syntax highlighting to
+         * @param len  the number of characters to apply syntax highlighting to
+         */
+        public StyleUpdater(final SyntaxPane sp, final StyledDocument doc, final int offset, final int len) {
+            sDoc = doc;
+            this.offset = offset;
+            this.len = len;
+            this.sp = sp;
+        }
+
+        /**
+         * apply snytax highlighting
+         */
+        public void run() {
+            Matcher m;
+            RegExStyle style;
+            cursor();
+            sp.removeCaretListener(sp);
+            try {
+                final int length = sDoc.getLength();
+                if (length > 0 && len > 0) {
+                    final String text = sDoc.getText(offset, len);
+                    if (text != null && text.length() > 0) {
+                        final Enumeration pe = patterns.elements();
+                        while (pe.hasMoreElements()) {
+                            style = (RegExStyle) pe.nextElement();
+                            m = style.getPattern().matcher(text);
+                            while (m.find()) {
+                                sDoc.setCharacterAttributes(offset + m.start(), m.end() - m.start(), style.getStyle(),
+                                    true);
+                            }
+                        }
+                    }
+                }
+            }
+            catch (final Exception ex) {
+                System.out.println("StyleUpdater ERROR: " + ex.getMessage());
+            }
+            sp.addCaretListener(sp);
+            cursor();
+        }
+
+        /** the document to apply syntax highlighting to */
+        private final StyledDocument sDoc;
+        /** the position inside the given document to start to apply syntax highlighting to */
+        private final int offset;
+        /** the number of characters to apply syntax highlighting to */
+        private final int len;
+        /** the SyntaxPane this StyleUpdater works on */
+        private final SyntaxPane sp;
+    }
+
+    /**
+     * CaretListener implementation
+     *
+     * <p>updates syntax highlighting for the current line
+     * when the caret moves</p>
+     */
+    public void caretUpdate(final CaretEvent e) {
+        try {
+            final StyledDocument sDoc = (StyledDocument) getDocument();
+            final int cPos = e.getDot();
+            final int length = sDoc.getLength();
+            final String text = sDoc.getText(0, length);
+            final int lineStart = text.substring(0, cPos).lastIndexOf("\n") + 1;
+            int lineEnd = text.indexOf("\n", cPos);
+            if (lineEnd < 0) {
+                lineEnd = length;
+            }
+            setMarks(sDoc, lineStart, lineEnd - lineStart);
+        }
+        catch (final Exception ex) {
+        }
+    }
+
+    /**
+     * overridden to keep caret changes during the initial text load
+     * from triggering syntax highlighting repetitively
+     */
+    public void setText(final String t) {
+        removeCaretListener(this);
+        super.setText(t);
+        final StyledDocument sDoc = (StyledDocument) getDocument();
+        setMarks(sDoc, 0, sDoc.getLength());
+        setCaretPosition(0);
+        addCaretListener(this);
+    }
+
+    /**
+     * convenience class associating a pattern with a
+     * set of attributes
+     */
+    class RegExStyle {
+        /**
+         * construct a <code>RegExStyle</code> instance
+         *
+         * @param p  the <code>Pattern</code> to apply this style to
+         * @param a  the attributes making up this style
+         */
+        public RegExStyle(final Pattern p, final AttributeSet a) {
+            this.p = p;
+            this.a = a;
+        }
+
+        /**
+         * get the <code>Pattern</code> this style is to be applied to
+         *
+         * @return the Pattern
+         */
+        public Pattern getPattern() {
+            return p;
+        }
+
+        /**
+         * get the attributes making up this style
+         *
+         * @return the set of attributes
+         */
+        public AttributeSet getStyle() {
+            return a;
+        }
+
+        /**
+         * set the Pattern to apply a given set of attributes to
+         *
+         * @param p  the Pattern
+         */
+        public void setPattern(final Pattern p) {
+            this.p = p;
+        }
+
+        /**
+         * set the set of attributes to apply to a given Pattern
+         *
+         * @param a  the set of attributes to use
+         */
+        public void setStyle(final AttributeSet a) {
+            this.a = a;
+        }
+
+        /** the Pattern to apply this style to */
+        private Pattern p;
+        /** the attributes making up this style */
+        private AttributeSet a;
+    }
+
+    /** Patterns registered with this SnytaxPane */
+    private Vector patterns;
+    /** the cursor to use to indicate a lengthy operation is going on */
+    private final Cursor waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
+}
diff --git a/src/com/lightdev/app/shtm/TableDialog.java b/src/com/lightdev/app/shtm/TableDialog.java
new file mode 100644
index 0000000..4b638ee
--- /dev/null
+++ b/src/com/lightdev/app/shtm/TableDialog.java
@@ -0,0 +1,224 @@
+/*
+* SimplyHTML, a word processor based on Java, HTML and CSS
+* Copyright (C) 2002 Ulrich Hilger
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.CSS;
+import javax.swing.text.html.HTML;
+
+/**
+ * Dialog to manipulate HTML table attributes.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class TableDialog extends DialogShell {
+    /** collection of all components with table related attributes */
+    Vector tableComponents = new Vector();
+    /** collection of all components with cell related attributes */
+    Vector cellComponents = new Vector();
+    /** selector for cell range to apply cell attributes to */
+    JComboBox cellRange;
+
+    /**
+     * constructor
+     *
+     * @param parent  the main frame having the TextResources
+     * @param title  the title for this dialog
+     * @param a  the set of attributes to show and manipulate
+     */
+    public TableDialog(final Frame parent, final String title) {
+        super(parent, title);
+        // add to content pane of DialogShell
+        final Container contentPane = super.getContentPane();
+        contentPane.add(buildTablePanel(), BorderLayout.NORTH);
+        contentPane.add(buildCellPanel(), BorderLayout.CENTER);
+        // cause optimal placement of all elements
+        pack();
+    }
+
+    public void setTableAttributes(final AttributeSet a) {
+        setComponentAttributes(tableComponents, a);
+    }
+
+    public void setCellAttributes(final AttributeSet a) {
+        setComponentAttributes(cellComponents, a);
+    }
+
+    public void setComponentAttributes(final Vector v, final AttributeSet a) {
+        final Enumeration components = v.elements();
+        AttributeComponent ac;
+        while (components.hasMoreElements()) {
+            ac = (AttributeComponent) components.nextElement();
+            ac.setValue(a);
+        }
+    }
+
+    /**
+     * get the set of attributes resulting from the settings on
+     * this TableDialog.
+     *
+     * @return the set of attributes set in this TableDialog
+     */
+    public AttributeSet getTableAttributes() {
+        return getComponentAttributes(tableComponents);
+    }
+
+    public AttributeSet getCellAttributes() {
+        //System.out.println("TableDialog getCellattributes=" + getComponentAttributes(cellComponents));
+        return getComponentAttributes(cellComponents);
+    }
+
+    private AttributeSet getComponentAttributes(final Vector v) {
+        final SimpleAttributeSet attributes = new SimpleAttributeSet();
+        final Enumeration components = v.elements();
+        AttributeComponent ac;
+        while (components.hasMoreElements()) {
+            ac = (AttributeComponent) components.nextElement();
+            //System.out.println(ac.getValue());
+            attributes.addAttributes(ac.getValue());
+        }
+        return attributes;
+    }
+
+    /**
+     * build the contents of the cell panel
+     *
+     * this is moved to a separate method to make the code more
+     * legible.
+     */
+    private JPanel buildCellPanel() {
+        new GridBagLayout();
+        new GridBagConstraints();
+        // construct cell format panel
+        final JPanel cellPanel = new JPanel(new BorderLayout());
+        cellPanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("cellPanelTitle")));
+        // construct tabbed pane for various cell settings
+        final JTabbedPane tp = new JTabbedPane();
+        tp.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
+        // add general panel to tabbed pane
+        final StylePanel sp = new StylePanel(StylePanel.TYPE_TABLE_CELL);
+        cellComponents.add(sp);
+        tp.add(Util.getResourceString("cellGenTabLabel"), sp);
+        // add padding panel to cell components and tabbed pane
+        final MarginPanel mp = new MarginPanel();
+        cellComponents.add(mp);
+        tp.add(Util.getResourceString("cellMarginTabLabel"), mp);
+        // construct border panel
+        final BorderPanel bPanel = new BorderPanel();
+        // add border width panel and border color panel to cell components
+        cellComponents.add(bPanel);
+        // add border panel to tabbed pane
+        tp.add(Util.getResourceString("cellBorderTabLabel"), bPanel);
+        // create cell range panel
+        final JPanel crPanel = new JPanel();
+        final String[] cellRangeSelection = new String[] { Util.getResourceString("thisCellRangeLabel"),
+                Util.getResourceString("thisColRangeLabel"), Util.getResourceString("thisRowRangeLabel"),
+                Util.getResourceString("allCellsRangeLabel") };
+        crPanel.add(new JLabel(Util.getResourceString("applyCellAttrLabel")));
+        cellRange = new JComboBox(cellRangeSelection);
+        crPanel.add(cellRange);
+        // get the preferred size of the tabbed pane
+        /*
+        int lastTabIndex = tp.getTabCount() - 1;
+        Rectangle tabRect = tp.getBoundsAt(lastTabIndex);
+        int prefWidth = tabRect.x + tabRect.width + 30;
+        tp.setPreferredSize(new Dimension(prefWidth, 300));
+        */
+        // add tabbed pane and range selector to cell panel
+        cellPanel.add(tp, BorderLayout.CENTER);
+        cellPanel.add(crPanel, BorderLayout.SOUTH);
+        return cellPanel;
+    }
+
+    /**
+     * get the range of cells to apply cell attributes to
+     */
+    public int getCellRange() {
+        return cellRange.getSelectedIndex();
+    }
+
+    /**
+     * build the contents of the table panel
+     *
+     * this is moved to a separate method to make the code more
+     * legible.
+     */
+    private JPanel buildTablePanel() {
+        // layout and constraints to use
+        final GridBagLayout g = new GridBagLayout();
+        final GridBagConstraints c = new GridBagConstraints();
+        // table panel
+        final JPanel tablePanel = new JPanel(g);
+        tablePanel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Util
+            .getResourceString("tablePanelTitle")));
+        // table width label
+        JLabel lb = new JLabel(Util.getResourceString("tableWidthLabel"));
+        Util.addGridBagComponent(tablePanel, lb, g, c, 0, 0, GridBagConstraints.EAST);
+        // table width combo box
+        final SizeSelectorPanel ssp = new SizeSelectorPanel(CSS.Attribute.WIDTH, HTML.Attribute.WIDTH, false,
+            SizeSelectorPanel.TYPE_COMBO);
+        Util.addGridBagComponent(tablePanel, ssp, g, c, 1, 0, GridBagConstraints.WEST);
+        tableComponents.addElement(ssp);
+        // table background color label
+        lb = new JLabel(Util.getResourceString("tableBgColLabel"));
+        Util.addGridBagComponent(tablePanel, lb, g, c, 0, 1, GridBagConstraints.EAST);
+        // table background color panel
+        final ColorPanel cp = new ColorPanel(null, Color.white, CSS.Attribute.BACKGROUND_COLOR);
+        Util.addGridBagComponent(tablePanel, cp, g, c, 1, 1, GridBagConstraints.WEST);
+        tableComponents.addElement(cp);
+        // table alignment label
+        lb = new JLabel(Util.getResourceString("alignLabel"));
+        Util.addGridBagComponent(tablePanel, lb, g, c, 0, 2, GridBagConstraints.EAST);
+        // table alignment combo box
+        final String[] items = new String[] { Util.getResourceString("alignLeft"),
+                Util.getResourceString("alignCenter"), Util.getResourceString("alignRight") };
+        final String[] names = new String[] { "left", "center", "right" };
+        final AttributeComboBox tAlgn = new AttributeComboBox(items, names, CSS.Attribute.TEXT_ALIGN,
+            HTML.Attribute.ALIGN);
+        Util.addGridBagComponent(tablePanel, tAlgn, g, c, 1, 2, GridBagConstraints.WEST);
+        tableComponents.addElement(tAlgn);
+        return tablePanel;
+    }
+}
diff --git a/src/com/lightdev/app/shtm/TagSelector.java b/src/com/lightdev/app/shtm/TagSelector.java
new file mode 100644
index 0000000..6e56613
--- /dev/null
+++ b/src/com/lightdev/app/shtm/TagSelector.java
@@ -0,0 +1,108 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.util.Vector;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.text.html.HTML;
+
+/**
+ * Component to select a tag, extending JComboBox.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class TagSelector extends JComboBox {
+    /** table with available tags to select */
+    private final Vector tags = new Vector();
+    /** table with tag names corresponding to tags */
+    private final Vector tagNames = new Vector();
+
+    /**
+     * construct a new TagSelector
+     */
+    public TagSelector() {
+        super();
+        initTags();
+        setModel(new DefaultComboBoxModel(tagNames));
+    }
+
+    /**
+     * Gets the name of the tag that is currently selected.
+     *
+     * @return the tag name
+     */
+    public String getSelectedTag() {
+        return (String) tags.elementAt(getSelectedIndex());
+    }
+
+    /**
+     * get the list of tags selectable through this component
+     *
+     * @return a Vector of tags available from this component
+     */
+    public Vector getTags() {
+        return tags;
+    }
+
+    /**
+     * set the tag that is to be shown in this component
+     *
+     * @param tag  the name of the tag to show
+     */
+    public void setSelectedTag(final String tag) {
+        final int index = tags.indexOf(tag);
+        if (index > -1) {
+            setSelectedIndex(tags.indexOf(tag));
+        }
+        else {
+            setSelectedIndex(0);
+        }
+    }
+
+    /**
+     * initialize content types hashtable
+     */
+    private void initTags() {
+        tags.addElement(HTML.Tag.P.toString());
+        tags.addElement(HTML.Tag.H1.toString());
+        tags.addElement(HTML.Tag.H2.toString());
+        tags.addElement(HTML.Tag.H3.toString());
+        tags.addElement(HTML.Tag.H4.toString());
+        tags.addElement(HTML.Tag.H5.toString());
+        tags.addElement(HTML.Tag.H6.toString());
+        tagNames.addElement(Util.getResourceString("cTagNamePara"));
+        tagNames.addElement(Util.getResourceString("cTagNameHead1"));
+        tagNames.addElement(Util.getResourceString("cTagNameHead2"));
+        tagNames.addElement(Util.getResourceString("cTagNameHead3"));
+        tagNames.addElement(Util.getResourceString("cTagNameHead4"));
+        tagNames.addElement(Util.getResourceString("cTagNameHead5"));
+        tagNames.addElement(Util.getResourceString("cTagNameHead6"));
+    }
+}
diff --git a/src/com/lightdev/app/shtm/TextResources.java b/src/com/lightdev/app/shtm/TextResources.java
new file mode 100644
index 0000000..bb44b0f
--- /dev/null
+++ b/src/com/lightdev/app/shtm/TextResources.java
@@ -0,0 +1,30 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Created on 09.11.2006
+ * Copyright (C) 2006 Dimitri Polivaev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+/**
+ * interface for getting text based resources
+ * 
+ *  * @author Dimitri Polivaev
+ * 14.01.2007
+ */
+public interface TextResources {
+    String getString(String pKey);
+}
diff --git a/src/com/lightdev/app/shtm/TitledPickList.java b/src/com/lightdev/app/shtm/TitledPickList.java
new file mode 100644
index 0000000..35fabcf
--- /dev/null
+++ b/src/com/lightdev/app/shtm/TitledPickList.java
@@ -0,0 +1,256 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.BorderLayout;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.EventObject;
+import java.util.Vector;
+
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.ListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+/**
+ * A pick list typically being used in font dialogs, consisting
+ * of a list title, a text field for the currently selected
+ * value and the actual pick list containing all possible values.
+ *
+ * As three different lists are needed in our font panel for
+ * family, style and size, its quite handy to have the code
+ * making up such a component in a separate class only once.
+ *
+ * As well in a separate class it is easier to implement the
+ * special 'behaviour', i.e. when list is clicked, the value
+ * of the text field is set accordingly and when a value is
+ * typed in the text field, the value in the list changes
+ * accordingly.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+class TitledPickList extends JPanel implements ListSelectionListener, CaretListener, FocusListener, KeyListener {
+    /** the chosen list entry */
+    private final JTextField choice;
+    boolean ignoreTextChanges = false;
+    /** the list having all possible entries */
+    private final JList optionsList;
+
+    /**
+     * constructor
+     *
+     * @param options  the options to be selectable in this list
+     * @param titleText  the title for the pick list
+     */
+    public TitledPickList(final String[] options, final String titleText) {
+        super(new BorderLayout());
+        choice = new JTextField();
+        choice.addCaretListener(this);
+        choice.addFocusListener(this);
+        choice.addKeyListener(this);
+        optionsList = new JList(options);
+        optionsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        optionsList.addListSelectionListener(this);
+        final JScrollPane scrollableList = new JScrollPane(optionsList);
+        final JPanel pickListPanel = new JPanel(new BorderLayout());
+        pickListPanel.add(choice, BorderLayout.NORTH);
+        pickListPanel.add(scrollableList, BorderLayout.CENTER);
+        final JLabel title = new JLabel();
+        title.setText(titleText);
+        add(title, BorderLayout.NORTH);
+        add(pickListPanel, BorderLayout.CENTER);
+    }
+
+    /**
+     * if the caret was updated, i.e. the user typed into
+     * the text field, try to find a font family name starting
+     * with what was typed so far, set the list to that family
+     */
+    public void caretUpdate(final CaretEvent ce) {
+        if (!ignoreTextChanges) {
+            if (choice.hasFocus()) {
+                final ListModel model = optionsList.getModel();
+                final String key = choice.getText().toLowerCase();
+                if (key != null) {
+                    int i = 0;
+                    final int modelSize = model.getSize();
+                    String listEntry = (String) model.getElementAt(i);
+                    while (++i < modelSize && !listEntry.toLowerCase().startsWith(key)) {
+                        listEntry = (String) model.getElementAt(i);
+                    }
+                    if (i < modelSize) {
+                        optionsList.setSelectedValue(listEntry, true);
+                    }
+                }
+            }
+        }
+    }
+
+    /** for FocusListener implementation, but unused here */
+    public void focusGained(final FocusEvent e) {
+    }
+
+    /**
+     * put the currently selected value in the list
+     * into the text field when user leaves field
+     */
+    public void focusLost(final FocusEvent e) {
+        updateTextFromList();
+    }
+
+    /**
+     * put the currently selected value in the list
+     * into the text field when user pressed enter in field
+     */
+    public void keyPressed(final KeyEvent e) {
+        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+            updateTextFromList();
+        }
+    }
+
+    /** for KeyListener implementation, but unused here */
+    public void keyReleased(final KeyEvent e) {
+    }
+
+    /** for KeyListener implementation, but unused here */
+    public void keyTyped(final KeyEvent e) {
+    }
+
+    /** put selected value into text field */
+    private void updateTextFromList() {
+        final Object value = optionsList.getSelectedValue();
+        if (value != null) {
+            choice.setText(value.toString());
+        }
+    }
+
+    /**
+     * get the value selected from the pick list
+     *
+     * @return the selected value or null if nothing is selected
+     */
+    public Object getSelection() {
+        return optionsList.getSelectedValue();
+    }
+
+    /**
+     * set the value selected in the pick list
+     *
+     * @param value  the value to be selected in the list
+     */
+    public void setSelection(final Object value) {
+        optionsList.setSelectedValue(value.toString(), true);
+        updateTextFromList();
+    }
+
+    /**
+     * set the selected index in the pick list
+     *
+     * @param index  the index of the value to be selected in the list
+     */
+    public void setSelection(final int index) {
+        optionsList.setSelectedIndex(index);
+        updateTextFromList();
+    }
+
+    /**
+     * get the index of the value selected in the pick list
+     *
+     * @return the index of the selected value or -1 if none is selected
+     */
+    public int getIndex() {
+        return optionsList.getSelectedIndex();
+    }
+
+    /**
+     * if another value was picked from the list, set the
+     * textfield according to the choice and update the
+     * sample
+     */
+    public void valueChanged(final ListSelectionEvent e) {
+        if (optionsList.hasFocus()) {
+            updateTextFromList();
+        }
+        fireValueChanged();
+    }
+
+    /* ------------- event handling start ------------ */
+    /** the listeners for TitledPickkListEvents */
+    private final Vector listeners = new Vector(0);
+
+    /**
+     * add an event listener.
+     *
+     * @param  listener  the event listener to add
+     */
+    public void addTitledPickListListener(final TitledPickListListener listener) {
+        listeners.addElement(listener);
+    }
+
+    /**
+     * remove an event listener.
+     *
+     * @param  listener  the event listener to remove
+     */
+    public void removeTitledPickListListener(final TitledPickListListener listener) {
+        listeners.removeElement(listener);
+    }
+
+    /** fire a value changed event to all registered listeners */
+    void fireValueChanged() {
+        final Enumeration listenerList = listeners.elements();
+        while (listenerList.hasMoreElements()) {
+            ((TitledPickListListener) listenerList.nextElement()).valueChanged(new TitledPickListEvent(this));
+        }
+    }
+
+    /** the event object definition for ColorPanels */
+    class TitledPickListEvent extends EventObject {
+        public TitledPickListEvent(final Object source) {
+            super(source);
+        }
+    }
+
+    /** the event listener definition for ColorPanels */
+    interface TitledPickListListener extends EventListener {
+        public void valueChanged(TitledPickListEvent e);
+    }
+    /* ------------- event handling end ------------ */
+}
diff --git a/src/com/lightdev/app/shtm/Util.java b/src/com/lightdev/app/shtm/Util.java
new file mode 100644
index 0000000..cf42673
--- /dev/null
+++ b/src/com/lightdev/app/shtm/Util.java
@@ -0,0 +1,986 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2002 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+package com.lightdev.app.shtm;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Point;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.prefs.Preferences;
+
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Element;
+import javax.swing.text.ElementIterator;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.StyleSheet;
+
+/**
+ * Utility methods for application SimplyHTML.
+ *
+ * @author Ulrich Hilger
+ * @author Light Development
+ * @author <a href="http://www.lightdev.com">http://www.lightdev.com</a>
+ * @author <a href="mailto:info at lightdev.com">info at lightdev.com</a>
+ * @author published under the terms and conditions of the
+ *      GNU General Public License,
+ *      for details see file gpl.txt in the distribution
+ *      package of this software
+ *
+ * 
+ */
+public class Util {
+    /* some constants */
+    public static final String JAR_PREFIX = "jar:";
+    public static final String JAR_EXTENSION = ".jar";
+    public static final String FILE_PREFIX = "file:";
+    public static final String CLASS_EXT = ".class";
+    public static final String JAR_SEPARATOR = "!/";
+    public static final String URL_SEPARATOR = "/";
+    public static final char URL_SEPARATOR_CHAR = '/';
+    public static final String CLASS_SEPARATOR = ".";
+    public static final char CLASS_SEPARATOR_CHAR = '.';
+    public static final String DIR_UP_INDICATOR = "..";
+    public static final String RELATIVE_PREFIX = "../";
+    public static final String PROTOCOL_SEPARATOR = ":";
+    public static final String ANCHOR_SEPARATOR = "#";
+    public static final String pct = "%";
+    public static final String pt = "pt";
+    public static final String px = "px";
+    /** the default block size in bytes for file operations */
+    private static int blockSize = 1024;
+    private static Vector startTimes = new Vector();
+    private static final String ERR_TITLE = "Error";
+    private static String unit = "";
+    /** a style sheet instanciated once for access to its utility methods */
+    private static StyleSheet s = new StyleSheet();
+    /* CSS Attribute constants */
+    public static final String CSS_ATTRIBUTE_NORMAL = "normal";
+    public static final String CSS_ATTRIBUTE_UNDERLINE = "underline";
+    public static final String CSS_ATTRIBUTE_LINE_THROUGH = "line-through";
+    public static final String CSS_ATTRIBUTE_NONE = "none";
+    public static final String CSS_ATTRIBUTE_ALIGN_LEFT = "left";
+    public static final String CSS_ATTRIBUTE_ALIGN_CENTER = "center";
+    public static final String CSS_ATTRIBUTE_ALIGN_RIGHT = "right";
+
+    public Util() {
+    }
+
+    /**
+     * rename a file to have a given extension
+     *
+     * @param from  the file to rename
+     * @param newExt  the new extension the file shall have
+     *
+     * @return the renamed file
+     */
+    public static File renameFile(final File from, final String newExt) {
+        final String fileName = Util.removeExtension(from.getName());
+        final String saveFileName = from.getParentFile().getAbsolutePath() + File.separator + fileName + newExt;
+        final File newFile = new File(saveFileName);
+        from.renameTo(newFile);
+        return newFile;
+    }
+
+    /**
+     * find the next link attribute from a given element upwards
+     * through the element hierarchy
+     *
+     * @param elem  the element to start looking at
+     *
+     * @return the link attribute found, or null, if none was found
+     */
+    public static Object findLinkUp(Element elem) {
+        //Element elem = ((SHTMLDocument) doc).getCharacterElement(selStart);
+        Object linkAttr = null; //elem.getAttributes().getAttribute(HTML.Tag.A);
+        Object href = null;
+        while ((elem != null) && (linkAttr == null)) {
+            linkAttr = elem.getAttributes().getAttribute(HTML.Tag.A);
+            if (linkAttr != null) {
+                href = ((AttributeSet) linkAttr).getAttribute(HTML.Attribute.HREF);
+            }
+            elem = elem.getParentElement();
+        }
+        if (linkAttr != null && href != null) {
+            return linkAttr;
+        }
+        else {
+            return null;
+        }
+    }
+
+    /**
+     * remove the extension from a file name
+     *
+     * @param  fileName  the file name to remove the extension from
+     *
+     * @return the file name without extension
+     */
+    public static String removeExtension(final String fileName) {
+        String newName = fileName;
+        final int pos = newName.lastIndexOf(".");
+        if (pos > -1) {
+            newName = fileName.substring(0, pos);
+        }
+        return newName;
+    }
+
+    /**
+     * resolve sets of attributes that are recursively stored in each other
+     *
+     * @param style  the set of attributes containing other sets of attributes
+     */
+    public static AttributeSet resolveAttributes(final AttributeSet style) {
+        final SimpleAttributeSet set = new SimpleAttributeSet();
+        if (style != null) {
+            final Enumeration names = style.getAttributeNames();
+            Object value;
+            Object key;
+            while (names.hasMoreElements()) {
+                key = names.nextElement();
+                //System.out.println("Util resolveAttributes key=" + key);
+                value = style.getAttribute(key);
+                //System.out.println("Util resolveAttributes value=" + value);
+                if ((!key.equals(StyleConstants.NameAttribute)) && (!key.equals(StyleConstants.ResolveAttribute))
+                        && (!key.equals(AttributeSet.ResolveAttribute)) && (!key.equals(AttributeSet.NameAttribute))) {
+                    set.addAttribute(key, value);
+                }
+                else {
+                    if (key.equals(StyleConstants.ResolveAttribute) || key.equals(AttributeSet.ResolveAttribute)) {
+                        //System.out.println("Util resolveAttributes resolving key=" + key);
+                        set.addAttributes(Util.resolveAttributes((AttributeSet) value));
+                    }
+                }
+            }
+        }
+        return set;
+    }
+
+    /**
+     * get a name by asking from the user
+     *
+     * <p>Wrapper for JOptionPane with I18N support</p>
+     *
+     * @param initialName  the name initially shown in option pane
+     * @param title  the title to be shown in the option pane
+     * @param text  the text to be shown in the option pane
+     *
+     * @return the entered name or null if action was cancelled
+     */
+    public static String nameInput(final Frame parent, final String initialName, final String regex,
+                                   final String title, final String text) {
+        String name;
+        do {
+            final Object input = JOptionPane.showInputDialog(null, Util.getResourceString(text),
+                Util.getResourceString(title), JOptionPane.QUESTION_MESSAGE, null, null, initialName);
+            name = input == null ? null : input.toString();
+        } while (name != null && !name.matches(regex));
+        return name;
+    }
+
+    /**
+     * Show a message with options to choose from
+     *
+     * <p>Wrapper for JOptionPane with I18N support</p>
+     *
+     * @param options  the options to be shown in the dialog
+     * @param title  the title to be shown in the dialog
+     * @param msg  the message to be shown in the dialog
+     * @param item  a variable part to be shown before msg
+     * @param sep  a separator for msg and item (return or blank etc.)
+     *
+     * @return the choice
+     */
+    public static int msgChoice(final int options, final String title, final String msg, final String item,
+                                final String sep) {
+        final String message = item + sep + Util.getResourceString(msg);
+        return JOptionPane.showConfirmDialog(null, message, Util.getResourceString(title), options,
+            JOptionPane.QUESTION_MESSAGE);
+    }
+
+    /**
+     * Show a message with options to choose from
+     *
+     * <p>Wrapper for JOptionPane with I18N support</p>
+     *
+     * @param options  the options to be shown in the dialog
+     * @param title  the title to be shown in the dialog
+     * @param msg  the message to be shown in the dialog
+     * @param item  a variable part to be shown before msg
+     * @param sep  a separator for msg and item (return or blank etc.)
+     *
+     * @return true, if YES was chosen, false if not
+     */
+    public static boolean msg(final int options, final String title, final String msg, final String item,
+                              final String sep) {
+        return (Util.msgChoice(options, title, msg, item, sep) == JOptionPane.YES_OPTION);
+    }
+
+    /**
+     * get names of all styles for a given tag
+     *
+     * @param styles  the style sheet to look for style names
+     * @param tag  the tag to find style names for
+     *
+     * @return a Vector with all style names found
+     */
+    public static Vector getStyleNamesForTag(final StyleSheet styles, final String tag) {
+        return Util.getStyleClassVector(tag, styles.getStyleNames());
+    }
+
+    /**
+     * get names of all styles for a given tag
+     *
+     * @param styles  the style sheet to look for style names
+     * @param tag  the tag to find style names for
+     *
+     * @return a Vector with all style names found
+     */
+    public static Vector getStyleNamesForTag(final AttributeSet styles, final String tag) {
+        return Util.getStyleClassVector(tag, styles.getAttributeNames());
+    }
+
+    private static Vector getStyleClassVector(final String tag, final Enumeration e) {
+        String name;
+        final Vector v = new Vector(0);
+        while (e.hasMoreElements()) {
+            name = (String) e.nextElement();
+            if (name.toLowerCase().startsWith(tag + ".")) {
+                //System.out.println("getStyleClassVector adding name '" + name + "'");
+                v.addElement(name.substring(2));
+            }
+        }
+        return v;
+    }
+
+    /**
+     * get the names of all styles found in a given StyleSheet
+     *
+     * @param styles  the StyleSheet to look for style names
+     *
+     * @return a Vector with all names found
+     */
+    public static Vector getStyleNames(final StyleSheet styles) {
+        final Vector styleNames = new Vector(0);
+        try {
+            final Enumeration rules = styles.getStyleNames();
+            while (rules.hasMoreElements()) {
+                styleNames.addElement(rules.nextElement());
+            }
+        }
+        catch (final Exception ee) {
+            Util.errMsg(null, ee.getMessage(), ee);
+        }
+        return styleNames;
+    }
+
+    /**
+     * delete a directory with all its contents
+     *
+     * <p>CAUTION: This method deletes all content of the given
+     * directory including all subdirectories and their conent</p>
+     *
+     * @param dir the directory to delete
+     */
+    public static void deleteDir(final File dir) {
+        if (dir.exists()) {
+            final File[] list = dir.listFiles();
+            for (int i = 0; i < list.length; i++) {
+                if (list[i].isDirectory()) {
+                    Util.deleteDir(list[i]);
+                }
+                else {
+                    list[i].delete();
+                }
+            }
+            dir.delete();
+        }
+    }
+
+    /**
+     * copies a single file.
+     *
+     * <p>If destFile already exists or if both files are the same
+     * the method does nothing. The complete destination path will be
+     * created before copying, if necessary.</p>
+     *
+     * @param srcFile   the file to copy from
+     * @param destFile  the file to copy to
+     */
+    public static void copyFile(final File srcFile, final File destFile) throws FileNotFoundException, IOException {
+        if (!srcFile.toString().equals(destFile.toString())) {
+            if (!destFile.exists()) {
+                RandomAccessFile src;
+                RandomAccessFile dest;
+                File destDir;
+                final byte[] buf = new byte[blockSize];
+                int bytesRead = 0;
+                src = new RandomAccessFile(srcFile.getPath(), "r");
+                destDir = new File(destFile.getParent());
+                destDir.mkdirs();
+                dest = new RandomAccessFile(destFile.getPath(), "rw");
+                bytesRead = src.read(buf);
+                while (bytesRead > -1) {
+                    dest.write(buf, 0, bytesRead);
+                    bytesRead = src.read(buf);
+                }
+                src.close();
+                dest.close();
+            }
+        }
+    }
+
+    /**
+     * get the index of a given element in the list of its parents elements.
+     *
+     * @param elem  the element to get the index number for
+     * @return the index of the given element
+     */
+    public static int getElementIndex(final Element elem) {
+        int i = 0;
+        final Element parent = elem.getParentElement();
+        if (parent != null) {
+            final int last = parent.getElementCount() - 1;
+            Element anElem = parent.getElement(i);
+            if (anElem != elem) {
+                while ((i < last) && (anElem != elem)) {
+                    anElem = parent.getElement(++i);
+                }
+            }
+        }
+        return i;
+    }
+
+    /**
+     * Get the path of the class file for a given class.
+     *
+     * <p>This is either a directory of a class file or a directory of
+     * a JAR file. Thus, this class must reside in the same place as
+     * the application in question, not in a separate library
+     * for instance.</p>
+     *
+     * @param cls  the class to get the path for
+     *
+     * @return the path of this class file or the path of the JAR file this class
+     *      file resides in, whatever applies
+     */
+    public static String getClassFilePath(final Class cls) {
+        int end = 0;
+        String urlStr = null;
+        String clsName = cls.getName();
+        final int clsNameLen = clsName.length() + CLASS_EXT.length();
+        int pos = clsName.lastIndexOf(CLASS_SEPARATOR);
+        if (pos > -1) {
+            clsName = clsName.substring(pos + 1);
+        }
+        clsName = clsName + CLASS_EXT;
+        final URL url = cls.getResource(clsName);
+        if (url != null) {
+            urlStr = url.toString();
+            pos = urlStr.indexOf(JAR_SEPARATOR);
+            if (pos > -1) {
+                urlStr = urlStr.substring(0, pos);
+                end = urlStr.lastIndexOf(URL_SEPARATOR) + 1;
+            }
+            else {
+                end = urlStr.length() - clsNameLen;
+            }
+            pos = urlStr.lastIndexOf(FILE_PREFIX);
+            if (pos > -1) {
+                pos += FILE_PREFIX.length() + 1;
+            }
+            else {
+                pos = 0;
+            }
+            urlStr = urlStr.substring(pos, end);
+            urlStr = urlStr.replaceAll("%20", " ");
+        }
+        return urlStr;
+    }
+
+    /**
+     * quick hack for getting the point value from an attribute value string
+     * (needs to be refined and consolidated with length value)
+     *
+     * @param valStr  the attribute value string to get the point size for
+     *
+     * @return the point size from the given attribute value
+     */
+    public static float getPtValue(String valStr) {
+        float len = 0;
+        int pos = valStr.indexOf(pt);
+        if (pos > -1) {
+            unit = pt;
+            valStr = valStr.substring(0, pos);
+            len = Float.valueOf(valStr).floatValue();
+        }
+        else {
+            pos = valStr.indexOf(px);
+            if (pos > -1) {
+                unit = px;
+                valStr = valStr.substring(0, pos);
+                len = Float.valueOf(valStr).floatValue() * 1.3f;
+            }
+            else {
+                pos = valStr.indexOf(pct);
+                if (pos > -1) {
+                    unit = pct;
+                    valStr = valStr.substring(0, pos);
+                    //System.out.println("Util.getPtValue valStr=" + valStr);
+                    len = Float.valueOf(valStr).floatValue() / 100f;
+                    //System.out.println("Util.getPtValue len=" + len);
+                }
+                else {
+                    // assume relative value 1 .. 6
+                    try {
+                        len = Float.valueOf(valStr).floatValue();
+                        unit = pt;
+                        /*
+                        switch((int) len) {
+                          case 1:
+                            len = 8;
+                            break;
+                          case 2:
+                            len = 10;
+                            break;
+                          case 3:
+                            len = 12;
+                            break;
+                          case 4:
+                            len = 14;
+                            break;
+                          case 5:
+                            len = 18;
+                            break;
+                          case 6:
+                            len = 24;
+                            break;
+                          default:
+                            len = len;
+                            break;
+                        }
+                        */
+                    }
+                    catch (final Exception e) {
+                        // unsupported number format (em ex, etc.)
+                    }
+                }
+            }
+        }
+        return len;
+    }
+
+    /**
+     * get the unit string from the last attribute object which was
+     * converted to a numerical value
+     *
+     * @return the unit string from the last attribute object
+     */
+    public static String getLastAttrUnit() {
+        return unit;
+    }
+
+    /**
+     * get the numerical value for an attribute object
+     *
+     * @param attr  the attribute to get the value from
+     *
+     * @return  the numerical value
+     */
+    public static float getAttrValue(final Object attr) {
+        float val = -1;
+        if (attr != null) {
+            val = Util.getPtValue(attr.toString());
+            //System.out.println("Util.getAttrValue val=" + val);
+        }
+        return val;
+    }
+
+    /**
+     * get the absolute value of an attribute
+     *
+     * @param attr  the attribute to get the value from
+     *
+     * @return the absolute numerical value
+     */
+    public static float getAbsoluteAttrVal(final Object attr) {
+        String valStr = null;
+        if (attr != null) {
+            valStr = attr.toString();
+            int pos = valStr.indexOf(pt);
+            unit = pt;
+            if (pos < 0) {
+                pos = valStr.indexOf(pct);
+                unit = pct;
+                if (pos < 0) {
+                    pos = valStr.indexOf(px);
+                }
+            }
+            if (pos > -1) {
+                valStr = valStr.substring(0, pos);
+                return Float.valueOf(valStr).floatValue();
+            }
+            else {
+                unit = "";
+            }
+        }
+        try {
+            return Float.valueOf(valStr).floatValue();
+        }
+        catch (final Exception e) {
+            // unsupported number format (em ex, etc.)
+            return 0f;
+        }
+    }
+
+    /**
+     * get the row index for a given table cell
+     *
+     * @param cell  the cell element to get the row index for
+     *
+     * @return the row index of the given cell element
+     */
+    public static int getRowIndex(final Element cell) {
+        final Element thisRow = cell.getParentElement();
+        final Element table = thisRow.getParentElement();
+        int index = 0;
+        final int count = table.getElementCount();
+        Element elem = table.getElement(index);
+        while (!elem.equals(thisRow) && index < count) {
+            elem = table.getElement(++index);
+        }
+        return index;
+    }
+
+    /**
+     * Get an arry of strings from a given string having several entries
+     * delimited by blanks.
+     *
+     * <p>In the resource file of SimplyHTML for instance menu bar and menu
+     * definitions are contained as strings having a key for each item.
+     * The keys are delimited with blanks.</p>
+     *
+     * <p>A string "file edit help" from the resource file for instance
+     * would be broken into an array of strings looking as follows</p>
+     *
+     * <p>
+     * String[0]="file"<br>
+     * String[1]="edit"<br>
+     * String[2]="help"
+     * </p>
+     *
+     * @param input  the string to transform into a string array
+     * @return the resulting string array
+     */
+    public static String[] tokenize(final String input, final String delim) {
+        final Vector v = new Vector();
+        final StringTokenizer t = new StringTokenizer(input, delim);
+        String result[];
+        while (t.hasMoreTokens()) {
+            v.addElement(t.nextToken());
+        }
+        result = new String[v.size()];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = (String) v.elementAt(i);
+        }
+        return result;
+    }
+
+    /**
+     * write a message with a time stamp to System.out and remember
+     * the time stamp in a LIFO Vector
+     */
+    public static void msgStart(final String startMsg) {
+        final long startTime = System.currentTimeMillis();
+        startTimes.addElement(new Long(startTime));
+        //System.out.println(startMsg + " startTime=" + startTime);
+    }
+
+    /**
+     * find the first occurrence of an <code>Element</code> in the
+     * element tree above a given <code>Element</code>
+     *
+     * @param name the name of the <code>Element</code> to search for
+     * @param start the <code>Element</code> to start looking
+     *
+     * @return the found <code>Element</code> or null if none is found
+     */
+    public static Element findElementUp(final String name, final Element start) {
+        Element elem = start;
+        while (elem != null && !elem.getName().equalsIgnoreCase(name)) {
+            elem = elem.getParentElement();
+        }
+        return elem;
+    }
+
+    /**
+     * find the first occurrence of an <code>Element</code> in the
+     * element tree above a given <code>Element</code>
+     *
+     * @param name1 the primary name of the <code>Element</code> to search for
+     * @param name2 an alternative name for the <code>Element</code> to search for
+     * @param start the <code>Element</code> to start looking
+     *
+     * @return the found <code>Element</code> or null if none is found
+     */
+    public static Element findElementUp(final String name1, final String name2, final Element start) {
+        Element elem = start;
+        while (elem != null && !(elem.getName().equalsIgnoreCase(name1) || elem.getName().equalsIgnoreCase(name2))) {
+            elem = elem.getParentElement();
+        }
+        return elem;
+    }
+
+    /**
+     * find the first occurrence of an <code>Element</code> in the
+     * element tree below a given <code>Element</code>
+     *
+     * @param name the name of the <code>Element</code> to search for
+     * @param parent the <code>Element</code> to start looking
+     *
+     * @return the found <code>Element</code> or null if none is found
+     */
+    public static Element findElementDown(final String name, final Element parent) {
+        Element foundElement = null;
+        final ElementIterator eli = new ElementIterator(parent);
+        Element thisElement = eli.first();
+        while (thisElement != null && foundElement == null) {
+            if (thisElement.getName().equalsIgnoreCase(name)) {
+                foundElement = thisElement;
+            }
+            thisElement = eli.next();
+        }
+        return foundElement;
+    }
+
+    /**
+     * convenience method for adding a component to a container
+     * layed out by a GridBagLayout
+     *
+     * @param container  the container to add a component to
+     * @param comp  the component to add to container
+     * @param g  the GridBagLayout associated with container
+     * @param c  the GridBagConstraints to use
+     * @param gx  the value to use for GridBagConstraints.gridx
+     * @param gy  the value to use for GridBagConstraints.gridy
+     * @param a  the value to use for GridBagConstraints.anchor
+     */
+    public static void addGridBagComponent(final JComponent container, final JComponent comp, final GridBagLayout g,
+                                           final GridBagConstraints c, final int gx, final int gy, final int a) {
+        /*
+        c.gridx = gx;
+        c.gridy = gy;
+        c.anchor = a;
+        c.insets = new Insets(2, 2, 2, 2);
+        c.ipadx = 2;
+        c.ipady = 2;
+        g.setConstraints(comp, c);
+        container.add(comp);
+        */
+        Util.addGridBagComponent(container, comp, g, c, gx, gy, a, 1, 1, GridBagConstraints.NONE, 0, 0);
+    }
+
+    /**
+     * convenience method for adding a component to a container
+     * layed out by a GridBagLayout
+     *
+     * @param container  the container to add a component to
+     * @param comp  the component to add to container
+     * @param g  the GridBagLayout associated with container
+     * @param c  the GridBagConstraints to use
+     * @param gx  the value to use for GridBagConstraints.gridx
+     * @param gy  the value to use for GridBagConstraints.gridy
+     * @param a  the value to use for GridBagConstraints.anchor
+     * @param gw  the value to use for GridBagConstraints.gridwidth
+     * @param gh  teh value to use for GridBagConstraints.gridheight
+     */
+    public static void addGridBagComponent(final JComponent container, final JComponent comp, final GridBagLayout g,
+                                           final GridBagConstraints c, final int gx, final int gy, final int a,
+                                           final int gw, final int gh) {
+        Util.addGridBagComponent(container, comp, g, c, gx, gy, a, gw, gh, GridBagConstraints.NONE, 0, 0);
+    }
+
+    /**
+     * convenience method for adding a component to a container
+     * layed out by a GridBagLayout
+     *
+     * @param container  the container to add a component to
+     * @param comp  the component to add to container
+     * @param g  the GridBagLayout associated with container
+     * @param c  the GridBagConstraints to use
+     * @param gx  the value to use for GridBagConstraints.gridx
+     * @param gy  the value to use for GridBagConstraints.gridy
+     * @param a  the value to use for GridBagConstraints.anchor
+     * @param gw  the value to use for GridBagConstraints.gridwidth
+     * @param gh  teh value to use for GridBagConstraints.gridheight
+     * @param f  the value to use for GridBagConstraints.fill
+     */
+    public static void addGridBagComponent(final JComponent container, final JComponent comp, final GridBagLayout g,
+                                           final GridBagConstraints c, final int gx, final int gy, final int a,
+                                           final int gw, final int gh, final int f) {
+        Util.addGridBagComponent(container, comp, g, c, gx, gy, a, gw, gh, GridBagConstraints.NONE, 0, 0);
+    }
+
+    /**
+     * convenience method for adding a component to a container
+     * layed out by a GridBagLayout
+     *
+     * @param container  the container to add a component to
+     * @param comp  the component to add to container
+     * @param g  the GridBagLayout associated with container
+     * @param c  the GridBagConstraints to use
+     * @param gx  the value to use for GridBagConstraints.gridx
+     * @param gy  the value to use for GridBagConstraints.gridy
+     * @param a  the value to use for GridBagConstraints.anchor
+     * @param gw  the value to use for GridBagConstraints.gridwidth
+     * @param gh  teh value to use for GridBagConstraints.gridheight
+     * @param f  the value to use for GridBagConstraints.fill
+     * @param wx  the value to use for GridBagConstraints.weightx
+     * @param wy  the value to use for GridBagConstraints.weighty
+     */
+    public static void addGridBagComponent(final JComponent container, final JComponent comp, final GridBagLayout g,
+                                           final GridBagConstraints c, final int gx, final int gy, final int a,
+                                           final int gw, final int gh, final int f, final double wx, final double wy) {
+        c.gridx = gx;
+        c.gridy = gy;
+        c.anchor = a;
+        c.insets = new Insets(2, 2, 2, 2);
+        c.ipadx = 2;
+        c.ipady = 2;
+        c.gridwidth = gw;
+        c.gridheight = gh;
+        c.fill = f;
+        c.weightx = wx;
+        c.weighty = wy;
+        g.setConstraints(comp, c);
+        container.add(comp);
+    }
+
+    /**
+     * resolve a relative URL string against an absolute URL string.
+     *
+     * <p>the absolute URL string is the start point for the
+     * relative path.</p>
+     *
+     * <p><b>Example:</b></p>
+     * <pre>
+     *   absolute path:  file:/d:/eigene dateien/eigene bilder/
+     *   relative path:  ../images/test.jpg
+     *   result:         file:/d:/eigene dateien/images/test.jpg
+     * </pre>
+     *
+     * @param relPath  the relative URL string to resolve
+     * @param absPath  the absolute URL string to start at
+     *
+     * @return the absolute URL string resulting from resolving relPath
+     *    against absPath
+     */
+    public static String resolveRelativePath(final String relPath, final String absPath) {
+        String newAbsPath = absPath;
+        String newRelPath = relPath;
+        if (absPath.endsWith(URL_SEPARATOR)) {
+            newAbsPath = absPath.substring(0, absPath.length() - 1);
+        }
+        int relPos = newRelPath.indexOf(RELATIVE_PREFIX);
+        while (relPos > -1) {
+            newRelPath = newRelPath.substring(relPos + RELATIVE_PREFIX.length());
+            newAbsPath = newAbsPath.substring(0, newAbsPath.lastIndexOf(URL_SEPARATOR));
+            relPos = newRelPath.indexOf(RELATIVE_PREFIX);
+        }
+        if (newRelPath.startsWith(URL_SEPARATOR)) {
+            return newAbsPath + newRelPath;
+        }
+        else {
+            return newAbsPath + URL_SEPARATOR + newRelPath;
+        }
+    }
+
+    /**
+     * get the path to a given file relative to a given directory
+     *
+     * @param fromDir  the directory having the file from which the link refers
+     * @param toFile  the file to which a link refers
+     *
+     * @return the relative path
+     */
+    public static String getRelativePath(final File fromDir, final File toFile) {
+        String fromStr = fromDir.getAbsolutePath();
+        if (!fromStr.endsWith(File.separator)) {
+            fromStr = fromStr + File.separator;
+        }
+        final String toStr = toFile.getAbsolutePath();
+        int pos = fromStr.indexOf(File.separator);
+        final int fromLen = fromStr.length();
+        final int toLen = toStr.length();
+        int oldPos = pos;
+        while ((pos > -1) && (pos < fromLen) && (pos < toLen)
+                && (fromStr.substring(0, pos).equalsIgnoreCase(toStr.substring(0, pos)))) {
+            oldPos = pos + 1;
+            pos = fromStr.indexOf(File.separator, oldPos);
+        }
+        final int samePos = oldPos;
+        int level = 0;
+        while (pos > -1) {
+            ++level;
+            oldPos = pos + 1;
+            pos = fromStr.indexOf(File.separator, oldPos);
+        }
+        final StringBuffer relPath = new StringBuffer();
+        if (level > 0) {
+            for (int i = 0; i < level; i++) {
+                relPath.append("..");
+                relPath.append(File.separator);
+            }
+        }
+        relPath.append(toStr.substring(samePos));
+        return relPath.toString().replace(File.separatorChar, URL_SEPARATOR_CHAR);
+    }
+
+    /**
+     * show an error message and print a stack trace to the console if
+     * in development mode (DEV_MODE = true)
+     *
+     * @param owner the owner of the message, or null
+     * @param msg the message to display, or null
+     * @param e the exception object describing the error, or null
+     */
+    public static void errMsg(final Component owner, final String msg, final Throwable e) {
+        if (e != null) {
+            e.printStackTrace();
+        }
+        if (msg != null) {
+            JOptionPane.showMessageDialog(owner, msg, ERR_TITLE, JOptionPane.ERROR_MESSAGE);
+        }
+    }
+
+    /**
+     * center a <code>Component</code> relative to
+     * another <code>Component</code>.
+     *
+     * @param parent  the <code>Component</code> to be used as the
+     *                  basis for centering
+     * @param comp  the <code>Component</code> to be centered within parent
+     *
+     */
+    public static void center(final Component parent, final Component comp) {
+        final Dimension cSize = comp.getPreferredSize();
+        final Dimension fSize = parent.getSize();
+        final Point loc = parent.getLocation();
+        comp.setLocation((fSize.width - cSize.width) / 2 + loc.x, (fSize.height - cSize.height) / 2 + loc.y);
+    }
+
+    /**
+     * get a StyleSheet object for using its utility methods
+     */
+    public static StyleSheet styleSheet() {
+        return s;
+    }
+
+    /**
+     * remove all occurrences of a given char from a given string
+     *
+     * @param src the string to remove from
+     * @param c  the char to remove
+     *
+     * @return a string copy of src with all occurrences of c removed
+     */
+    public static String removeChar(final String src, final char c) {
+        final StringBuffer buf = new StringBuffer();
+        int start = 0;
+        int pos = src.indexOf(c);
+        while ((pos > -1) && (start < src.length())) {
+            pos = src.indexOf(c, start);
+            if ((pos > -1) && (start < src.length())) {
+                buf.append(src.substring(start, pos));
+                start = pos + 1;
+            }
+        }
+        if (start < src.length()) {
+            buf.append(src.substring(start));
+        }
+        if (buf.length() == 0) {
+            buf.append(src);
+        }
+        return buf.toString();
+    }
+
+    /**
+     * get a string from the resources file
+     *
+     * @param resources  the TextResources to get the string from
+     * @param nm  the key of the string
+     * @return the string for the given key or null if not found
+     */
+    static public String getResourceString(final TextResources resources, final String nm) {
+        return DynamicResource.getResourceString(resources, nm);
+    }
+
+    static public String getResourceString(final String nm) {
+        final String resourceString = DynamicResource.getResourceString(SHTMLPanelImpl.getResources(), nm);
+        return resourceString != null ? resourceString : nm;
+    }
+
+    static public String getPreference(final String key, final String defaultValue) {
+        String paramValue = DynamicResource.getResourceString(SHTMLPanel.getResources(), key);
+        if (paramValue != null) {
+            return paramValue;
+        }
+        paramValue = defaultValue;
+        try {
+            final Preferences prefs = Preferences.userNodeForPackage(PrefsDialog.class);
+            paramValue = prefs.get(key, paramValue);
+        }
+        catch (final Exception ex) {
+        }
+        return paramValue;
+    }
+
+    static boolean preferenceIsTrue(final String key) {
+        return Util.getPreference(key, "false").equalsIgnoreCase("true");
+    }
+
+    static boolean preferenceIsTrue(final String key, final String defaultValue) {
+        return Util.getPreference(key, defaultValue).equalsIgnoreCase("true");
+    }
+
+    static boolean useSteStyleSheet() {
+        return Util.getPreference(PrefsDialog.PREFS_USE_STD_STYLE_SHEET, "false").equalsIgnoreCase("true");
+    }
+
+    /** Tells whether the user should be able to switch between the WYSIWYG editor pane and the HTML source
+     *  editor pane using the UI element of tab, shown below the editing panes. If false, switching
+     *  between editor panes is still possible, albeit not using the tabs. */
+    static boolean showViewsInTabs() {
+        return Util.preferenceIsTrue("showViewsInTabs", "true");
+    }
+}
diff --git a/src/com/lightdev/app/shtm/help/JavaHelpSearch/DOCS.TAB b/src/com/lightdev/app/shtm/help/JavaHelpSearch/DOCS.TAB
new file mode 100644
index 0000000..dc50de6
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/JavaHelpSearch/DOCS.TAB differ
diff --git a/src/com/lightdev/app/shtm/help/JavaHelpSearch/SCHEMA b/src/com/lightdev/app/shtm/help/JavaHelpSearch/SCHEMA
new file mode 100644
index 0000000..645695a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/JavaHelpSearch/SCHEMA
@@ -0,0 +1,2 @@
+JavaSearch 1.0
+TMAP bs=2048 rt=1 fl=-1 id1=3249 id2=1
diff --git a/src/com/lightdev/app/shtm/help/JavaHelpSearch/TMAP b/src/com/lightdev/app/shtm/help/JavaHelpSearch/TMAP
new file mode 100644
index 0000000..8f743c8
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/JavaHelpSearch/TMAP differ
diff --git a/src/com/lightdev/app/shtm/help/help.hs b/src/com/lightdev/app/shtm/help/help.hs
new file mode 100644
index 0000000..46b5436
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/help.hs
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE helpset
+  PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 1.0//EN"
+         "http://java.sun.com/products/javahelp/helpset_1_0.dtd">
+<helpset version="1.0">
+   <!-- title -->
+   <title>help</title>
+   <!-- maps -->
+   <maps>
+     <homeID>item15</homeID>
+     <mapref location="help.jhm" />
+   </maps>
+   <!-- views -->
+   <view>
+      <name>TOC</name>
+      <label>Table Of Contents</label>
+      <type>javax.help.TOCView</type>
+      <data>helpTOC.xml</data>
+   </view>
+   <view>
+      <name>Index</name>
+      <label>Index</label>
+      <type>javax.help.IndexView</type>
+      <data>helpIndex.xml</data>
+   </view>
+   <view>
+      <name>Search</name>
+      <label>Search</label>
+      <type>javax.help.SearchView</type>
+         <data engine="com.sun.java.help.search.DefaultSearchEngine">
+           JavaHelpSearch
+         </data>
+   </view>
+</helpset>
diff --git a/src/com/lightdev/app/shtm/help/help.jhm b/src/com/lightdev/app/shtm/help/help.jhm
new file mode 100644
index 0000000..2156b93
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/help.jhm
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+   <!DOCTYPE map
+     PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Map Version 1.0//EN"
+            "http://java.sun.com/products/javahelp/map_1_0.dtd">
+<map version="1.0">
+   <mapID target="item73" url="topic73.htm" />
+   <mapID target="item1" url="topic1.htm" />
+   <mapID target="item7" url="topic1/topic7.htm" />
+   <mapID target="item5" url="topic1/topic5.htm" />
+   <mapID target="item56" url="topic1/topic5/topic56.htm" />
+   <mapID target="item21" url="topic1/topic21.htm" />
+   <mapID target="item24" url="topic1/topic24.htm" />
+   <mapID target="item22" url="topic22.htm" />
+   <mapID target="item6" url="topic22/topic6.htm" />
+   <mapID target="item23" url="topic22/topic23.htm" />
+   <mapID target="item52" url="topic22/topic52.htm" />
+   <mapID target="item16" url="topic16.htm" />
+   <mapID target="item112" url="topic16/topic112.htm" />
+   <mapID target="item4" url="topic16/topic4.htm" />
+   <mapID target="item11" url="topic16/topic4/topic11.htm" />
+   <mapID target="item12" url="topic16/topic4/topic12.htm" />
+   <mapID target="item17" url="topic16/topic4/topic12/topic17.htm" />
+   <mapID target="item13" url="topic16/topic4/topic12/topic13.htm" />
+   <mapID target="item14" url="topic16/topic4/topic12/topic14.htm" />
+   <mapID target="item18" url="topic16/topic4/topic12/topic18.htm" />
+   <mapID target="item19" url="topic16/topic4/topic12/topic19.htm" />
+   <mapID target="item25" url="topic16/topic4/topic25.htm" />
+   <mapID target="item42" url="topic16/topic4/topic25/topic42.htm" />
+   <mapID target="item46" url="topic16/topic4/topic25/topic46.htm" />
+   <mapID target="item38" url="topic16/topic4/topic25/topic38.htm" />
+   <mapID target="item41" url="topic16/topic4/topic25/topic41.htm" />
+   <mapID target="item45" url="topic16/topic4/topic25/topic45.htm" />
+   <mapID target="item29" url="topic16/topic4/topic25/topic29.htm" />
+   <mapID target="item32" url="topic16/topic4/topic25/topic32.htm" />
+   <mapID target="item47" url="topic16/topic4/topic25/topic47.htm" />
+   <mapID target="item48" url="topic16/topic4/topic25/topic48.htm" />
+   <mapID target="item31" url="topic16/topic4/topic25/topic31.htm" />
+   <mapID target="item20" url="topic16/topic4/topic20.htm" />
+   <mapID target="item28" url="topic16/topic4/topic20/topic28.htm" />
+   <mapID target="item27" url="topic16/topic4/topic20/topic27.htm" />
+   <mapID target="item36" url="topic16/topic4/topic20/topic36.htm" />
+   <mapID target="item37" url="topic16/topic4/topic20/topic37.htm" />
+   <mapID target="item49" url="topic16/topic4/topic20/topic49.htm" />
+   <mapID target="item39" url="topic16/topic4/topic39.htm" />
+   <mapID target="item40" url="topic16/topic4/topic39/topic40.htm" />
+   <mapID target="item51" url="topic16/topic4/topic39/topic51.htm" />
+   <mapID target="item43" url="topic16/topic4/topic39/topic43.htm" />
+   <mapID target="item44" url="topic16/topic4/topic39/topic44.htm" />
+   <mapID target="item62" url="topic16/topic62.htm" />
+   <mapID target="item67" url="topic16/topic62/topic67.htm" />
+   <mapID target="item70" url="topic16/topic62/topic70.htm" />
+   <mapID target="item68" url="topic16/topic62/topic68.htm" />
+   <mapID target="item63" url="topic16/topic62/topic63.htm" />
+   <mapID target="item64" url="topic16/topic62/topic64.htm" />
+   <mapID target="item65" url="topic16/topic62/topic65.htm" />
+   <mapID target="item69" url="topic16/topic62/topic69.htm" />
+   <mapID target="item66" url="topic16/topic62/topic66.htm" />
+   <mapID target="item72" url="topic16/topic62/topic72.htm" />
+   <mapID target="item74" url="topic16/topic74.htm" />
+   <mapID target="item76" url="topic16/topic74/topic76.htm" />
+   <mapID target="item77" url="topic16/topic74/topic77.htm" />
+   <mapID target="item78" url="topic16/topic74/topic78.htm" />
+   <mapID target="item75" url="topic16/topic74/topic75.htm" />
+   <mapID target="item80" url="topic16/topic74/topic80.htm" />
+   <mapID target="item81" url="topic16/topic74/topic81.htm" />
+   <mapID target="item79" url="topic16/topic74/topic79.htm" />
+   <mapID target="item82" url="topic16/topic74/topic82.htm" />
+   <mapID target="item83" url="topic16/topic74/topic83.htm" />
+   <mapID target="item86" url="topic16/topic86.htm" />
+   <mapID target="item89" url="topic16/topic86/topic89.htm" />
+   <mapID target="item92" url="topic16/topic86/topic92.htm" />
+   <mapID target="item95" url="topic16/topic86/topic95.htm" />
+   <mapID target="item96" url="topic16/topic86/topic96.htm" />
+   <mapID target="item100" url="topic16/topic86/topic100.htm" />
+   <mapID target="item91" url="topic16/topic86/topic91.htm" />
+   <mapID target="item99" url="topic16/topic86/topic99.htm" />
+   <mapID target="item93" url="topic16/topic86/topic93.htm" />
+   <mapID target="item94" url="topic16/topic86/topic94.htm" />
+   <mapID target="item103" url="topic16/topic103.htm" />
+   <mapID target="item109" url="topic16/topic103/topic109.htm" />
+   <mapID target="item107" url="topic16/topic103/topic107.htm" />
+   <mapID target="item108" url="topic16/topic103/topic108.htm" />
+   <mapID target="item110" url="topic16/topic103/topic110.htm" />
+   <mapID target="item111" url="topic16/topic103/topic111.htm" />
+   <mapID target="item113" url="topic16/topic103/topic113.htm" />
+   <mapID target="item114" url="topic16/topic103/topic114.htm" />
+   <mapID target="item119" url="topic16/topic103/topic119.htm" />
+   <mapID target="item117" url="topic16/topic103/topic117.htm" />
+   <mapID target="item120" url="topic16/topic120.htm" />
+   <mapID target="item121" url="topic16/topic120/topic121.htm" />
+   <mapID target="item122" url="topic16/topic120/topic122.htm" />
+   <mapID target="item123" url="topic16/topic120/topic123.htm" />
+   <mapID target="item124" url="topic16/topic120/topic124.htm" />
+   <mapID target="item125" url="topic16/topic120/topic125.htm" />
+   <mapID target="item128" url="topic16/topic128.htm" />
+   <mapID target="item134" url="topic16/topic128/topic134.htm" />
+   <mapID target="item129" url="topic16/topic128/topic129.htm" />
+   <mapID target="item131" url="topic16/topic128/topic131.htm" />
+   <mapID target="item130" url="topic16/topic128/topic130.htm" />
+   <mapID target="item133" url="topic16/topic128/topic133.htm" />
+   <mapID target="item140" url="topic16/topic140.htm" />
+   <mapID target="item141" url="topic16/topic140/topic141.htm" />
+   <mapID target="item144" url="topic16/topic140/topic144.htm" />
+   <mapID target="item145" url="topic16/topic140/topic145.htm" />
+   <mapID target="item146" url="topic16/topic140/topic146.htm" />
+   <mapID target="item147" url="topic16/topic140/topic147.htm" />
+   <mapID target="item148" url="topic16/topic140/topic148.htm" />
+   <mapID target="item149" url="topic16/topic140/topic149.htm" />
+   <mapID target="item150" url="topic16/topic140/topic150.htm" />
+   <mapID target="item152" url="topic16/topic152.htm" />
+   <mapID target="item153" url="topic16/topic152/topic153.htm" />
+   <mapID target="item154" url="topic16/topic152/topic154.htm" />
+   <mapID target="item155" url="topic16/topic152/topic155.htm" />
+   <mapID target="item156" url="topic16/topic152/topic156.htm" />
+   <mapID target="item157" url="topic16/topic152/topic157.htm" />
+   <mapID target="item158" url="topic16/topic152/topic158.htm" />
+   <mapID target="item168" url="topic16/topic168.htm" />
+   <mapID target="item169" url="topic16/topic168/topic169.htm" />
+   <mapID target="item170" url="topic16/topic168/topic170.htm" />
+   <mapID target="item171" url="topic16/topic168/topic171.htm" />
+   <mapID target="item173" url="topic16/topic173.htm" />
+   <mapID target="item174" url="topic16/topic173/topic174.htm" />
+   <mapID target="item179" url="topic16/topic173/topic179.htm" />
+   <mapID target="item175" url="topic16/topic173/topic175.htm" />
+   <mapID target="item178" url="topic16/topic173/topic178.htm" />
+   <mapID target="item176" url="topic16/topic173/topic176.htm" />
+   <mapID target="item180" url="topic16/topic173/topic180.htm" />
+   <mapID target="item34" url="topic16/topic34.htm" />
+   <mapID target="item33" url="topic16/topic34/topic33.htm" />
+   <mapID target="item50" url="topic16/topic34/topic50.htm" />
+   <mapID target="item71" url="topic16/topic34/topic71.htm" />
+   <mapID target="item84" url="topic16/topic34/topic84.htm" />
+   <mapID target="item115" url="topic16/topic34/topic115.htm" />
+   <mapID target="item151" url="topic16/topic34/topic151.htm" />
+   <mapID target="item15" url="topic15.htm" />
+   <mapID target="item116" url="topic15/topic116.htm" />
+   <mapID target="item57" url="topic15/topic57.htm" />
+   <mapID target="item59" url="topic15/topic59.htm" />
+   <mapID target="item58" url="topic15/topic58.htm" />
+   <mapID target="item60" url="topic15/topic60.htm" />
+   <mapID target="item127" url="topic15/topic60/topic127.htm" />
+   <mapID target="item85" url="topic15/topic60/topic85.htm" />
+   <mapID target="item102" url="topic15/topic60/topic102.htm" />
+   <mapID target="item126" url="topic15/topic60/topic126.htm" />
+   <mapID target="item135" url="topic15/topic60/topic135.htm" />
+   <mapID target="item138" url="topic15/topic60/topic138.htm" />
+   <mapID target="item139" url="topic15/topic60/topic139.htm" />
+   <mapID target="item159" url="topic15/topic60/topic159.htm" />
+   <mapID target="item162" url="topic15/topic60/topic162.htm" />
+   <mapID target="item160" url="topic15/topic60/topic160.htm" />
+   <mapID target="item172" url="topic15/topic60/topic172.htm" />
+   <mapID target="item177" url="topic15/topic60/topic177.htm" />
+   <mapID target="item60a" url="topic15/topic60a.htm" />
+   <mapID target="item61" url="topic15/topic61.htm" />
+   <mapID target="item118" url="topic15/topic118.htm" />
+   <mapID target="item163" url="topic15/topic163.htm" />
+   <mapID target="item164" url="topic15/topic163/topic164.htm" />
+   <mapID target="item165" url="topic15/topic163/topic165.htm" />
+   <mapID target="item166" url="topic15/topic163/topic166.htm" />
+   <mapID target="item167" url="topic15/topic163/topic167.htm" />
+   <mapID target="item181" url="topic15/topic163/topic181.htm" />
+</map>
diff --git a/src/com/lightdev/app/shtm/help/helpIndex.xml b/src/com/lightdev/app/shtm/help/helpIndex.xml
new file mode 100644
index 0000000..fc137e7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/helpIndex.xml
@@ -0,0 +1,774 @@
+<?xml version='1.0' encoding='ISO-8859-1'  ?>
+   <!DOCTYPE index
+     PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 1.0//EN"
+            "http://java.sun.com/products/javahelp/index_1_0.dtd">
+<index version="1.0">
+   <indexitem text="about SimplyHTML" target="item1" />
+   <indexitem text="AboutBox" target="item40" />
+   <indexitem text="absolute paths" target="item156" />
+   <indexitem text="absolute references" target="item134" />
+   <indexitem text="AbstractPlugin" target="item113" />
+   <indexitem text="action list" target="item28" />
+   <indexitem text="actions" target="item20" />
+   <indexitem text="actions for list formatting" target="item125" />
+   <indexitem text="actions of FrmMain" target="item28" />
+   <indexitem text="actions, connecting to menu">
+      <indexitem text="Creating a dynamic menu" target="item68" />
+      <indexitem text="Adding an edit menu" target="item66" />
+   </indexitem>
+   <indexitem text="actions, defining for plug-ins" target="item113" />
+   <indexitem text="actions, enabling disabling" target="item68" />
+   <indexitem text="Adding a menu bar and menu items" target="item19" />
+   <indexitem text="adding a standard tool bar" target="item83" />
+   <indexitem text="adding columns" target="item91" />
+   <indexitem text="adding elements" target="item96" />
+   <indexitem text="adding images" target="item135" />
+   <indexitem text="adding images to the repository" target="item130" />
+   <indexitem text="adding online help" target="item43" />
+   <indexitem text="adding rows" target="item91" />
+   <indexitem text="AnchorDialog" target="item157" />
+   <indexitem text="API documentation" target="item44" />
+   <indexitem text="API documents" target="item1" />
+   <indexitem text="App" target="item11" />
+   <indexitem text="append row" target="item102" />
+   <indexitem text="appent column" target="item102" />
+   <indexitem text="application" target="item4" />
+   <indexitem text="application creating" target="item11" />
+   <indexitem text="application, documenting" target="item39" />
+   <indexitem text="application, terminating" target="item37" />
+   <indexitem text="apply a named style" target="item139" />
+   <indexitem text="apply font changes" target="item78" />
+   <indexitem text="apply paragraph attributes" target="item141" />
+   <indexitem text="applyAttributes" target="item78" />
+   <indexitem text="applying attributes" target="item93" />
+   <indexitem text="applying image settings" target="item133" />
+   <indexitem text="applying links" target="item155" />
+   <indexitem text="approach to work with paragraph and named styles" target="item145" />
+   <indexitem text="attribute changes" target="item78" />
+   <indexitem text="attribute changes, enabling" target="item96" />
+   <indexitem text="attributes, changing" target="item93" />
+   <indexitem text="attributes, changing for images" target="item130" />
+   <indexitem text="attributes, combining" target="item78" />
+   <indexitem text="attributes, for input" target="item78" />
+   <indexitem text="AttributeSet" target="item78" />
+   <indexitem text="audience" target="item16" />
+   <indexitem text="author" target="item7" />
+   <indexitem text="automate menu construction" target="item68" />
+   <indexitem text="aviod redundancy of code" target="item28" />
+   <indexitem text="avoiding loss of data in the close process" target="item33" />
+   <indexitem text="border rendering, enhancing" target="item99" />
+   <indexitem text="border-color" target="item100" />
+   <indexitem text="border-width" target="item100" />
+   <indexitem text="caret movement in tables" target="item94" />
+   <indexitem text="caret movement inside lists" target="item126" />
+   <indexitem text="caret movement inside tables" target="item102" />
+   <indexitem text="CaretListener" target="item82" />
+   <indexitem text="caretUpdate" target="item82" />
+   <indexitem text="Cascading Style Sheets CSS" target="item42" />
+   <indexitem text="case sensitive search" target="item174" />
+   <indexitem text="cell attributes, changing" target="item93" />
+   <indexitem text="cell border rendering, enhancing" target="item99" />
+   <indexitem text="cells, removing" target="item91" />
+   <indexitem text="change named style" target="item139" />
+   <indexitem text="change single font attributes" target="item81" />
+   <indexitem text="changing attributes" target="item96" />
+   <indexitem text="changing font settings" target="item85" />
+   <indexitem text="changing images" target="item135" />
+   <indexitem text="changing links" target="item159" />
+   <indexitem text="changing list attributes" target="item124" />
+   <indexitem text="changing list formatting" target="item126" />
+   <indexitem text="changing paragraph styles" target="item138" />
+   <indexitem text="changing plug-in settings individually" target="item117" />
+   <indexitem text="changing table and cell attributes" target="item93" />
+   <indexitem text="changing the table format" target="item102" />
+   <indexitem text="changing the table structure" target="item102" />
+   <indexitem text="class App" target="item11" />
+   <indexitem text="Class DynamicResource" target="item111" />
+   <indexitem text="class ParaStyleDialog" target="item146" />
+   <indexitem text="Class PluginManager" target="item110" />
+   <indexitem text="class StyleSelector" target="item147" />
+   <indexitem text="classes" target="item24" />
+   <indexitem text="clipboard" target="item65" />
+   <indexitem text="close actions" target="item33" />
+   <indexitem text="closing all documents" target="item36" />
+   <indexitem text="closing documents">
+      <indexitem text="SHTMLFileCloseAction" target="item27" />
+      <indexitem text="Closing documents" target="item61" />
+   </indexitem>
+   <indexitem text="closing the application" target="item37" />
+   <indexitem text="ColorPanel" target="item75" />
+   <indexitem text="column, append" target="item102" />
+   <indexitem text="column, delete" target="item102" />
+   <indexitem text="column, insert" target="item102" />
+   <indexitem text="columns, adding" target="item91" />
+   <indexitem text="columns, removing" target="item91" />
+   <indexitem text="command" target="item52" />
+   <indexitem text="communication between objects" target="item71" />
+   <indexitem text="concept for image support" target="item129" />
+   <indexitem text="connecting components and actions" target="item111" />
+   <indexitem text="connecting GUI and functionality" target="item20" />
+   <indexitem text="constructing a DocumentPane" target="item41" />
+   <indexitem text="constructing a LicensePane " target="item51" />
+   <indexitem text="constructing the main window" target="item13" />
+   <indexitem text="copyright notices" target="item39" />
+   <indexitem text="create named style" target="item139" />
+   <indexitem text="createToolBar" target="item79" />
+   <indexitem text="creating a basic application" target="item11" />
+   <indexitem text="creating a dynamic menu" target="item68" />
+   <indexitem text="creating a font formatting tool bar" target="item79" />
+   <indexitem text="creating a GUI to define link anchors" target="item157" />
+   <indexitem text="creating a GUI to define links" target="item156" />
+   <indexitem text="creating a main window and menus" target="item12" />
+   <indexitem text="creating a new table" target="item95" />
+   <indexitem text="creating an About dialog" target="item40" />
+   <indexitem text="creating and manipulating lists" target="item126" />
+   <indexitem text="creating and manipulating tables" target="item102" />
+   <indexitem text="creating and storing documents" target="item25" />
+   <indexitem text="creating images" target="item135" />
+   <indexitem text="creating link anchors" target="item162" />
+   <indexitem text="creating links" target="item159" />
+   <indexitem text="Creating new documents">
+      <indexitem text="Creating new documents" target="item29" />
+      <indexitem text="Creating new documents" target="item57" />
+   </indexitem>
+   <indexitem text="creating plug-ins for SimplyHTML" target="item113" />
+   <indexitem text="creating source code documentation" target="item44" />
+   <indexitem text="CSS" target="item76" />
+   <indexitem text="CSS attributes" target="item141" />
+   <indexitem text="CSS shorthand properties, transforming" target="item100" />
+   <indexitem text="CSS style information, saving" target="item47" />
+   <indexitem text="CSS styles" target="item42" />
+   <indexitem text="CSSWriter" target="item48" />
+   <indexitem text="cultural region" target="item70" />
+   <indexitem text="customizeFrame" target="item83" />
+   <indexitem text="customizing Java for CSS" target="item76" />
+   <indexitem text="customizing the main window" target="item18" />
+   <indexitem text="cut and paste">
+      <indexitem text="Cut and paste mechanism in Java" target="item65" />
+      <indexitem text="How cut and paste work in SimplyHTML" target="item69" />
+      <indexitem text="Common edit functions" target="item127" />
+   </indexitem>
+   <indexitem text="data loss, avoiding" target="item33" />
+   <indexitem text="dataflavor" target="item65" />
+   <indexitem text="dealing with styles and font settings" target="item76" />
+   <indexitem text="defining actions for plug-ins" target="item113" />
+   <indexitem text="delete column" target="item102" />
+   <indexitem text="delete named style" target="item139" />
+   <indexitem text="delete row" target="item102" />
+   <indexitem text="deleting images" target="item135" />
+   <indexitem text="deleting link anchors" target="item162" />
+   <indexitem text="deployment of SimplyHTML" target="item151" />
+   <indexitem text="design" target="item16" />
+   <indexitem text="development" target="item16" />
+   <indexitem text="development stages, planned" target="item112" />
+   <indexitem text="directory for images" target="item131" />
+   <indexitem text="discrepancies in HTML and CSS rendering" target="item115" />
+   <indexitem text="distribution package">
+      <indexitem text="Parts of the distribution package" target="item24" />
+      <indexitem text="Installation" target="item23" />
+   </indexitem>
+   <indexitem text="doc" target="item24" />
+   <indexitem text="documentation" target="item1" />
+   <indexitem text="documenting the application" target="item39" />
+   <indexitem text="DocumentListener" target="item38" />
+   <indexitem text="DocumentPane" target="item38" />
+   <indexitem text="DocumentPane, constructing" target="item41" />
+   <indexitem text="documents" target="item4" />
+   <indexitem text="documents in Java" target="item25" />
+   <indexitem text="documents in SimplyHTML" target="item25" />
+   <indexitem text="documents, closing">
+      <indexitem text="SHTMLFileCloseAction" target="item27" />
+      <indexitem text="Closing documents" target="item61" />
+   </indexitem>
+   <indexitem text="documents, closing all" target="item36" />
+   <indexitem text="documents, creating">
+      <indexitem text="Creating new documents" target="item29" />
+      <indexitem text="Creating new documents" target="item57" />
+   </indexitem>
+   <indexitem text="documents, creating and storing" target="item25" />
+   <indexitem text="documents, editing" target="item60" />
+   <indexitem text="documents, loading  from file" target="item31" />
+   <indexitem text="documents, opening" target="item59" />
+   <indexitem text="documents, saving">
+      <indexitem text="Saving documents" target="item32" />
+      <indexitem text="Saving documents" target="item58" />
+   </indexitem>
+   <indexitem text="documents, saving under a different name" target="item58" />
+   <indexitem text="drag" target="item72" />
+   <indexitem text="drag and drop">
+      <indexitem text="Implementing drag and drop" target="item72" />
+      <indexitem text="Common edit functions" target="item127" />
+   </indexitem>
+   <indexitem text="drop">
+      <indexitem text="Implementing drag and drop" target="item72" />
+      <indexitem text="Common edit functions" target="item127" />
+   </indexitem>
+   <indexitem text="dynamic menu, creating" target="item68" />
+   <indexitem text="dynamic resources" target="item111" />
+   <indexitem text="edit functions" target="item127" />
+   <indexitem text="edit menu" target="item66" />
+   <indexitem text="edit named style" target="item139" />
+   <indexitem text="editing documents" target="item60" />
+   <indexitem text="EditorKit" target="item41" />
+   <indexitem text="EffectPanel" target="item75" />
+   <indexitem text="Element" target="item78" />
+   <indexitem text="element changes, enabling" target="item96" />
+   <indexitem text="element type, setting" target="item160" />
+   <indexitem text="elements, adding" target="item96" />
+   <indexitem text="elements, removing" target="item96" />
+   <indexitem text="ElementTreePanel" target="item5" />
+   <indexitem text="enabling element and attribute changes" target="item96" />
+   <indexitem text="enhancing cell border rendering" target="item99" />
+   <indexitem text="event dispatching thread" target="item11" />
+   <indexitem text="example: making a new plug-in" target="item119" />
+   <indexitem text="ExampleFileFilter" target="item5" />
+   <indexitem text="executable JAR" target="item52" />
+   <indexitem text="existing documents, opening" target="item59" />
+   <indexitem text="exiting the application" target="item37" />
+   <indexitem text="Extractor" target="item24" />
+   <indexitem text="FamilyPickList" target="item75" />
+   <indexitem text="file menu" target="item28" />
+   <indexitem text="files" target="item4" />
+   <indexitem text="find and replace basics" target="item174" />
+   <indexitem text="find and replace for whole words" target="item174" />
+   <indexitem text="find and replace over multiple documents" target="item176" />
+   <indexitem text="find and replace search direction" target="item174" />
+   <indexitem text="find and replace start position" target="item174" />
+   <indexitem text="find and replace user interface" target="item179" />
+   <indexitem text="find logic" target="item175" />
+   <indexitem text="finding links" target="item155" />
+   <indexitem text="finding plug-ins" target="item110" />
+   <indexitem text="font attributes, changing single ones" target="item81" />
+   <indexitem text="font dialog" target="item74" />
+   <indexitem text="font formatting tool bar, creating" target="item79" />
+   <indexitem text="font manipulation" target="item74" />
+   <indexitem text="font manipulation GUI" target="item75" />
+   <indexitem text="font name discrepancies" target="item115" />
+   <indexitem text="font settings, applying" target="item78" />
+   <indexitem text="font settings, changing" target="item85" />
+   <indexitem text="font size discrepancies" target="item115" />
+   <indexitem text="font style attributes, changing" target="item75" />
+   <indexitem text="FontAction" target="item80" />
+   <indexitem text="FontComponent">
+      <indexitem text="Creating a GUI for font manipulation" target="item75" />
+      <indexitem text="Actions and components to switch single font attributes" target="item81" />
+   </indexitem>
+   <indexitem text="fontComponents" target="item75" />
+   <indexitem text="FontDialog" target="item80" />
+   <indexitem text="FontFamilyPicker" target="item81" />
+   <indexitem text="FontPanel" target="item75" />
+   <indexitem text="FontSizePicker" target="item81" />
+   <indexitem text="format image" target="item135" />
+   <indexitem text="format, of supported images" target="item129" />
+   <indexitem text="FormatImageAction" target="item133" />
+   <indexitem text="FrmMain" target="item17" />
+   <indexitem text="functionality" target="item16" />
+   <indexitem text="functionality and GUI, connecting" target="item20" />
+   <indexitem text="geographical region" target="item70" />
+   <indexitem text="getAttributes" target="item75" />
+   <indexitem text="getInputAttributes" target="item78" />
+   <indexitem text="getMaxAttributes" target="item78" />
+   <indexitem text="getting compiled classes" target="item24" />
+   <indexitem text="getting started" target="item22" />
+   <indexitem text="getting this tutorial in JavaHelp format" target="item24" />
+   <indexitem text="getValue" target="item75" />
+   <indexitem text="GNU General Public License">
+      <indexitem text="License" target="item5" />
+      <indexitem text="GNU General Public License" target="item56" />
+   </indexitem>
+   <indexitem text="GPL">
+      <indexitem text="License" target="item5" />
+      <indexitem text="GNU General Public License" target="item56" />
+   </indexitem>
+   <indexitem text="gpl txt">
+      <indexitem text="License" target="item5" />
+      <indexitem text="Parts of the distribution package" target="item24" />
+   </indexitem>
+   <indexitem text="graphical user interface" target="item20" />
+   <indexitem text="GUI">
+      <indexitem text="The class DocumentPane" target="item38" />
+      <indexitem text="Using layouts for proper alignment of visible components" target="item50" />
+      <indexitem text="User interface" target="item163" />
+   </indexitem>
+   <indexitem text="GUI and functionality, connecting " target="item20" />
+   <indexitem text="GUI for font manipulation" target="item75" />
+   <indexitem text="handling window close events" target="item14" />
+   <indexitem text="heading element types" target="item160" />
+   <indexitem text="help menu" target="item28" />
+   <indexitem text="Help pdf" target="item24" />
+   <indexitem text="help, how it is created for SimplyHTML" target="item43" />
+   <indexitem text="HelpExpert">
+      <indexitem text="About SimplyHTML" target="item1" />
+      <indexitem text="Adding online help" target="item43" />
+   </indexitem>
+   <indexitem text="highlighting syntax">
+      <indexitem text="Stage 10: HTML code editor and syntax highlighting" target="item168" />
+      <indexitem text="Adding syntax highlighting" target="item170" />
+   </indexitem>
+   <indexitem text="history of SimplyHTML" target="item21" />
+   <indexitem text="how help is created for SimplyHTML" target="item43" />
+   <indexitem text="how plug-ins are found" target="item110" />
+   <indexitem text="how subdirectories are structured" target="item24" />
+   <indexitem text="how to apply links" target="item155" />
+   <indexitem text="how to use JavaHelp in an application" target="item43" />
+   <indexitem text="how undo and redo work in SimplyHTML" target="item64" />
+   <indexitem text="HTML" target="item172" />
+   <indexitem text="HTML and CSS rendering, discrepancies" target="item115" />
+   <indexitem text="HTML code" target="item168" />
+   <indexitem text="HTML code editor" target="item169" />
+   <indexitem text="HTML code view" target="item172" />
+   <indexitem text="HTML documents" target="item42" />
+   <indexitem text="HTML tags" target="item78" />
+   <indexitem text="HTML, transport of" target="item69" />
+   <indexitem text="HTMLDocument">
+      <indexitem text="The class SHTMLEditorKit" target="item45" />
+      <indexitem text="Extending classes for tag SPAN" target="item77" />
+   </indexitem>
+   <indexitem text="HTMLEditorKit">
+      <indexitem text="The class SHTMLEditorKit" target="item45" />
+      <indexitem text="Extending classes for tag SPAN" target="item77" />
+   </indexitem>
+   <indexitem text="HTMLReader" target="item77" />
+   <indexitem text="HTMLText" target="item69" />
+   <indexitem text="HTMLTextSelection" target="item69" />
+   <indexitem text="HTMLWriter" target="item77" />
+   <indexitem text="i18n" target="item67" />
+   <indexitem text="image attributes, changing" target="item130" />
+   <indexitem text="image directory" target="item131" />
+   <indexitem text="image formats" target="item129" />
+   <indexitem text="image links">
+      <indexitem text="How to apply links" target="item155" />
+      <indexitem text="Creating and manipulating links" target="item159" />
+   </indexitem>
+   <indexitem text="image list maintenance" target="item130" />
+   <indexitem text="image preview" target="item130" />
+   <indexitem text="image references in HTML" target="item134" />
+   <indexitem text="image repository" target="item129" />
+   <indexitem text="image settings, applying" target="item133" />
+   <indexitem text="image storage, implementing" target="item131" />
+   <indexitem text="image, format" target="item135" />
+   <indexitem text="image, insert" target="item135" />
+   <indexitem text="image, reading from the class path" target="item40" />
+   <indexitem text="ImageDialog" target="item130" />
+   <indexitem text="images, adding to repository" target="item130" />
+   <indexitem text="images, removing from repository" target="item130" />
+   <indexitem text="implementing image storage" target="item131" />
+   <indexitem text="incorporating plug-ins at runtime" target="item108" />
+   <indexitem text="individual border rendering" target="item99" />
+   <indexitem text="inisde lists" target="item120" />
+   <indexitem text="inner classes" target="item49" />
+   <indexitem text="input attributes" target="item78" />
+   <indexitem text="insert a table" target="item95" />
+   <indexitem text="insert column" target="item102" />
+   <indexitem text="insert image" target="item135" />
+   <indexitem text="insert row" target="item102" />
+   <indexitem text="insert table" target="item102" />
+   <indexitem text="InsertImageAction" target="item133" />
+   <indexitem text="inside images" target="item128" />
+   <indexitem text="inside links" target="item152" />
+   <indexitem text="inside named styles" target="item140" />
+   <indexitem text="inside paragraph styles" target="item140" />
+   <indexitem text="inside SimplyHTML" target="item16" />
+   <indexitem text="installation" target="item23" />
+   <indexitem text="installing plug-ins" target="item114" />
+   <indexitem text="interaction between objects" target="item71" />
+   <indexitem text="interaction between style components and style sheet" target="item148" />
+   <indexitem text="Interface FontComponent" target="item75" />
+   <indexitem text="interfaces, using" target="item71" />
+   <indexitem text="internationalization">
+      <indexitem text="Using resource bundles" target="item67" />
+      <indexitem text="Dynamic resources" target="item111" />
+   </indexitem>
+   <indexitem text="J2SE" target="item6" />
+   <indexitem text="JAR" target="item52" />
+   <indexitem text="JAR files" target="item110" />
+   <indexitem text="Java" target="item6" />
+   <indexitem text="Java 2 Standard Editition J2SE" target="item6" />
+   <indexitem text="Java Network Launching Protocol" target="item151" />
+   <indexitem text="Java Runtime Environemt" target="item11" />
+   <indexitem text="Java Runtime Environment">
+      <indexitem text="Requirements" target="item6" />
+      <indexitem text="Starting SimplyHTML" target="item52" />
+   </indexitem>
+   <indexitem text="Java Web Start" target="item151" />
+   <indexitem text="Javadoc">
+      <indexitem text="About SimplyHTML" target="item1" />
+      <indexitem text="Creating source code documentation" target="item44" />
+   </indexitem>
+   <indexitem text="JavaHelp">
+      <indexitem text="Parts of the distribution package" target="item24" />
+      <indexitem text="Requirements" target="item6" />
+   </indexitem>
+   <indexitem text="JavaHelp extension" target="item43" />
+   <indexitem text="JEditorPane" target="item38" />
+   <indexitem text="jhall jar" target="item24" />
+   <indexitem text="jhall.jar" target="item6" />
+   <indexitem text="JNLP" target="item151" />
+   <indexitem text="JPanel" target="item38" />
+   <indexitem text="JRE">
+      <indexitem text="Requirements" target="item6" />
+      <indexitem text="Installation" target="item23" />
+      <indexitem text="Starting SimplyHTML" target="item52" />
+      <indexitem text="Creating a basic application" target="item11" />
+   </indexitem>
+   <indexitem text="JScrollPane" target="item38" />
+   <indexitem text="JTabbedPane" target="item18" />
+   <indexitem text="jtpDocs">
+      <indexitem text="The class FrmMain" target="item17" />
+      <indexitem text="Customizing the main window" target="item18" />
+   </indexitem>
+   <indexitem text="laguages, other" target="item111" />
+   <indexitem text="language">
+      <indexitem text="Using resource bundles" target="item67" />
+      <indexitem text="Presenting SimplyHTML in multiple languages" target="item70" />
+   </indexitem>
+   <indexitem text="layout view" target="item172" />
+   <indexitem text="layouts, using for proper alignment" target="item50" />
+   <indexitem text="license" target="item5" />
+   <indexitem text="LicensePane" target="item51" />
+   <indexitem text="line separator" target="item48" />
+   <indexitem text="link anchors" target="item153" />
+   <indexitem text="link anchors, setting and removing" target="item162" />
+   <indexitem text="link protocol" target="item153" />
+   <indexitem text="link structure" target="item153" />
+   <indexitem text="link types" target="item153" />
+   <indexitem text="LinkDialog" target="item156" />
+   <indexitem text="links" target="item152" />
+   <indexitem text="links in HTML" target="item153" />
+   <indexitem text="links, creating and manipulating" target="item159" />
+   <indexitem text="list actions" target="item125" />
+   <indexitem text="list attributes, changing" target="item124" />
+   <indexitem text="list format dialog" target="item124" />
+   <indexitem text="list formatting" target="item123" />
+   <indexitem text="list formatting, changing" target="item126" />
+   <indexitem text="list formatting, turning on or off" target="item126" />
+   <indexitem text="list rendering" target="item121" />
+   <indexitem text="listeners" target="item148" />
+   <indexitem text="listeners, using" target="item84" />
+   <indexitem text="lists in HTML documents" target="item121" />
+   <indexitem text="lists, creating and manipulating" target="item126" />
+   <indexitem text="Loading documents from file" target="item31" />
+   <indexitem text="loading plug-ins" target="item110" />
+   <indexitem text="locale" target="item70" />
+   <indexitem text="look and feel" target="item11" />
+   <indexitem text="loss of data, avoiding" target="item33" />
+   <indexitem text="main frame" target="item11" />
+   <indexitem text="main window">
+      <indexitem text="Creating a main window and menus" target="item12" />
+      <indexitem text="Constructing the main window" target="item13" />
+   </indexitem>
+   <indexitem text="main window, customizing" target="item18" />
+   <indexitem text="making a new plug-in (example)" target="item119" />
+   <indexitem text="making plug-ins available to SimplyHTML" target="item114" />
+   <indexitem text="manipulate fonts" target="item74" />
+   <indexitem text="manipulating fonts and font styles" target="item78" />
+   <indexitem text="manipulating links" target="item159" />
+   <indexitem text="manipulating the table structure" target="item91" />
+   <indexitem text="margin" target="item100" />
+   <indexitem text="menu" target="item66" />
+   <indexitem text="menu bar, adding" target="item19" />
+   <indexitem text="menu items, adding" target="item19" />
+   <indexitem text="menu, creating" target="item68" />
+   <indexitem text="menus" target="item12" />
+   <indexitem text="merge lists" target="item123" />
+   <indexitem text="multiple document find and replace" target="item176" />
+   <indexitem text="multiple languages" target="item70" />
+   <indexitem text="named styles" target="item141" />
+   <indexitem text="named styles, create, edit, delete" target="item139" />
+   <indexitem text="online help, adding" target="item43" />
+   <indexitem text="Open Source" target="item1" />
+   <indexitem text="opening existing documents" target="item59" />
+   <indexitem text="options" target="item117" />
+   <indexitem text="other languages" target="item111" />
+   <indexitem text="package">
+      <indexitem text="Parts of the distribution package" target="item24" />
+      <indexitem text="Installation" target="item23" />
+   </indexitem>
+   <indexitem text="padding" target="item100" />
+   <indexitem text="paragraph attributes" target="item141" />
+   <indexitem text="paragraph element type" target="item160" />
+   <indexitem text="paragraph styles, changing" target="item138" />
+   <indexitem text="ParaStyleDialog" target="item145" />
+   <indexitem text="parts needed to implement links" target="item154" />
+   <indexitem text="parts needed to implement style manipulation" target="item144" />
+   <indexitem text="parts of the distribution package" target="item24" />
+   <indexitem text="parts of the plug-in architecture" target="item107" />
+   <indexitem text="paste">
+      <indexitem text="Cut and paste mechanism in Java" target="item65" />
+      <indexitem text="How cut and paste work in SimplyHTML" target="item69" />
+      <indexitem text="Common edit functions" target="item127" />
+   </indexitem>
+   <indexitem text="path" target="item23" />
+   <indexitem text="planned development stages" target="item112" />
+   <indexitem text="plug-in architecture parts" target="item107" />
+   <indexitem text="plug-in initialization" target="item108" />
+   <indexitem text="plug-in installation" target="item114" />
+   <indexitem text="plug-in menu" target="item108" />
+   <indexitem text="plug-in requirements" target="item109" />
+   <indexitem text="plug-in, changing settings" target="item117" />
+   <indexitem text="plug-in, making new (example)" target="item119" />
+   <indexitem text="plug-ins, creating" target="item113" />
+   <indexitem text="plug-ins, defining actions" target="item113" />
+   <indexitem text="plug-ins, incorporating at runtime" target="item108" />
+   <indexitem text="plug-ins, removing" target="item114" />
+   <indexitem text="plug-ins, using" target="item118" />
+   <indexitem text="plug-ins: finding and loading" target="item110" />
+   <indexitem text="plug-ins: using class DynamicResource for" target="item111" />
+   <indexitem text="PluginManager" target="item110" />
+   <indexitem text="political region" target="item70" />
+   <indexitem text="position to start find and replace" target="item174" />
+   <indexitem text="preferences" target="item117" />
+   <indexitem text="preparing for window close events" target="item13" />
+   <indexitem text="presenting SimplyHTML in multiple languages" target="item70" />
+   <indexitem text="previewing images" target="item130" />
+   <indexitem text="process oriented perspective" target="item34" />
+   <indexitem text="processWindowEvent" target="item14" />
+   <indexitem text="propertiers" target="item66" />
+   <indexitem text="properties files" target="item111" />
+   <indexitem text="protocol, for links" target="item153" />
+   <indexitem text="range of text" target="item78" />
+   <indexitem text="reading an image from the class path" target="item40" />
+   <indexitem text="readme document" target="item43" />
+   <indexitem text="readme txt" target="item24" />
+   <indexitem text="redo" target="item63" />
+   <indexitem text="reference link" target="item29" />
+   <indexitem text="references, to images, absolute and relative" target="item134" />
+   <indexitem text="region, geographical, political, cultural" target="item70" />
+   <indexitem text="registerDocument" target="item82" />
+   <indexitem text="regular expressions" target="item170" />
+   <indexitem text="relative paths" target="item156" />
+   <indexitem text="relative references" target="item134" />
+   <indexitem text="remove named style" target="item139" />
+   <indexitem text="removing cells" target="item91" />
+   <indexitem text="removing columns" target="item91" />
+   <indexitem text="removing elements" target="item96" />
+   <indexitem text="removing images" target="item135" />
+   <indexitem text="removing images from the repository" target="item130" />
+   <indexitem text="removing link anchors" target="item162" />
+   <indexitem text="removing plug-ins" target="item114" />
+   <indexitem text="removing rows" target="item91" />
+   <indexitem text="rendering lists" target="item121" />
+   <indexitem text="rendering mechanism (cell borders)" target="item99" />
+   <indexitem text="replace logic" target="item178" />
+   <indexitem text="repository for images" target="item129" />
+   <indexitem text="requirements" target="item6" />
+   <indexitem text="requirements for plug-ins" target="item109" />
+   <indexitem text="resource bundles">
+      <indexitem text="Adding an edit menu" target="item66" />
+      <indexitem text="Dynamic resources" target="item111" />
+   </indexitem>
+   <indexitem text="resource bundles, using" target="item67" />
+   <indexitem text="restoring contents of the downloaded ZIP file" target="item24" />
+   <indexitem text="restrictions for images" target="item129" />
+   <indexitem text="row, append" target="item102" />
+   <indexitem text="row, delete" target="item102" />
+   <indexitem text="row, insert" target="item102" />
+   <indexitem text="rows, adding" target="item91" />
+   <indexitem text="rows, removing" target="item91" />
+   <indexitem text="run" target="item52" />
+   <indexitem text="Runtime Environment">
+      <indexitem text="Requirements" target="item6" />
+      <indexitem text="Starting SimplyHTML" target="item52" />
+   </indexitem>
+   <indexitem text="save thread" target="item27" />
+   <indexitem text="saving CSS style information" target="item47" />
+   <indexitem text="saving documents">
+      <indexitem text="Saving documents" target="item32" />
+      <indexitem text="Saving documents" target="item58" />
+   </indexitem>
+   <indexitem text="saving documents under a different name" target="item58" />
+   <indexitem text="saving style sheets" target="item150" />
+   <indexitem text="SDK" target="item6" />
+   <indexitem text="search direction" target="item174" />
+   <indexitem text="searching for whole words" target="item174" />
+   <indexitem text="selection" target="item78" />
+   <indexitem text="set most relevant font and font style settings at once" target="item75" />
+   <indexitem text="set of attributes" target="item78" />
+   <indexitem text="setAttributes" target="item75" />
+   <indexitem text="setting a look and feel" target="item11" />
+   <indexitem text="setting image attributes" target="item130" />
+   <indexitem text="setting link anchors" target="item162" />
+   <indexitem text="setting links" target="item159" />
+   <indexitem text="setting paragraph styles" target="item138" />
+   <indexitem text="setting the element type" target="item160" />
+   <indexitem text="setValue" target="item75" />
+   <indexitem text="SHTMLAction" target="item71" />
+   <indexitem text="SHTMLEditorKit" target="item45" />
+   <indexitem text="SHTMLFileCloseAction" target="item27" />
+   <indexitem text="SHTMLFileCloseAllAction" target="item36" />
+   <indexitem text="SHTMLFileExitAction" target="item37" />
+   <indexitem text="SHTMLFileNewAction" target="item28" />
+   <indexitem text="SHTMLFileOpenAction" target="item28" />
+   <indexitem text="SHTMLFileSaveAction" target="item28" />
+   <indexitem text="SHTMLFileSaveAsAction" target="item28" />
+   <indexitem text="SHTMLHelpAppInfoAction" target="item28" />
+   <indexitem text="SHTMLHelpShowContentsAction">
+      <indexitem text="Actions of FrmMain" target="item28" />
+      <indexitem text="Adding online help" target="item43" />
+   </indexitem>
+   <indexitem text="SHTMLWriter">
+      <indexitem text="Creating a new table" target="item95" />
+      <indexitem text="CSS shorthand properties" target="item100" />
+   </indexitem>
+   <indexitem text="SimplyHTML distribution package" target="item23" />
+   <indexitem text="SimplyHTML jar" target="item24" />
+   <indexitem text="SizePickList" target="item75" />
+   <indexitem text="Software Development Kit SDK" target="item6" />
+   <indexitem text="source" target="item24" />
+   <indexitem text="source code documentation, creating" target="item44" />
+   <indexitem text="source codes" target="item16" />
+   <indexitem text="SPAN">
+      <indexitem text="Customizing Java for CSS" target="item76" />
+      <indexitem text="Extending classes for tag SPAN" target="item77" />
+   </indexitem>
+   <indexitem text="split lists" target="item123" />
+   <indexitem text="spotlights" target="item34" />
+   <indexitem text="stage 1 application documents and files" target="item4" />
+   <indexitem text="stage 10: HTML code editor and syntax highlighting" target="item168" />
+   <indexitem text="stage 2: resource bundles and common edit functions" target="item62" />
+   <indexitem text="stage 3: font manipulation and tool bars" target="item74" />
+   <indexitem text="stage 4: tables" target="item86" />
+   <indexitem text="stage 5: plug-ins, user settings and dynamic resources" target="item103" />
+   <indexitem text="stage 8: Paragraph styles and named styles" target="item140" />
+   <indexitem text="stage 9: links" target="item152" />
+   <indexitem text="stages">
+      <indexitem text="About SimplyHTML" target="item1" />
+      <indexitem text="Inside SimplyHTML" target="item16" />
+   </indexitem>
+   <indexitem text="stages, planned for development" target="item112" />
+   <indexitem text="start position for find and replace" target="item174" />
+   <indexitem text="starting SimplyHTML" target="item52" />
+   <indexitem text="store undoable edit actions" target="item64" />
+   <indexitem text="structure" target="item16" />
+   <indexitem text="structure of tables in documents" target="item92" />
+   <indexitem text="STYLE attributes" target="item77" />
+   <indexitem text="style handling design in SimplyHTML" target="item46" />
+   <indexitem text="style selector" target="item145" />
+   <indexitem text="style selector, in tool bar" target="item139" />
+   <indexitem text="style sheet">
+      <indexitem text="The class SHTMLEditorKit" target="item45" />
+      <indexitem text="Loading documents from file" target="item31" />
+      <indexitem text="Manipulating fonts and font styles" target="item78" />
+      <indexitem text="Saving documents" target="item58" />
+   </indexitem>
+   <indexitem text="style sheet reference link" target="item29" />
+   <indexitem text="style sheet storage" target="item150" />
+   <indexitem text="style sheet, saving">
+      <indexitem text="Saving CSS style information" target="item47" />
+      <indexitem text="The class CSSWriter" target="item48" />
+   </indexitem>
+   <indexitem text="style sheets" target="item141" />
+   <indexitem text="style sheets and HTML documents" target="item42" />
+   <indexitem text="style sheets, saving" target="item150" />
+   <indexitem text="StylePickList" target="item75" />
+   <indexitem text="styles" target="item65" />
+   <indexitem text="styles in HTML and CSS" target="item141" />
+   <indexitem text="styles, changing for paragraphs" target="item138" />
+   <indexitem text="StyleSheet">
+      <indexitem text="Constructing a DocumentPane" target="item41" />
+      <indexitem text="The class CSSWriter" target="item48" />
+   </indexitem>
+   <indexitem text="subdirectories" target="item24" />
+   <indexitem text="Sun Microsystems Inc" target="item5" />
+   <indexitem text="supporting find and replace over multiple documents" target="item176" />
+   <indexitem text="switch single font attributes" target="item81" />
+   <indexitem text="switch views" target="item172" />
+   <indexitem text="switching list formatting on or off" target="item123" />
+   <indexitem text="synchronizing tool bar and document" target="item82" />
+   <indexitem text="syntax highlighting">
+      <indexitem text="Stage 10: HTML code editor and syntax highlighting" target="item168" />
+      <indexitem text="Adding syntax highlighting" target="item170" />
+   </indexitem>
+   <indexitem text="system platforms" target="item11" />
+   <indexitem text="table attributes, changing" target="item93" />
+   <indexitem text="table cell margin discrepancies" target="item115" />
+   <indexitem text="table manipulation parts to implement" target="item89" />
+   <indexitem text="table structure in documents" target="item92" />
+   <indexitem text="table structure, manipulating" target="item91" />
+   <indexitem text="table, creating new" target="item95" />
+   <indexitem text="TableDialog" target="item93" />
+   <indexitem text="tables, caret movement">
+      <indexitem text="Caret movement in tables" target="item94" />
+      <indexitem text="Creating and manipulating tables" target="item102" />
+   </indexitem>
+   <indexitem text="tables, changing structure" target="item102" />
+   <indexitem text="tables, changing the format" target="item102" />
+   <indexitem text="tables, creating and manipulating" target="item102" />
+   <indexitem text="tables, insert" target="item102" />
+   <indexitem text="tag SPAN">
+      <indexitem text="Customizing Java for CSS" target="item76" />
+      <indexitem text="Extending classes for tag SPAN" target="item77" />
+   </indexitem>
+   <indexitem text="target audience" target="item16" />
+   <indexitem text="temporary storage" target="item129" />
+   <indexitem text="terminating the application" target="item37" />
+   <indexitem text="text files" target="item67" />
+   <indexitem text="text links">
+      <indexitem text="How to apply links" target="item155" />
+      <indexitem text="Creating and manipulating links" target="item159" />
+   </indexitem>
+   <indexitem text="thread">
+      <indexitem text="Creating a basic application" target="item11" />
+      <indexitem text="SHTMLFileCloseAction" target="item27" />
+   </indexitem>
+   <indexitem text="threads" target="item49" />
+   <indexitem text="threads, using for lengthy operations" target="item49" />
+   <indexitem text="TitledPickList" target="item75" />
+   <indexitem text="ToggleFontAction" target="item81" />
+   <indexitem text="toggleList" target="item123" />
+   <indexitem text="tool bar for font formatting" target="item79" />
+   <indexitem text="tool bar, adding a standard one" target="item83" />
+   <indexitem text="tool bar, synchronizing" target="item82" />
+   <indexitem text="tool bars" target="item74" />
+   <indexitem text="transferable" target="item65" />
+   <indexitem text="transport" target="item69" />
+   <indexitem text="transport of data" target="item65" />
+   <indexitem text="transport of HTML" target="item69" />
+   <indexitem text="trnasferable" target="item69" />
+   <indexitem text="turning list formatting on or off" target="item126" />
+   <indexitem text="tutorial">
+      <indexitem text="Parts of the distribution package" target="item24" />
+      <indexitem text="Documenting the application" target="item39" />
+   </indexitem>
+   <indexitem text="types of links" target="item153" />
+   <indexitem text="UIManager" target="item11" />
+   <indexitem text="undo" target="item63" />
+   <indexitem text="undoable edit actions" target="item64" />
+   <indexitem text="UndoableEditListener" target="item63" />
+   <indexitem text="UndoManager" target="item63" />
+   <indexitem text="UndoManager, creating" target="item64" />
+   <indexitem text="unregisterDocument" target="item82" />
+   <indexitem text="updateFormatControls" target="item82" />
+   <indexitem text="URL" target="item31" />
+   <indexitem text="usage of application SimplyHTML" target="item15" />
+   <indexitem text="usage of styles" target="item42" />
+   <indexitem text="user interface">
+      <indexitem text="Connecting GUI and functionality" target="item20" />
+      <indexitem text="User interface" target="item163" />
+   </indexitem>
+   <indexitem text="user interface for find and replace" target="item179" />
+   <indexitem text="user manual" target="item39" />
+   <indexitem text="user settings" target="item117" />
+   <indexitem text="using class DynamicResource for plug-ins" target="item111" />
+   <indexitem text="using FontPanel" target="item80" />
+   <indexitem text="using interfaces" target="item71" />
+   <indexitem text="using Java Web Start to launch SimplyHTML" target="item151" />
+   <indexitem text="using layouts for proper alignment of visible components " target="item50" />
+   <indexitem text="using LinkDialog and AnchorDialog" target="item158" />
+   <indexitem text="using listeners" target="item84" />
+   <indexitem text="using plug-ins" target="item118" />
+   <indexitem text="using resource bundles" target="item67" />
+   <indexitem text="using SimplyHTML" target="item15" />
+   <indexitem text="using threads for lengthy operations" target="item49" />
+   <indexitem text="Vector" target="item75" />
+   <indexitem text="view, HTML" target="item172" />
+   <indexitem text="view, layout" target="item172" />
+   <indexitem text="Web Start" target="item151" />
+   <indexitem text="whole word search" target="item174" />
+   <indexitem text="window close events" target="item37" />
+   <indexitem text="window close events, handling" target="item14" />
+   <indexitem text="window close events, preparing for" target="item13" />
+   <indexitem text="working with HTML code" target="item172" />
+   <indexitem text="zip file" target="item23" />
+   <indexitem text="zip files" target="item24" />
+</index>
diff --git a/src/com/lightdev/app/shtm/help/helpTOC.xml b/src/com/lightdev/app/shtm/help/helpTOC.xml
new file mode 100644
index 0000000..17c4ee7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/helpTOC.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="ISO-8859-1"  ?>
+<!DOCTYPE toc
+  PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 1.0//EN"
+            "http://java.sun.com/products/javahelp/toc_1_0.dtd">
+<toc version="1.0">
+<tocitem text="help" image="chapter" >
+<tocitem text="Title page" target="item73" image="topic" />
+<tocitem text="About SimplyHTML" target="item1" image="chapter" >
+<tocitem text="Author" target="item7" image="topic" />
+<tocitem text="License" target="item5" image="chapter" >
+<tocitem text="GNU General Public License" target="item56" image="topic" />
+</tocitem>
+<tocitem text="History" target="item21" image="topic" />
+<tocitem text="Parts of the distribution package" target="item24" image="topic" />
+</tocitem>
+<tocitem text="Getting started" target="item22" image="chapter" >
+<tocitem text="Requirements" target="item6" image="topic" />
+<tocitem text="Installation" target="item23" image="topic" />
+<tocitem text="Starting SimplyHTML" target="item52" image="topic" />
+</tocitem>
+<tocitem text="Inside SimplyHTML" target="item16" image="chapter" >
+<tocitem text="Planned development stages" target="item112" image="topic" />
+<tocitem text="Stage 1: Documents and files, menus and actions" target="item4" image="chapter" >
+<tocitem text="Creating a basic application" target="item11" image="topic" />
+<tocitem text="Creating a main window and menus" target="item12" image="chapter" >
+<tocitem text="The class FrmMain" target="item17" image="topic" />
+<tocitem text="Constructing the main window" target="item13" image="topic" />
+<tocitem text="Handling window close events" target="item14" image="topic" />
+<tocitem text="Customizing the main window" target="item18" image="topic" />
+<tocitem text="Adding a menu bar and menu items" target="item19" image="topic" />
+</tocitem>
+<tocitem text="Creating and storing documents" target="item25" image="chapter" >
+<tocitem text="Style sheets and HTML documents" target="item42" image="topic" />
+<tocitem text="Style handling design in SimplyHTML" target="item46" image="topic" />
+<tocitem text="The class DocumentPane" target="item38" image="topic" />
+<tocitem text="Constructing a DocumentPane" target="item41" image="topic" />
+<tocitem text="The class SHTMLEditorKit" target="item45" image="topic" />
+<tocitem text="Creating new documents" target="item29" image="topic" />
+<tocitem text="Saving documents" target="item32" image="topic" />
+<tocitem text="Saving CSS style information" target="item47" image="topic" />
+<tocitem text="The class CSSWriter" target="item48" image="topic" />
+<tocitem text="Loading documents from file" target="item31" image="topic" />
+</tocitem>
+<tocitem text="Connecting GUI and functionality" target="item20" image="chapter" >
+<tocitem text="Actions of FrmMain" target="item28" image="topic" />
+<tocitem text="SHTMLFileCloseAction" target="item27" image="topic" />
+<tocitem text="SHTMLFileCloseAllAction" target="item36" image="topic" />
+<tocitem text="SHTMLFileExitAction" target="item37" image="topic" />
+<tocitem text="Using threads for lengthy operations" target="item49" image="topic" />
+</tocitem>
+<tocitem text="Documenting the application" target="item39" image="chapter" >
+<tocitem text="Creating an 'About dialog'" target="item40" image="topic" />
+<tocitem text="The class LicensePane" target="item51" image="topic" />
+<tocitem text="Adding online help" target="item43" image="topic" />
+<tocitem text="Creating source code documentation" target="item44" image="topic" />
+</tocitem>
+</tocitem>
+<tocitem text="Stage 2: Resource bundles and common edit functions" target="item62" image="chapter" >
+<tocitem text="Using resource bundles" target="item67" image="topic" />
+<tocitem text="Presenting SimplyHTML in multiple languages" target="item70" image="topic" />
+<tocitem text="Creating a dynamic menu" target="item68" image="topic" />
+<tocitem text="Typical undo/redo parts" target="item63" image="topic" />
+<tocitem text="How undo and redo work in SimplyHTML" target="item64" image="topic" />
+<tocitem text="Cut and paste mechanism in Java" target="item65" image="topic" />
+<tocitem text="How cut and paste work in SimplyHTML" target="item69" image="topic" />
+<tocitem text="Adding an edit menu" target="item66" image="topic" />
+<tocitem text="Implementing drag and drop" target="item72" image="topic" />
+</tocitem>
+<tocitem text="Stage 3: Font manipulation and tool bars" target="item74" image="chapter" >
+<tocitem text="Customizing Java for CSS" target="item76" image="topic" />
+<tocitem text="Extending classes for tag SPAN" target="item77" image="topic" />
+<tocitem text="Manipulating fonts and font styles" target="item78" image="topic" />
+<tocitem text="Creating a GUI for font manipulation" target="item75" image="topic" />
+<tocitem text="Using the new font formatting GUI" target="item80" image="topic" />
+<tocitem text="Actions and components to switch single font attributes" target="item81" image="topic" />
+<tocitem text="Creating a font formatting tool bar" target="item79" image="topic" />
+<tocitem text="Synchronizing tool bar and document" target="item82" image="topic" />
+<tocitem text="Adding a standard tool bar" target="item83" image="topic" />
+</tocitem>
+<tocitem text="Stage 4: Tables" target="item86" image="chapter" >
+<tocitem text="Table manipulation parts to implement" target="item89" image="topic" />
+<tocitem text="Table structure in documents" target="item92" image="topic" />
+<tocitem text="Creating a new table" target="item95" image="topic" />
+<tocitem text="Enabling element and attribute changes" target="item96" image="topic" />
+<tocitem text="CSS shorthand properties" target="item100" image="topic" />
+<tocitem text="Manipulating the table structure" target="item91" image="topic" />
+<tocitem text="Enhancing cell border rendering" target="item99" image="topic" />
+<tocitem text="Changing table and cell attributes" target="item93" image="topic" />
+<tocitem text="Caret movement in tables" target="item94" image="topic" />
+</tocitem>
+<tocitem text="Stage 5: Plug-ins, user settings and dynamic resources" target="item103" image="chapter" >
+<tocitem text="Requirements" target="item109" image="topic" />
+<tocitem text="Parts of the plug-in architecture" target="item107" image="topic" />
+<tocitem text="Incorporating plug-ins at runtime" target="item108" image="topic" />
+<tocitem text="Class PluginManager" target="item110" image="topic" />
+<tocitem text="Dynamic resources" target="item111" image="topic" />
+<tocitem text="Creating plug-ins for SimplyHTML" target="item113" image="topic" />
+<tocitem text="Making plug-ins available to SimplyHTML" target="item114" image="topic" />
+<tocitem text="Example: Making a new plug-in" target="item119" image="topic" />
+<tocitem text="Changing plug-in settings individually" target="item117" image="topic" />
+</tocitem>
+<tocitem text="Stage 6: Lists" target="item120" image="chapter" >
+<tocitem text="Lists in HTML documents" target="item121" image="topic" />
+<tocitem text="Implementing list formatting in SimplyHTML" target="item122" image="topic" />
+<tocitem text="Switching list formatting on or off" target="item123" image="topic" />
+<tocitem text="Creating a list format dialog" target="item124" image="topic" />
+<tocitem text="Adding actions and GUI elements" target="item125" image="topic" />
+</tocitem>
+<tocitem text="Stage 7: Images" target="item128" image="chapter" >
+<tocitem text="Image references in HTML" target="item134" image="topic" />
+<tocitem text="General concept for image support" target="item129" image="topic" />
+<tocitem text="Implementing image storage" target="item131" image="topic" />
+<tocitem text="Creating a GUI to manipulate image references" target="item130" image="topic" />
+<tocitem text="Making the GUI available to the user" target="item133" image="topic" />
+</tocitem>
+<tocitem text="Stage 8: Paragraph styles and named styles" target="item140" image="chapter" >
+<tocitem text="Styles in HTML and CSS" target="item141" image="topic" />
+<tocitem text="Parts needed to implement style manipulation" target="item144" image="topic" />
+<tocitem text="Approach to work with paragraph and named styles" target="item145" image="topic" />
+<tocitem text="Class ParaStyleDialog" target="item146" image="topic" />
+<tocitem text="Class StyleSelector" target="item147" image="topic" />
+<tocitem text="Interaction between style components and style sheet" target="item148" image="topic" />
+<tocitem text="Adding the new style components to the GUI" target="item149" image="topic" />
+<tocitem text="Style sheet storage" target="item150" image="topic" />
+</tocitem>
+<tocitem text="Stage 9: Links" target="item152" image="chapter" >
+<tocitem text="Links in HTML" target="item153" image="topic" />
+<tocitem text="New parts in this stage" target="item154" image="topic" />
+<tocitem text="How to apply links" target="item155" image="topic" />
+<tocitem text="Creating a GUI to define links" target="item156" image="topic" />
+<tocitem text="Creating a GUI to define link anchors" target="item157" image="topic" />
+<tocitem text="Using LinkDialog and AnchorDialog" target="item158" image="topic" />
+</tocitem>
+<tocitem text="Stage 10: HTML code editor and syntax highlighting" target="item168" image="chapter" >
+<tocitem text="HTML code editor: a simple approach" target="item169" image="topic" />
+<tocitem text="Adding syntax highlighting" target="item170" image="topic" />
+<tocitem text="Integrating the new component" target="item171" image="topic" />
+</tocitem>
+<tocitem text="Stage 11: Find and replace" target="item173" image="chapter" >
+<tocitem text="Find and replace basics" target="item174" image="topic" />
+<tocitem text="Find and replace user interface" target="item179" image="topic" />
+<tocitem text="Find logic" target="item175" image="topic" />
+<tocitem text="Replace logic" target="item178" image="topic" />
+<tocitem text="Supporting find and replace over multiple documents" target="item176" image="topic" />
+<tocitem text="Using FindReplaceDialog in SimplyHTML" target="item180" image="topic" />
+</tocitem>
+<tocitem text="Spotlights" target="item34" image="chapter" >
+<tocitem text="Avoiding loss of data in the close process" target="item33" image="topic" />
+<tocitem text="Using layouts for proper alignment of visible components" target="item50" image="topic" />
+<tocitem text="Using interfaces" target="item71" image="topic" />
+<tocitem text="Using listeners" target="item84" image="topic" />
+<tocitem text="Discrepancies in HTML and CSS rendering" target="item115" image="topic" />
+<tocitem text="Java Web Start" target="item151" image="topic" />
+</tocitem>
+</tocitem>
+<tocitem text="Using SimplyHTML" target="item15" image="chapter" >
+<tocitem text="What is SimplyHTML?" target="item116" image="topic" />
+<tocitem text="Creating new documents" target="item57" image="topic" />
+<tocitem text="Opening existing documents" target="item59" image="topic" />
+<tocitem text="Saving documents" target="item58" image="topic" />
+<tocitem text="Editing documents" target="item60" image="chapter" >
+<tocitem text="Common edit functions" target="item127" image="topic" />
+<tocitem text="Changing font settings" target="item85" image="topic" />
+<tocitem text="Creating and manipulating tables" target="item102" image="topic" />
+<tocitem text="Creating and manipulating lists" target="item126" image="topic" />
+<tocitem text="Working with images" target="item135" image="topic" />
+<tocitem text="Changing paragraph styles" target="item138" image="topic" />
+<tocitem text="Creating and manipulating named styles" target="item139" image="topic" />
+<tocitem text="Creating and manipulating links" target="item159" image="topic" />
+<tocitem text="Creating and deleting link anchors" target="item162" image="topic" />
+<tocitem text="Setting the element type" target="item160" image="topic" />
+<tocitem text="Working with HTML code" target="item172" image="topic" />
+<tocitem text="Using find and replace" target="item177" image="topic" />
+</tocitem>
+<tocitem text="Searching documents" target="item60a" image="topic"/>
+<tocitem text="Closing documents" target="item61" image="topic" />
+<tocitem text="Using plug-ins" target="item118" image="topic" />
+<tocitem text="User interface" target="item163" image="chapter" >
+<tocitem text="Link dialog" target="item164" image="topic" />
+<tocitem text="Link anchor dialog" target="item165" image="topic" />
+<tocitem text="Image dialog" target="item166" image="topic" />
+<tocitem text="Options dialog" target="item167" image="topic" />
+<tocitem text="Find and replace dialog" target="item181" image="topic" />
+</tocitem>
+</tocitem>
+</tocitem>
+</toc>
diff --git a/src/com/lightdev/app/shtm/help/images/anchrDlg.jpg b/src/com/lightdev/app/shtm/help/images/anchrDlg.jpg
new file mode 100644
index 0000000..5da4b28
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/images/anchrDlg.jpg differ
diff --git a/src/com/lightdev/app/shtm/help/images/elemTree.jpg b/src/com/lightdev/app/shtm/help/images/elemTree.jpg
new file mode 100644
index 0000000..4ca7f3d
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/images/elemTree.jpg differ
diff --git a/src/com/lightdev/app/shtm/help/images/fr.jpg b/src/com/lightdev/app/shtm/help/images/fr.jpg
new file mode 100644
index 0000000..8b32566
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/images/fr.jpg differ
diff --git a/src/com/lightdev/app/shtm/help/images/imgDlg.jpg b/src/com/lightdev/app/shtm/help/images/imgDlg.jpg
new file mode 100644
index 0000000..e9e17d7
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/images/imgDlg.jpg differ
diff --git a/src/com/lightdev/app/shtm/help/images/linkDlg.jpg b/src/com/lightdev/app/shtm/help/images/linkDlg.jpg
new file mode 100644
index 0000000..1fbaa59
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/images/linkDlg.jpg differ
diff --git a/src/com/lightdev/app/shtm/help/images/linkImgPnl.jpg b/src/com/lightdev/app/shtm/help/images/linkImgPnl.jpg
new file mode 100644
index 0000000..d333f13
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/images/linkImgPnl.jpg differ
diff --git a/src/com/lightdev/app/shtm/help/images/optDlg.jpg b/src/com/lightdev/app/shtm/help/images/optDlg.jpg
new file mode 100644
index 0000000..5711c35
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/images/optDlg.jpg differ
diff --git a/src/com/lightdev/app/shtm/help/images/splashImage.jpg b/src/com/lightdev/app/shtm/help/images/splashImage.jpg
new file mode 100644
index 0000000..9addf64
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/images/splashImage.jpg differ
diff --git a/src/com/lightdev/app/shtm/help/index.htm b/src/com/lightdev/app/shtm/help/index.htm
new file mode 100644
index 0000000..b4ecb6b
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/index.htm
@@ -0,0 +1,8 @@
+<html>
+<frameset cols="30%,*">
+  <frame src="toc.htm" name="toc" border=1 scrolling=no>
+  <frame src="topic1.htm" name="main">
+</frameset>
+<body bgcolor=#FFFFFF>
+</body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/project.prf b/src/com/lightdev/app/shtm/help/project.prf
new file mode 100644
index 0000000..9abcefb
Binary files /dev/null and b/src/com/lightdev/app/shtm/help/project.prf differ
diff --git a/src/com/lightdev/app/shtm/help/style.css b/src/com/lightdev/app/shtm/help/style.css
new file mode 100644
index 0000000..1bfc573
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/style.css
@@ -0,0 +1,307 @@
+p.heading3 { font-size:12pt;
+             color:#000000;
+             text-decoration:none;
+             font-weight:bold;
+             font-family:Arial,Sans-Serif;
+             text-align:left;
+             font-style:normal;
+             margin-top:12pt;
+             margin-bottom:3pt;
+             background-color:#ffffff; }
+
+p.heading2 { font-size:14pt;
+             color:#000000;
+             text-decoration:none;
+             font-weight:bold;
+             font-family:Arial,Sans-Serif;
+             text-align:left;
+             font-style:normal;
+             margin-top:15pt;
+             margin-bottom:3pt;
+             background-color:#ffffff; }
+
+nobr { white-space:nowrap; }
+
+p.heading1 { font-size:18pt;
+             color:#000000;
+             text-decoration:none;
+             font-weight:bold;
+             font-family:Arial,Sans-Serif;
+             text-align:left;
+             font-style:normal;
+             margin-top:18pt;
+             margin-bottom:6pt;
+             background-color:#ffffff; }
+
+ol { font-size:12pt;
+     list-style-type:decimal;
+     font-family:Arial,Sans-Serif;
+     margin-top:6pt;
+     list-style-position:outside;
+     margin-bottom:10;
+     margin-left:30pt; }
+
+u { text-decoration:underline; }
+
+p.table { font-size:12pt;
+          font-family:Arial,Sans-Serif;
+          margin-top:0pt;
+          margin-bottom:0pt; }
+
+s { text-decoration:line-through; }
+
+p { font-size:12pt;
+    color:#000000;
+    font-family:Arial,Sans-Serif;
+    margin-top:6pt; }
+
+dd p { margin-top:0;
+       margin-left:0;
+       margin-bottom:0; }
+
+p.code { font-size:12pt;
+         color:#000000;
+         text-decoration:none;
+         font-family:Monospaced;
+         font-weight:normal;
+         text-align:left;
+         font-style:normal;
+         margin-top:6pt;
+         background-color:#ffffff; }
+
+ol li p { margin-top:0;
+          margin-bottom:0; }
+
+address { color:blue;
+          font-style:italic; }
+
+i { font-style:italic; }
+
+p.standard_bold { font-size:12pt;
+                  color:#000000;
+                  text-decoration:none;
+                  font-family:Arial,Sans-Serif;
+                  font-weight:bold;
+                  text-align:left;
+                  font-style:normal;
+                  background-color:#ffffff; }
+
+h6 { font-size:xx-small;
+     font-weight:bold;
+     margin-top:10;
+     margin-bottom:10; }
+
+h5 { font-size:x-small;
+     font-weight:bold;
+     margin-top:10;
+     margin-bottom:10; }
+
+h4 { font-size:small;
+     font-weight:bold;
+     margin-top:10;
+     margin-bottom:10; }
+
+h3 { font-size:medium;
+     font-weight:bold;
+     margin-top:10;
+     margin-bottom:10; }
+
+dir li p { margin-top:0;
+           margin-bottom:0; }
+
+h2 { font-size:large;
+     font-weight:bold;
+     margin-top:10;
+     margin-bottom:10; }
+
+b { font-weight:bold; }
+
+h1 { font-size:x-large;
+     font-weight:bold;
+     margin-top:10;
+     margin-bottom:10; }
+
+caption { caption-side:top;
+          text-align:center; }
+
+a { color:blue;
+    text-decoration:underline; }
+
+ul li ul li ul li { margin-right:0;
+                    margin-top:0;
+                    margin-left:0;
+                    margin-bottom:0; }
+
+p.standard { font-family:Arial,Sans-Serif;
+             font-size:12pt;
+             background-color:#ffffff;
+             margin-top:6pt;
+             color:#000000; }
+
+menu { margin-top:10;
+       margin-left:40;
+       margin-bottom:10; }
+
+menu li p { margin-top:0;
+            margin-bottom:0; }
+
+sup { vertical-align:sup; }
+
+body { font-size:14pt;
+       color:black;
+       font-family:Serif;
+       font-weight:normal;
+       margin-right:0;
+       margin-left:0; }
+
+ul li ul li ul { list-style-type:square;
+                 margin-left:25; }
+
+blockquote { margin-right:35;
+             margin-top:5;
+             margin-bottom:5;
+             margin-left:35; }
+
+samp { font-size:small;
+       font-family:Monospaced; }
+
+cite { font-style:italic; }
+
+sub { vertical-align:sub; }
+
+em { font-style:italic; }
+
+ul li p { margin-top:0;
+          margin-bottom:0; }
+
+ul li ul li { margin-right:0;
+              margin-top:0;
+              margin-left:0;
+              margin-bottom:0; }
+
+var { font-weight:bold;
+      font-style:italic; }
+
+table { width:80%;
+        border-color:Gray;
+        border-style:outset; }
+
+dfn { font-style:italic; }
+
+menu li { margin-right:0;
+          margin-top:0;
+          margin-left:0;
+          margin-bottom:0; }
+
+strong { font-weight:bold; }
+
+ul { font-size:12pt;
+     list-style-type:disc;
+     font-family:Arial,Sans-Serif;
+     margin-top:6pt;
+     list-style-position:outside;
+     margin-bottom:10;
+     margin-left:30pt; }
+
+center { text-align:center; }
+
+ul li ul { list-style-type:circle;
+           margin-left:25; }
+
+kbd { font-size:small;
+      font-family:Monospaced; }
+
+dir li { margin-right:0;
+         margin-top:0;
+         margin-left:0;
+         margin-bottom:0; }
+
+ul li menu { list-style-type:circle;
+             margin-left:25; }
+
+dt { margin-top:0;
+     margin-bottom:0; }
+
+ol li { margin-right:0;
+        margin-top:0;
+        margin-left:0;
+        margin-bottom:0; }
+
+li p { margin-top:0;
+       margin-bottom:0; }
+
+strike { text-decoration:line-through; }
+
+dl { margin-top:10;
+     margin-left:0;
+     margin-bottom:10; }
+
+tt { font-family:Monospaced; }
+
+ul li { margin-right:0;
+        margin-top:0;
+        margin-left:0;
+        margin-bottom:0; }
+
+dir { margin-top:10;
+      margin-left:40;
+      margin-bottom:10; }
+
+tr { text-align:left; }
+
+pre p { margin-top:0; }
+
+dd { margin-top:0;
+     margin-left:40;
+     margin-bottom:0; }
+
+li { margin-top:0; }
+
+p.image_subtitle { font-size:12pt;
+                   color:#000000;
+                   text-decoration:none;
+                   font-family:Arial,Sans-Serif;
+                   font-weight:normal;
+                   text-align:center;
+                   font-style:italic;
+                   margin-top:6pt;
+                   background-color:#ffffff; }
+
+th { padding-bottom:3;
+     border-color:Gray;
+     padding-right:3;
+     font-weight:bold;
+     border-style:inset;
+     padding-left:3;
+     text-align:center;
+     padding-top:3; }
+
+pre { font-family:Monospaced;
+      margin-top:5;
+      margin-bottom:5; }
+
+td { margin-top:1pt;
+     padding-left:4pt;
+     text-align:left;
+     padding-top:0pt;
+     margin-right:1pt;
+     border-right-width:0pt;
+     margin-left:1pt;
+     border-top-width:0pt;
+     padding-right:4pt;
+     border-color:Gray;
+     border-bottom-width:0pt;
+     border-left-width:0pt;
+     background-color:#dcdcdb;
+     border-style:solid;
+     margin-bottom:1pt;
+     vertical-align:top;
+     padding-bottom:2pt; }
+
+code { font-size:small;
+       font-family:Monospaced; }
+
+small { font-size:x-small; }
+
+big { font-size:x-large; }
+
diff --git a/src/com/lightdev/app/shtm/help/toc.htm b/src/com/lightdev/app/shtm/help/toc.htm
new file mode 100644
index 0000000..f19f5bb
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/toc.htm
@@ -0,0 +1,19 @@
+<HTML>
+<BODY>
+<APPLET
+  ARCHIVE  = "JavaHelpTOC.jar"
+  CODEBASE = "."
+  CODE     = "de.calcom.applet.help.JavaHelpTOC.class"
+  NAME     = "JavaHelpTOC"
+  WIDTH    = 100%
+  HEIGHT   = 100%
+  HSPACE   = 0
+  VSPACE   = 0
+  ALIGN    = top
+>
+<PARAM NAME="mapFileName" VALUE="help.jhm">
+<PARAM NAME="tocFileName" VALUE="helpTOC.xml">
+<PARAM NAME="targetFrame" VALUE="main">
+</APPLET>
+</BODY>
+</HTML>
diff --git a/src/com/lightdev/app/shtm/help/topic1.htm b/src/com/lightdev/app/shtm/help/topic1.htm
new file mode 100644
index 0000000..32fcf0e
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic1.htm
@@ -0,0 +1,83 @@
+<html>
+  <head>
+    <link href="style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      About SimplyHTML
+    </p>
+    <p>
+      SimplyHTML is an application for text processing. It stores documents as 
+      HTML files in combination with <a href="topic16/topic4/topic25/topic42.htm">
+Cascading Style Sheets (CSS)</a>. The application combines text processing 
+      features as known from popular word processors with a simple and generic 
+      way to store textual information and styles.
+    </p>
+    <p>
+      SimplyHTML is not intended to be used as an editor for web pages in the 
+      first place (although it can be used for this purpose with some 
+      limitations too). Especially HTML and CSS produced by other applications 
+      might or might not work with SimplyHTML, as other applications as well 
+      have trouble with content not produced by themselves.
+    </p>
+    <p>
+      See also chapter '<a href="topic15/topic116.htm">What is SimplyHTML?</a> 
+      ' in section '<a href="topic15.htm">Using SimplyHTML</a>' for additional 
+      details.
+    </p>
+    <p class="heading2">
+      The SimplyHTML Project
+    </p>
+    <p>
+      The SimplyHTML project was started to build an application with above 
+      features and to document, how this can be done. This is approached by 
+      building SimplyHTML in several stages and by documenting all stages 
+      thoroughly. Each stage is covering certain functionality making it 
+      easier to concentrate on some of the many details such an application is 
+      made of. Stages are described in this tutorial, which as well serves as 
+      online help. Source codes are documented with Javadoc in addition.
+    </p>
+    <p class="heading3">
+      Open Source
+    </p>
+    <p>
+      All source code is openly available along with the application and can 
+      be used to find out, how the application is working. Among serving for 
+      above functions, SimplyHTML shall be an example for developers intending 
+      to build applications with similar functionality. As well it can serve 
+      as basis for other applications.
+    </p>
+    <p>
+      Please see chapter <a href="topic1/topic5.htm">License</a> for details 
+      about terms and conditions for availability and distribution of this 
+      product.
+    </p>
+    <p class="heading3">
+      Documentation
+    </p>
+    <p>
+      Sources are documented by Javadoc comments, which are compiled to an API 
+      documents collection with <a href="topic16/topic4/topic39/topic44.htm">
+      Javadoc</a>.
+    </p>
+    <p>
+      The project and application is documented with this tutorial. The 
+      tutorial covers general information about the project and the 
+      application, information about <a href="topic22.htm">installation and 
+      requirements</a>, the <a href="topic16.htm">internal structure and 
+      functions</a> of SimplyHTML and finally its <a href="topic15.htm">usage</a>
+ .
+    </p>
+    <p>
+      The tutorial can be used as online help for SimplyHTML as well as for 
+      reading about how SimplyHTML is built. It is available in formats plain 
+      HTML, JavaHelp and PDF. The tutorial was built with application 
+      HelpExpert entirely.
+    </p>
+    <p>
+      Application HelpExpert is available at <font color="#3333ff">
+      http://www.calcom.de/eng/product/hlpex.htm</font>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic1/topic21.htm b/src/com/lightdev/app/shtm/help/topic1/topic21.htm
new file mode 100644
index 0000000..da34ee7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic1/topic21.htm
@@ -0,0 +1,135 @@
+<html>
+  <head>
+    <link type="text/css" href="../style.css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      History of SimplyHTML
+    </p>
+    <p class="heading2">
+      April 27, 2003
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic173.htm">Stage 11</a> published with find and 
+      replace support.
+    </p>
+    <p class="heading2">
+      February 15, 2003
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic168.htm">Stage 10</a> published adding a HTML 
+      editor with syntax highlighting and some enhancements in the plug-in 
+      architecture.
+    </p>
+    <p class="heading2">
+      December 29, 2002
+    </p>
+    <p class="standard">
+      Release 2 of stage 9 published. This release is a major update with 
+      enhancements to the way SimplyHTML handles HTML content. Release 2 
+      focuses on a clearer distinction between HTML 3.2 and HTML 4. It lets 
+      the user choose the HTML version SimplyHTML should use through the <a href="../topic15/topic163/topic167.htm">
+options dialog</a>. Changes were made to the style sheet handling and the 
+      plug-in architecture too.
+    </p>
+    <p class="heading2">
+      December 13, 2002
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic152.htm">Stage 9</a> published featuring 
+      creation and manipulation of links and link anchors. Refines working 
+      with paragraph styles and named styles by supporting tag types and 
+      multiple styles for given tags in certain controls. Refines cut and 
+      paste for nested paragraph tags. <a href="../topic16/topic34/topic115.htm">
+Compensates</a> different display of font sizes between Java and Web Browsers. 
+      Table rendering was enhanced. Selected dialogs have a button for context 
+      sensitive help on the respective dialog. A new section <a href="../topic15/topic163.htm">
+user interface</a> has been added to the tutorial for this purpose. The 
+      application 'remembers' the directories of the file that was last opened 
+      and saved.
+    </p>
+    <p class="heading2">
+      November 8, 2002
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic140.htm">Stage 8</a> published implementing 
+      paragraph and named style manipulation. SimplyHTML is enabled for <a href="../topic16/topic34/topic151.htm">
+Java Web Start</a> as well and can be started with a single mouse click now 
+      from SimplyHTML's homepage at <font color="#0039ff">
+      http://www.lightdev.com</font>.
+    </p>
+    <p class="heading2">
+      October 20, 2002
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic128.htm">Stage 7</a> published implementing 
+      image insertion and manipulation. Fixed a serious bug in class <font face="'Courier New',Monospaced,Monospace"><a href="../topic16/topic103/topic113.htm">
+AbstractPlugin</a></font>.
+    </p>
+    <p class="heading2">
+      October 4, 2002
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic120.htm">Stage 6</a> published implementing 
+      list formatting.
+    </p>
+    <p class="heading2">
+      September 19, 2002
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic103.htm">Stage 5</a> published implementing a 
+      plug-in architecture and enhanced handling of resource bundles for 
+      dynamic menu creation. Along with the plug-in facility, user settings 
+      are implemented to be persistently stored. An <font face="'Courier New',Monospaced,Monospace">
+AttributeMapper</font> compensates some <a href="../topic16/topic34/topic115.htm">
+discrepancies between Java and HTML</a>.
+    </p>
+    <p class="heading2">
+      August 15, 2002
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic86.htm">Stage 4</a> published featuring table 
+      manipulation
+    </p>
+    <p class="heading2">
+      July 11, 2002
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic74.htm">Stage 3</a> published featuring font 
+      manipulation and dynamic tool bar creation.
+    </p>
+    <p class="heading2">
+      June 29, 2002
+    </p>
+    <p class="standard">
+      <a href="../topic16/topic62.htm">Stage 2</a> published. Features 
+      resource bundles, multiple language support, cut and paste, drag and 
+      drop, both including HTML styles and dynamic menu creation.
+    </p>
+    <p class="heading2">
+      June 21, 2002
+    </p>
+    <p>
+      First full release of <a href="../topic16/topic4.htm">stage 1</a> 
+      published. Inlcudes initial build of the tutorial, API docs, source 
+      codes, executable JAR file and a PDF version of the tutorial.
+    </p>
+    <p class="heading2">
+      June 16, 2002
+    </p>
+    <p>
+      published pre-release 1 of stage 1 (source codes and javadoc 
+      compilation). Wow, eight weeks went by and still no first release 
+      finished. Let's at least share what we have so far. Because the tutorial 
+      takes more time to write than the application itself and although the 
+      tutorial is almoset done, this pre-release comes without the tutorial.
+    </p>
+    <p class="heading2">
+      April 2002
+    </p>
+    <p>
+      start of the SimplyHTML project.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic1/topic24.htm b/src/com/lightdev/app/shtm/help/topic1/topic24.htm
new file mode 100644
index 0000000..4c0fde8
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic1/topic24.htm
@@ -0,0 +1,83 @@
+<html>
+  <head>
+    <link href="../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Parts of the distribution package
+    </p>
+    <p>
+      The distribution package comes as a single compressed zip file. It 
+      contains
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">SimplyHTML.jar</font> 
+        - the executable file for the latest stage of SimplyHTML
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">Help.pdf</font> - this 
+        tutorial as PDF file
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">readme.txt</font> - 
+        essential information about SimplyHTML
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">gpl.txt</font> - the 
+        file containing the license agreement valid for all parts of the 
+        distribution package
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">jhall.jar</font> - 
+        JavaHelp runtime extension
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">source</font> - source 
+        code directory
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">doc</font> - directory 
+        with API documentation files
+      </li>
+    </ul>
+    <p>
+      Please refer to chapter '<a href="../topic1/topic5.htm">License</a>' for 
+      terms and conditions of using above parts.
+    </p>
+    <p class="heading2">
+      Restoring contents of the downloaded ZIP file
+    </p>
+    <p>
+      Above contents can be restored from the compressed distribution file by 
+      using one of the many applications capable to extract ZIP files (WinZIP 
+      or Ark for instance). If you do not have such an application, you could 
+      use application Extractor available free at
+    </p>
+    <p>
+      <font color="#0033ff">http://www.calcom.de/eng/product/xtract.htm</font>
+    </p>
+    <p class="heading2">
+      Getting compiled classes
+    </p>
+    <p>
+      Besides compiling the sources, file <font face="'Courier New',Monospaced,Monospace">
+SimplyHTML.jar</font> has a complete set of classes for the latest stage of 
+      SimplyHTML. Java Archive (JAR) files are structured like ZIP files. 
+      Their contents can be restored with any application able to extract ZIP 
+      archives (see above).
+    </p>
+    <p class="heading2">
+      Getting this tutorial in JavaHelp format
+    </p>
+    <p>
+      Additional to the version in PDF format <font face="'Courier New',Monospaced,Monospace">
+SimplyHTML.jar</font> has a complete set of this tutorial in <a href="../topic16/topic4/topic39/topic43.htm">
+JavaHelp</a> format in package <font face="'Courier New',Monospaced,Monospace">
+      com.lightdev.app.shtm.help</font> too. Opening file <font face="'Courier New',Monospaced,Monospace">
+index.htm</font> in this package lets you open the tutorial with any Java 
+      enabled browser as well.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic1/topic5.htm b/src/com/lightdev/app/shtm/help/topic1/topic5.htm
new file mode 100644
index 0000000..cb7586d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic1/topic5.htm
@@ -0,0 +1,29 @@
+<html>
+  <head>
+    <link href="../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      License
+    </p>
+    <p>
+      Except for parts shown separately below, application SimplyHTML and all 
+      of its components such as source codes, documentation and accompanying 
+      documents are distributed unter the terms and conditions of the <a href="../topic1/topic5/topic56.htm">
+GNU General Public License</a>. To read the full license text, please see file 
+      '<font face="'Courier New',Monospaced,Monospace">gpl.txt</font>' in the <a href="../topic1/topic24.htm">
+distribution package</a> of this software or refer to its text <a href="../topic1/topic5/topic56.htm">
+here</a>.
+    </p>
+    <p class="heading2">
+      Parts falling under different license terms
+    </p>
+    <p>
+      Classes <font face="'Courier New',Monospaced,Monospace">ExampleFileFilter</font>
+ , <font face="'Courier New',Monospaced,Monospace">ElementTreePanel</font> and 
+      their source code is Copyright 2002 Sun Microsystems, Inc. All rights 
+      reserved.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic1/topic5/topic56.htm b/src/com/lightdev/app/shtm/help/topic1/topic5/topic56.htm
new file mode 100644
index 0000000..92b2e82
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic1/topic5/topic56.htm
@@ -0,0 +1,607 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p>
+      GNU GENERAL PUBLIC LICENSE
+    </p>
+    <p>
+      Version 2, June 1991
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+    </p>
+    <p>
+      59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Everyone is permitted to copy and distribute verbatim copies of this 
+      license document, but changing it is not allowed.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Preamble
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      The licenses for most software are designed to take away your freedom to 
+      share and change it. By contrast, the GNU General Public License is 
+      intended to guarantee your freedom to share and change free software--to 
+      make sure the software is free for all its users. This General Public 
+      License applies to most of the Free Software Foundation's software and 
+      to any other program whose authors commit to using it. (Some other Free 
+      Software Foundation software is covered by the GNU Library General 
+      Public License instead.) You can apply it to your programs, too.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      When we speak of free software, we are referring to freedom, not price. 
+      Our General Public Licenses are designed to make sure that you have the 
+      freedom to distribute copies of free software (and charge for this 
+      service if you wish), that you receive source code or can get it if you 
+      want it, that you can change the software or use pieces of it in new 
+      free programs; and that you know you can do these things.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      To protect your rights, we need to make restrictions that forbid anyone 
+      to deny you these rights or to ask you to surrender the rights. These 
+      restrictions translate to certain responsibilities for you if you 
+      distribute copies of the software, or if you modify it.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      For example, if you distribute copies of such a program, whether gratis 
+      or for a fee, you must give the recipients all the rights that you have. 
+      You must make sure that they, too, receive or can get the source code. 
+      And you must show them these terms so they know their rights.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      We protect your rights with two steps:
+    </p>
+    <p>
+      (1) copyright the software, and
+    </p>
+    <p>
+      (2) offer you this license which gives you legal permission to copy, 
+      distribute and/or modify the software.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Also, for each author's protection and ours, we want to make certain 
+      that everyone understands that there is no warranty for this free 
+      software. If the software is modified by someone else and passed on, we 
+      want its recipients to know that what they have is not the original, so 
+      that any problems introduced by others will not reflect on the original 
+      authors' reputations.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Finally, any free program is threatened constantly by software patents. 
+      We wish to avoid the danger that redistributors of a free program will 
+      individually obtain patent licenses, in effect making the program 
+      proprietary. To prevent this, we have made it clear that any patent must 
+      be licensed for everyone's free use or not licensed at all.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      The precise terms and conditions for copying, distribution and 
+      modification follow.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      GNU GENERAL PUBLIC LICENSE
+    </p>
+    <p>
+      TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      0. This License applies to any program or other work which contains a 
+      notice placed by the copyright holder saying it may be distributed under 
+      the terms of this General Public License. The "Program", below, refers 
+      to any such program or work, and a "work based on the Program" means 
+      either the Program or any derivative work under copyright law: that is 
+      to say, a work containing the Program or a portion of it, either 
+      verbatim or with modifications and/or translated into another language. 
+      (Hereinafter, translation is included without limitation in the term 
+      "modification".) Each licensee is addressed as "you".
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Activities other than copying, distribution and modification are not 
+      covered by this License; they are outside its scope. The act of running 
+      the Program is not restricted, and the output from the Program is 
+      covered only if its contents constitute a work based on the Program 
+      (independent of having been made by running the Program). Whether that 
+      is true depends on what the Program does.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      1. You may copy and distribute verbatim copies of the Program's source 
+      code as you receive it, in any medium, provided that you conspicuously 
+      and appropriately publish on each copy an appropriate copyright notice 
+      and disclaimer of warranty; keep intact all the notices that refer to 
+      this License and to the absence of any warranty; and give any other 
+      recipients of the Program a copy of this License along with the Program.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      You may charge a fee for the physical act of transferring a copy, and 
+      you may at your option offer warranty protection in exchange for a fee.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      2. You may modify your copy or copies of the Program or any portion of 
+      it, thus forming a work based on the Program, and copy and distribute 
+      such modifications or work under the terms of Section 1 above, provided 
+      that you also meet all of these conditions:
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      a) You must cause the modified files to carry prominent notices stating 
+      that you changed the files and the date of any change.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      b) You must cause any work that you distribute or publish, that in whole 
+      or in part contains or is derived from the Program or any part thereof, 
+      to be licensed as a whole at no charge to all third parties under the 
+      terms of this License.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      c) If the modified program normally reads commands interactively when 
+      run, you must cause it, when started running for such interactive use in 
+      the most ordinary way, to print or display an announcement including an 
+      appropriate copyright notice and a notice that there is no warranty (or 
+      else, saying that you provide a warranty) and that users may 
+      redistribute the program under these conditions, and telling the user 
+      how to view a copy of this License. (Exception: if the Program itself is 
+      interactive but does not normally print such an announcement, your work 
+      based on the Program is not required to print an announcement.)
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      These requirements apply to the modified work as a whole. If 
+      identifiable sections of that work are not derived from the Program, and 
+      can be reasonably considered independent and separate works in 
+      themselves, then this License, and its terms, do not apply to those 
+      sections when you distribute them as separate works. But when you 
+      distribute the same sections as part of a whole which is a work based on 
+      the Program, the distribution of the whole must be on the terms of this 
+      License, whose permissions for other licensees extend to the entire 
+      whole, and thus to each and every part regardless of who wrote it.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Thus, it is not the intent of this section to claim rights or contest 
+      your rights to work written entirely by you; rather, the intent is to 
+      exercise the right to control the distribution of derivative or 
+      collective works based on the Program.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      In addition, mere aggregation of another work not based on the Program 
+      with the Program (or with a work based on the Program) on a volume of a 
+      storage or distribution medium does not bring the other work under the 
+      scope of this License.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      3. You may copy and distribute the Program (or a work based on it, under 
+      Section 2) in object code or executable form under the terms of Sections 
+      1 and 2 above provided that you also do one of the following:
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      a) Accompany it with the complete corresponding machine-readable source 
+      code, which must be distributed under the terms of Sections 1 and 2 
+      above on a medium customarily used for software interchange; or,
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      b) Accompany it with a written offer, valid for at least three years, to 
+      give any third party, for a charge no more than your cost of physically 
+      performing source distribution, a complete machine-readable copy of the 
+      corresponding source code, to be distributed under the terms of Sections 
+      1 and 2 above on a medium customarily used for software interchange; or,
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      c) Accompany it with the information you received as to the offer to 
+      distribute corresponding source code. (This alternative is allowed only 
+      for noncommercial distribution and only if you received the program in 
+      object code or executable form with such an offer, in accord with 
+      Subsection b above.)
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      The source code for a work means the preferred form of the work for 
+      making modifications to it. For an executable work, complete source code 
+      means all the source code for all modules it contains, plus any 
+      associated interface definition files, plus the scripts used to control 
+      compilation and installation of the executable. However, as a special 
+      exception, the source code distributed need not include anything that is 
+      normally distributed (in either source or binary form) with the major 
+      components (compiler, kernel, and so on) of the operating system on 
+      which the executable runs, unless that component itself accompanies the 
+      executable.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      If distribution of executable or object code is made by offering access 
+      to copy from a designated place, then offering equivalent access to copy 
+      the source code from the same place counts as distribution of the source 
+      code, even though third parties are not compelled to copy the source 
+      along with the object code.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      4. You may not copy, modify, sublicense, or distribute the Program 
+      except as expressly provided under this License. Any attempt otherwise 
+      to copy, modify, sublicense or distribute the Program is void, and will 
+      automatically terminate your rights under this License. However, parties 
+      who have received copies, or rights, from you under this License will 
+      not have their licenses terminated so long as such parties remain in 
+      full compliance.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      5. You are not required to accept this License, since you have not 
+      signed it. However, nothing else grants you permission to modify or 
+      distribute the Program or its derivative works. These actions are 
+      prohibited by law if you do not accept this License. Therefore, by 
+      modifying or distributing the Program (or any work based on the 
+      Program), you indicate your acceptance of this License to do so, and all 
+      its terms and conditions for copying, distributing or modifying the 
+      Program or works based on it.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      6. Each time you redistribute the Program (or any work based on the 
+      Program), the recipient automatically receives a license from the 
+      original licensor to copy, distribute or modify the Program subject to 
+      these terms and conditions. You may not impose any further restrictions 
+      on the recipients' exercise of the rights granted herein. You are not 
+      responsible for enforcing compliance by third parties to this License.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      7. If, as a consequence of a court judgment or allegation of patent 
+      infringement or for any other reason (not limited to patent issues), 
+      conditions are imposed on you (whether by court order, agreement or 
+      otherwise) that contradict the conditions of this License, they do not 
+      excuse you from the conditions of this License. If you cannot distribute 
+      so as to satisfy simultaneously your obligations under this License and 
+      any other pertinent obligations, then as a consequence you may not 
+      distribute the Program at all. For example, if a patent license would 
+      not permit royalty-free redistribution of the Program by all those who 
+      receive copies directly or indirectly through you, then the only way you 
+      could satisfy both it and this License would be to refrain entirely from 
+      distribution of the Program.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      If any portion of this section is held invalid or unenforceable under 
+      any particular circumstance, the balance of the section is intended to 
+      apply and the section as a whole is intended to apply in other 
+      circumstances.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      It is not the purpose of this section to induce you to infringe any 
+      patents or other property right claims or to contest validity of any 
+      such claims; this section has the sole purpose of protecting the 
+      integrity of the free software distribution system, which is implemented 
+      by public license practices. Many people have made generous 
+      contributions to the wide range of software distributed through that 
+      system in reliance on consistent application of that system; it is up to 
+      the author/donor to decide if he or she is willing to distribute 
+      software through any other system and a licensee cannot impose that 
+      choice.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      This section is intended to make thoroughly clear what is believed to be 
+      a consequence of the rest of this License.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      8. If the distribution and/or use of the Program is restricted in 
+      certain countries either by patents or by copyrighted interfaces, the 
+      original copyright holder who places the Program under this License may 
+      add an explicit geographical distribution limitation excluding those 
+      countries, so that distribution is permitted only in or amongcountries 
+      not thus excluded. In such case, this License incorporates the 
+      limitation as if written in the body of this License.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      9. The Free Software Foundation may publish revised and/or new versions 
+      of the General Public License from time to time. Such new versions will 
+      be similar in spirit to the present version, but may differ in detail to 
+      address new problems or concerns.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Each version is given a distinguishing version number. If the Program 
+      specifies a version number of this License which applies to it and "any 
+      later version", you have the option of following the terms and 
+      conditions either of that version or of any later version published by 
+      the Free Software Foundation. If the Program does not specify a version 
+      number of this License, you may choose any version ever published by the 
+      Free Software Foundation.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      10. If you wish to incorporate parts of the Program into other free 
+      programs whose distribution conditions are different, write to the 
+      author to ask for permission. For software which is copyrighted by the 
+      Free Software Foundation, write to the Free Software Foundation; we 
+      sometimes make exceptions for this. Our decision will be guided by the 
+      two goals of preserving the free status of all derivatives of our free 
+      software and of promoting the sharing and reuse of software generally.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      NO WARRANTY
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 
+      FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 
+      OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 
+      PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 
+      EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
+      ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH 
+      YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
+      NECESSARY SERVICING, REPAIR OR CORRECTION.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 
+      WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 
+      AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
+      DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
+      DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM 
+      (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 
+      INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF 
+      THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR 
+      OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      END OF TERMS AND CONDITIONS
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      How to Apply These Terms to Your New Programs
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      If you develop a new program, and you want it to be of the greatest 
+      possible use to the public, the best way to achieve this is to make it 
+      free software which everyone can redistribute and change under these 
+      terms.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      To do so, attach the following notices to the program. It is safest to 
+      attach them to the start of each source file to most effectively convey 
+      the exclusion of warranty; and each file should have at least the 
+      "copyright" line and a pointer to where the full notice is found.
+
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      <one line to give the program's name and a brief idea of what it does.>
+
+    </p>
+    <p>
+      Copyright (C) <year> <name of author>
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      This program is free software; you can redistribute it and/or modify it 
+      under the terms of the GNU General Public License as published by the 
+      Free Software Foundation; either version 2 of the License, or (at your 
+      option) any later version.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      This program is distributed in the hope that it will be useful, but 
+      WITHOUT ANY WARRANTY; without even the implied warranty of 
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
+      Public License for more details.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      You should have received a copy of the GNU General Public License along 
+      with this program; if not, write to the Free Software Foundation, Inc., 
+      59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Also add information on how to contact you by electronic and paper mail.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      If the program is interactive, make it output a short notice like this 
+      when it starts in an interactive mode:
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Gnomovision version 69, Copyright (C) year name of author
+    </p>
+    <p>
+      Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    </p>
+    <p>
+      This is free software, and you are welcome to redistribute it under 
+      certain conditions; type `show c' for details.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      The hypothetical commands `show w' and `show c' should show the 
+      appropriate parts of the General Public License. Of course, the commands 
+      you use may be called something other than `show w' and `show c'; they 
+      could even be mouse-clicks or menu items--whatever suits your program.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      You should also get your employer (if you work as a programmer) or your 
+      school, if any, to sign a "copyright disclaimer" for the program, if 
+      necessary. Here is a sample; alter the names:
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+    </p>
+    <p>
+      `Gnomovision' (which makes passes at compilers) written by James Hacker.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      <signature of Ty Coon>, 1 April 1989
+    </p>
+    <p>
+      Ty Coon, President of Vice
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      This General Public License does not permit incorporating your program 
+      into proprietary programs. If your program is a subroutine library, you 
+      may consider it more useful to permit linking proprietary applications 
+      with the library. If this is what you want to do, use the GNU Library 
+      General Public License instead of this License.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic1/topic7.htm b/src/com/lightdev/app/shtm/help/topic1/topic7.htm
new file mode 100644
index 0000000..3c62c43
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic1/topic7.htm
@@ -0,0 +1,33 @@
+<html>
+  <head>
+    <link href="../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Author
+    </p>
+    <p>
+      SimplyHTML, this documentation and all contents of the <a href="../topic1/topic24.htm">
+distribution package</a> of SimplyHTML are created and maintained by
+    </p>
+    <p>
+      Ulrich Hilger<br>Gartenstrasse 15<br>65830 Kriftel<br>Germany
+    </p>
+    <p>
+      e-mail info at lightdev.com<br>Internet http://www.lightdev.com<br>Fax +49 
+      721 151 41 09 67
+    </p>
+    <p>
+      I would like to hear your comments and suggestions so please don't 
+      hesitate to write.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      All rights reserved. Please see chapter '<a href="../topic1/topic5.htm"> 
+      License</a>' for details.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15.htm b/src/com/lightdev/app/shtm/help/topic15.htm
new file mode 100644
index 0000000..89efbe3
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15.htm
@@ -0,0 +1,51 @@
+<html>
+  <head>
+    <link href="style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using SimplyHTML
+    </p>
+    <p>
+      Once application SimplyHTML is set up as described in chapter '<a href="topic22.htm">
+Getting started</a>', it is ready to be used. The chapters in this section 
+      describe <i>usage</i> of application SimplyHTML. For information about 
+      how the functionality mentioned in this section is achieved, please 
+      consult chapter '<a href="topic16.htm">Inside SimplyHTML</a>'. This 
+      section is divided into the following chapters
+    </p>
+    <ul>
+      <li>
+        <a href="topic15/topic116.htm">What is SimplyHTML?</a>
+      </li>
+      <li>
+        <a href="topic15/topic57.htm">Creating new documents</a>
+      </li>
+      <li>
+        <a href="topic15/topic59.htm">Opening existing documents</a>
+      </li>
+      <li>
+        <a href="topic15/topic58.htm">Saving documents</a>
+      </li>
+      <li>
+        <a href="topic15/topic60.htm">Editing documents</a>
+      </li>
+      <li>
+      	<a href="topic15/topic60a.htm">Searching Documents</a>
+      </li>
+      <li>
+        <a href="topic15/topic61.htm">Closing documents</a>
+      </li>
+      <li>
+        <a href="topic15/topic118.htm">Using plug-ins</a>
+      </li>
+    </ul>
+    <p>
+      Users might want to start with 'What is SimplyHTML' to see whether or 
+      not the application fits their needs. Besides general information about 
+      document usage in SimplyHTML the part about editing documents mentioned 
+      above takes the most room as it is the main functionality of SimplyHTML.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic116.htm b/src/com/lightdev/app/shtm/help/topic15/topic116.htm
new file mode 100644
index 0000000..d642d20
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic116.htm
@@ -0,0 +1,102 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      What is SimplyHTML?
+    </p>
+    <p>
+      As shortly described in chapter '<a href="../topic1.htm">About the 
+      SimplyHTML project</a> ', SimplyHTML is an application for text 
+      processing on the basis of HTML documents formatted with CSS. It 
+      combines functionality of a word processor with the standards of HTML 
+      and CSS.
+    </p>
+    <p>
+      Usage of the HTML and CSS standard for documents created with SimplyHTML 
+      opens a wide variety of usage possibilities because many other 
+      applications 'understand' and use HTML and CSS such as
+    </p>
+    <ul>
+      <li>
+        web browsers
+      </li>
+      <li>
+        other text processors
+      </li>
+      <li>
+        presentation and graphics software
+      </li>
+    </ul>
+    <p class="heading2">
+      Features
+    </p>
+    <p>
+      SimplyHTML features the following functionality
+    </p>
+    <ul>
+      <li>
+        opens, maintains and saves documents in HTML and CSS format
+      </li>
+      <li>
+        any number of documents can be opened at the same time and are 
+        displayed in a tabbed pane
+      </li>
+      <li>
+        formatting of paragraph styles
+      </li>
+      <li>
+        creation of own named styles for paragraphs
+      </li>
+      <li>
+        formatting of font attributes on character level
+      </li>
+      <li>
+        rich table formatting
+      </li>
+      <li>
+        list formatting
+      </li>
+      <li>
+        insertion and formatting of JPEG and GIF images
+      </li>
+      <li>
+        creation and manipulation of links and link anchors
+      </li>
+      <li>
+        drag and drop in the editor pane
+      </li>
+      <li>
+        cut and paste for styled HTML text
+      </li>
+      <li>
+        cascading undo/redo
+      </li>
+      <li>
+        plug-in facility for extension of SimplyHTML
+      </li>
+      <li>
+        support of Java Web Start for easy deployment
+      </li>
+      <li>
+        editor for HTML code with syntax highlighting
+      </li>
+    </ul>
+    <p>
+      See '<a href="../topic16/topic112.htm">Planned development stages</a>' 
+      for additional features to be present in future.
+    </p>
+    <p class="heading2">
+      Differences of HTML and CSS in various environments
+    </p>
+    <p>
+      SimplyHTML tries to consequently adhere to HTML and CSS standards. 
+      However, there are discrepancies over different environments, which 
+      sometimes can be compensated, sometimes only partly or not at all. 
+      Please see chapter '<a href="../topic16/topic34/topic115.htm"> 
+      Discrepancies in HTML and CSS rendering</a>' on that subject too.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic118.htm b/src/com/lightdev/app/shtm/help/topic15/topic118.htm
new file mode 100644
index 0000000..92a38fd
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic118.htm
@@ -0,0 +1,78 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using plug-ins
+    </p>
+    <p>
+      SimplyHTML provides a mechanism to extend the main editing 
+      functionalities of the application by external objects called 
+      'plug-ins'. Plug-ins are installed by copying one or more plug-in files 
+      into the directory SimplyHTML is installed in. Once installed, a plug-in 
+      is loaded and activated inside SimplyHTML upon start of the application 
+      by default.
+    </p>
+    <p class="heading2">
+      Accessing plug-in functions
+    </p>
+    <p>
+      Each plug-in provides an own menu in menu 'Plugin' of SimplyHTML where 
+      all plug-in functionality is available. In addition there usually is a 
+      menu item in the 'Help' menu having documentation on the plug-in.
+    </p>
+    <p>
+      To access the functions of a plug-in
+    </p>
+    <ul>
+      <li>
+        open menu 'Plugin'
+      </li>
+      <li>
+        open the sub-menu for respective plug-in
+      </li>
+    </ul>
+    <p>
+      To access help information for a given plug-in
+    </p>
+    <ul>
+      <li>
+        open menu 'Help'
+      </li>
+      <li>
+        select the menu item referring to help for a given plug-in
+      </li>
+    </ul>
+    <p class="heading2">
+      Activating and de-activating plug-ins
+    </p>
+    <p>
+      Loaded plug-ins can be activated or deactivated for each user 
+      individually. As well the location where a plug-in is docked inside 
+      SimplyHTML's main window can be changed. To change the settings of any 
+      loaded plug-in
+    </p>
+    <ul>
+      <li>
+        select 'Manage plug-ins...' from menu 'Plugin'
+      </li>
+      <li>
+        choose a plug-in from the list of loaded plug-ins
+      </li>
+      <li>
+        adjust settings accordingly and
+      </li>
+      <li>
+        press 'Close'
+      </li>
+    </ul>
+    <p>
+      The settings are applied to respective plug-ins and are stored 
+      individually for the user who made the changes. See <a href="../topic16/topic103.htm">
+respective chapter</a> in section 'Inside SimplyHTML' if you would like to 
+      know more about plug-ins.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic163.htm b/src/com/lightdev/app/shtm/help/topic15/topic163.htm
new file mode 100644
index 0000000..22c9f5d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic163.htm
@@ -0,0 +1,35 @@
+<html>
+  <head>
+    <link href="../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      User interface
+    </p>
+    <p>
+      This chapter explains parts of the user interface of application 
+      SimplyHTML. The chapter describes from the perspective of certain parts 
+      of the GUI (e.g. a dialog) as opposed to previous chapters explaining 
+      parts of the application from a functional perspective (e.g. 'how to 
+      save a file').
+    </p>
+    <p>
+      This section covers of the following GUI parts of application SimplyHTML
+    </p>
+    <ul>
+      <li>
+        <a href="../topic15/topic163/topic164.htm">Link dialog</a>
+      </li>
+      <li>
+        <a href="../topic15/topic163/topic165.htm">Link anchor dialog</a>
+      </li>
+      <li>
+        <a href="../topic15/topic163/topic166.htm">Image dialog</a>
+      </li>
+      <li>
+        <a href="../topic15/topic163/topic167.htm">Options dialog</a>
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic163/topic164.htm b/src/com/lightdev/app/shtm/help/topic15/topic163/topic164.htm
new file mode 100644
index 0000000..60a0c09
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic163/topic164.htm
@@ -0,0 +1,162 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Link dialog
+    </p>
+    <p>
+      In the link dialog all link attributes are shown and can be changed (see 
+      also '<a href="../../topic15/topic60/topic159.htm">Creating and 
+      manipulating links</a>').
+    </p>
+    <p>
+      
+    </p>
+    <p style=" text-align:center;">
+      <img height="331" src="../../images/linkDlg.jpg" width="431">
+      
+    </p>
+    <p class="image_subtitle">
+      the link dialog
+    </p>
+    <p>
+      
+    </p>
+    <p class="heading2">
+      Style
+    </p>
+    <p>
+      Combo box <font face="'Courier New',Monospaced,Monospace">Style</font> 
+      allows to set by which named style the link shall be formatted in the 
+      editor. Any existing <a href="../../topic15/topic60/topic139.htm">named 
+      style</a> from the associated style sheet is listed in this combo box.
+    </p>
+    <p class="heading2">
+      Type
+    </p>
+    <p>
+      With combo box <font face="'Courier New',Monospaced,Monospace">Type</font>
+ a <a href="../../topic16/topic152/topic153.htm">link type</a> can be set such 
+      as 'local file', 'relative address', 'mailto', etc. Other elements of 
+      the link dialog are enabled or disabled according to selections in combo 
+      box <font face="'Courier New',Monospaced,Monospace">Type</font>.
+    </p>
+    <p>
+      When switching between types 'local' and 'relative' or vice versa, 
+      contents of text field Address is automatically changed accordingly 
+      (relative or absolute address snytax),
+    </p>
+    <p class="heading2">
+      Address
+    </p>
+    <p>
+      In text field <font face="'Courier New',Monospaced,Monospace">Address</font>
+ the address of the link target is shown. An address can be typed into this 
+      field at any time. No <a href="../../topic16/topic152/topic153.htm">
+      protocol</a> such as <font face="'Courier New',Monospaced,Monospace">
+      telnet:/</font> or <font face="'Courier New',Monospaced,Monospace">file:/</font>
+ needs to be typed into field <font face="'Courier New',Monospaced,Monospace">
+      Address</font>. The protocol information is automatically generated from 
+      the selection in combo box <font face="'Courier New',Monospaced,Monospace">
+Type</font>.
+    </p>
+    <p class="heading2">
+      Browse (Address)
+    </p>
+    <p>
+      With button <font face="'Courier New',Monospaced,Monospace">Browse</font>
+       next to text field <font face="'Courier New',Monospaced,Monospace">
+      Address</font> a local file can be selected through a file chooser 
+      dialog. This button is enabled, if '<font face="'Courier New',Monospaced,Monospace">
+local'</font> is selected in combo box <font face="'Courier New',Monospaced,Monospace">
+Type</font>.
+    </p>
+    <p class="heading2">
+      Anchor
+    </p>
+    <p>
+      In text field <font face="'Courier New',Monospaced,Monospace">Anchor</font>
+ the name of a link anchor can be entered (see also '<a href="../../topic15/topic60/topic162.htm">
+Creating and deleting anchor links</a>'). The entered anchor name refers to an 
+      anchor link inside the target referred to by the entry in text field <font face="'Courier New',Monospaced,Monospace">
+Address</font>. The separator character <font face="'Courier New',Monospaced,Monospace">
+(</font><font face="Sans-Serif">#</font><font face="'Courier New',Monospaced,Monospace">
+)</font> for link anchor names does not need to be entered, it is completed 
+      automatically by the link dialog.
+    </p>
+    <p class="heading2">
+      Browse (Anchor)
+    </p>
+    <p>
+      With button <font face="'Courier New',Monospaced,Monospace">Browse</font>
+       next to text field <font face="'Courier New',Monospaced,Monospace">
+      Anchor</font> an existing link anchor can be selected or a new link 
+      anchor can be defined throgh the <a href="../../topic15/topic163/topic165.htm">
+link anchor dialog</a>. The link anchor dialog is shown for the link targed 
+      specified in text field <font face="'Courier New',Monospaced,Monospace">
+      Address</font>.
+    </p>
+    <p class="heading2">
+      Show link as Text
+    </p>
+    <p>
+      With button <font face="'Courier New',Monospaced,Monospace">Show link as 
+      Text</font> is selected that the link specified in this dialog is to be 
+      entered as a text link into the associated document. When this button is 
+      selected, panel <font face="'Courier New',Monospaced,Monospace">Text</font>
+ will be shown.
+    </p>
+    <p class="heading2">
+      Text panel
+    </p>
+    <p>
+      In panel <font face="'Courier New',Monospaced,Monospace">Text</font> a 
+      text can be entered that is to be formatted as link. Panel <font face="'Courier New',Monospaced,Monospace">
+Text</font> is only visible, if button Show link as Text has been selected.
+    </p>
+    <p class="heading2">
+      Show link as Image
+    </p>
+    <p>
+      With button <font face="'Courier New',Monospaced,Monospace">Show link as 
+      Image</font> is selected that the link specified in this dialog is to be 
+      entered as an image link into the associated document.
+    </p>
+    <p class="heading2">
+      Image Panel
+    </p>
+    <p>
+      In panel <font face="'Courier New',Monospaced,Monospace">Image</font> an 
+      image and image size can be selected. The selected image will be shown 
+      in the associated document as link. All image settings in panel <font face="'Courier New',Monospaced,Monospace">
+Image</font> are only <i>shown</i>. They can be set or changed through button <font face="'Courier New',Monospaced,Monospace">
+Set...</font>.
+    </p>
+    <p>
+      
+    </p>
+    <p style=" text-align:center;">
+      <img height="173" src="../../images/linkImgPnl.jpg" width="327">
+      
+    </p>
+    <p class="image_subtitle">
+      the link image panel
+    </p>
+    <p>
+      
+    </p>
+    <p class="heading3">
+      Button Set...
+    </p>
+    <p>
+      All image properties in panel <font face="'Courier New',Monospaced,Monospace">
+Image</font> are set through button <font face="'Courier New',Monospaced,Monospace">
+Set...</font> which will bring up an <a href="../../topic15/topic163/topic166.htm">
+image dialog</a>. In the image dialog an image file and its size can be 
+      selected accordingly.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic163/topic165.htm b/src/com/lightdev/app/shtm/help/topic15/topic163/topic165.htm
new file mode 100644
index 0000000..d95e4c2
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic163/topic165.htm
@@ -0,0 +1,78 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Link anchor dialog
+    </p>
+    <p>
+      The link anchor dialog allows to <a href="../../topic15/topic60/topic162.htm">
+create and remove link anchors</a> for a document. It is shown with either the 
+      document that is currently edited (when opened through menu 'Format') or 
+      with the document targeted in a link (through the <a href="../../topic15/topic163/topic164.htm">
+link dialog</a>).
+    </p>
+    <p>
+      
+    </p>
+    <p style=" text-align:center;">
+      <img height="332" src="../../images/anchrDlg.jpg" width="409">
+      
+    </p>
+    <p class="image_subtitle">
+      the link anchor dialog
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      
+    </p>
+    <p class="heading2">
+      Defined anchors panel
+    </p>
+    <p>
+      In panel <font face="'Courier New',Monospaced,Monospace">defined anchors</font>
+ all existing link anchors for the shown document are listed. Clicking one 
+      link anchor name in panel <font face="'Courier New',Monospaced,Monospace">
+defined anchors</font> highlights the position of that link anchor in panel <font face="'Courier New',Monospaced,Monospace">
+Document</font>.
+    </p>
+    <p class="heading2">
+      Add
+    </p>
+    <p>
+      Clicking button <font face="'Courier New',Monospaced,Monospace">Add</font>
+ will show an input dialog to enter a name for a new link anchor to create. 
+      Button <font face="'Courier New',Monospaced,Monospace">Add</font> is 
+      only enabled when a portion of text is selected in panel <font face="'Courier New',Monospaced,Monospace">
+Document</font>. The new link anchor will be created for the position selected 
+      in panel <font face="'Courier New',Monospaced,Monospace">Document</font>.
+    </p>
+    <p class="heading2">
+      Delete
+    </p>
+    <p>
+      When button <font face="'Courier New',Monospaced,Monospace">Delete</font>
+       is clicked, the selected link anchor is removed from the assocated 
+      document. Button <font face="'Courier New',Monospaced,Monospace">Delete</font>
+ is only enabled when a link anchor is selected in the <font face="'Courier New',Monospaced,Monospace">
+defined anchors</font> panel.
+    </p>
+    <p class="heading2">
+      Document panel
+    </p>
+    <p>
+      Panel <font face="'Courier New',Monospaced,Monospace">Document</font> 
+      shows the document this link anchor dialog allows to set link anchors 
+      for. In the shown document, the currently selected link anchor is 
+      highlighted. If a new link anchor is to be created, panel <font face="'Courier New',Monospaced,Monospace">
+Document</font> is used to select the text to formatted as a link anchor first.
+    </p>
+    <p>
+      
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic163/topic166.htm b/src/com/lightdev/app/shtm/help/topic15/topic163/topic166.htm
new file mode 100644
index 0000000..01eb978
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic163/topic166.htm
@@ -0,0 +1,135 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Image dialog
+    </p>
+    <p>
+      The image dialog is used to add images to a document and change 
+      attribute settings for such image. It also allows to maintain the image 
+      repository a document is associated to. See also chapter '<a href="../../topic15/topic60/topic135.htm">
+Working with images</a>' about how images are applied to documents.
+    </p>
+    <p>
+      
+    </p>
+    <p style=" text-align:center;">
+      <img height="402" src="../../images/imgDlg.jpg" width="487">
+      
+    </p>
+    <p class="image_subtitle">
+      the image dialog
+    </p>
+    <p>
+      
+    </p>
+    <p class="heading2">
+      Image files panel
+    </p>
+    <p>
+      In panel image files all files are shown that are stored in the <a href="../../topic16/topic128/topic129.htm">
+image repository</a> that is associated to the currently edited document. 
+      Clicking on one image file name listed in panel Image files shows the 
+      image in panel Preview and lists image attributes in panel Properties.
+    </p>
+    <p class="heading3">
+      Add
+    </p>
+    <p>
+      Press button Add to add a new image file to the repository. A file 
+      chooser dialog will appear to select a file from. The selected file is 
+      copied into the image repository associated with the document and 
+      displayed in pnale Image Files.
+    </p>
+    <p class="heading3">
+      Delete
+    </p>
+    <p>
+      Button Delete is used to remove a file from the image repository. 
+      Respective file is permanently deleted from the directory used as an 
+      image repository.
+    </p>
+    <p>
+      <b>Note</b>: All references to the deleted image in any document 
+      associated to this image repository will be 'broken' when deleting an 
+      image from the repository.
+    </p>
+    <p class="heading2">
+      Preview panel
+    </p>
+    <p>
+      Panel Preview displays an image selected in panel Image files. An image 
+      is scaled to the current size of the preview area when initially 
+      displayed. When image attributes are changed in panel Properties, the 
+      image size changes accordingly. The size of the preview area remains 
+      unchanged and scroll bars are shown when an image does not fit into the 
+      preview area. The size of the preview area can be changed by resizing 
+      the dialog window. In this case the image size remains the same and only 
+      the size of the preview area changes along with the window size.
+    </p>
+    <p class="heading2">
+      Properties panel
+    </p>
+    <p>
+      In panel Properties attributes of the image currently displayed in panel 
+      Preview are shown. Changes to image attributes in panel Properties 
+      directly affect the image shown in panel Preview, i.e. the image changes 
+      in size accordingly.
+    </p>
+    <p class="heading3">
+      Scale
+    </p>
+    <p>
+      Use this control to enter a value by which the size of the image is to 
+      be scaled. Size is scaled proportionally, i.e. the relation of width and 
+      height is always kept.
+    </p>
+    <p class="heading3">
+      Width
+    </p>
+    <p>
+      Use this control to set a width for the image. Height and scale are 
+      adjusted accordingly.
+    </p>
+    <p class="heading3">
+      Height
+    </p>
+    <p>
+      Use this control to set a height for the image. Width and scale are 
+      adjusted accordingly.
+    </p>
+    <p class="heading3">
+      Horiz. Space
+    </p>
+    <p>
+      This field can be used to set a value for space between the image and 
+      objects on the left and right of the image.
+    </p>
+    <p class="heading3">
+      Vert. Space
+    </p>
+    <p>
+      This field can be used to set a value for space between the image and 
+      objects on top and bottom of the image.
+    </p>
+    <p class="heading3">
+      Alignment
+    </p>
+    <p>
+      Alignment controls how the image is to be aligned relative to other 
+      objects, i.e. an alignment setting of left aligns the image left of any 
+      other objects. (This setting is modeled but not rendered in SimplyHTML)
+    </p>
+    <p class="heading3">
+      Border
+    </p>
+    <p>
+      Set the width of a border around the image. A setting of 0 means no 
+      border, any other value means a border around the image in the specified 
+      width.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic163/topic167.htm b/src/com/lightdev/app/shtm/help/topic15/topic163/topic167.htm
new file mode 100644
index 0000000..7eed9bb
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic163/topic167.htm
@@ -0,0 +1,77 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Options dialog
+    </p>
+    <p>
+      The options dialog allows to set general preferences for application 
+      SimplyHTML. All settings are persistently stored for each individual 
+      user and reinstated when SimplyHTML is launched.
+    </p>
+    <p>
+      
+    </p>
+    <p style=" text-align:center;">
+      <img height="221" src="../../images/optDlg.jpg" width="251">
+      
+    </p>
+    <p style=" text-align:center;" class="image_subtitle">
+      the options dialog
+    </p>
+    <p class="heading2">
+      Look and feel
+    </p>
+    <p>
+      A feature of the Java[tm] platform is its 'pluggable look and feel' 
+      concept. With this setting the user can select a look and feel from 
+      those installed on the machine SimplyHTML is running on.
+    </p>
+    <p class="heading2">
+      Write HTML files as HTML 3.2
+    </p>
+    <p>
+      Setting this option causes SimplyHTML to create document files in HTML 
+      3.2. This means that some features from later HTML versions are not 
+      available such as certain CSS formats and HTML tags. Setting this option 
+      is useful for environments that require HTML 3.2 such as JavaHelp.
+    </p>
+    <p class="heading2">
+      Write HTML files as HTML 4
+    </p>
+    <p>
+      Setting this option causes SimplyHTML to create documents in HTML 4. 
+      This enables certain formatting features such as individual table 
+      borders or background coloring for individual parts of text.
+    </p>
+    <p class="heading2">
+      Link new documents with default style sheet
+    </p>
+    <p>
+      Usually a reference between a document and a style sheet containing 
+      named styles is only created when <a href="../../topic15/topic60/topic139.htm">
+named styles are added to a document explicitly</a>. In cases where a new 
+      document shall use an existing style sheet which was previously created 
+      for another document, this option can be used.
+    </p>
+    <p>
+      Selecting this option causes creation of a style sheet reference in 
+      newly created documents linking to the default style sheet ('<font face="'Courier New',Monospaced,Monospace">
+style.css</font>'). File '<font face="'Courier New',Monospaced,Monospace"> 
+      style.css</font>' always is created by SimplyHTML, when <a href="../../topic15/topic60/topic139.htm">
+named styles are added to a document</a>.
+    </p>
+    <p>
+      When a new document is created with this option selected, the style 
+      sheet reference to '<font face="'Courier New',Monospaced,Monospace"> 
+      style.css</font>' is included in the new document upon creation even 
+      without named styles being defined for the new document so far. The new 
+      document has then to be saved to the directory where respective file '<font face="'Courier New',Monospaced,Monospace">
+style.css</font>' is already located for the styles from '<font face="'Courier New',Monospaced,Monospace">
+style.css</font>' to be in effect in the new document.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic163/topic181.htm b/src/com/lightdev/app/shtm/help/topic15/topic163/topic181.htm
new file mode 100644
index 0000000..aa1a09d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic163/topic181.htm
@@ -0,0 +1,140 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+<title>Find and replace dialog</title>  </head>
+  <body>
+    <p class="heading1">
+      Find and replace dialog
+    </p>
+    <p>
+      Find and replace is done in a dialog window where all relevant options 
+      can be set:
+    </p>
+    <p style=" text-align:center;">
+      <img src="../../images/fr.jpg" width="426" height="235">
+      
+    </p>
+    <p class="image_subtitle">
+      the find and replace dialog
+    </p>
+    <p>
+      
+    </p>
+    <p class="heading2">
+      Text to find
+    </p>
+    <p>
+      In field <font face="'Courier New',Monospaced,Monospace">Text to find</font>
+ an arbitrary text phrase can be entered. This text phrase will be searched 
+      during a find or replace operation.
+    </p>
+    <p class="heading2">
+      Replace with
+    </p>
+    <p>
+      In field <font face="'Courier New',Monospaced,Monospace">Replace with</font>
+ a text phrase is entered that is to replace the text phrase entered in field 
+      Text to find.
+    </p>
+    <p class="heading2">
+      Find next...
+    </p>
+    <p>
+      Button <font face="'Courier New',Monospaced,Monospace">Find next...</font>
+ is pressed to initiate a find operation with the settings currently selected 
+      in the find and replace dialog.
+    </p>
+    <p class="heading2">
+      Replace...
+    </p>
+    <p>
+      By pressing button <font face="'Courier New',Monospaced,Monospace">
+      Replace...</font> a replace operation is initiated. The find and replace 
+      dialog is hidden and the next occurrence of the phrase in field <font face="'Courier New',Monospaced,Monospace">
+Text to find</font> is located. When found, an option pane lets the user 
+      choose whether or not the found occurrence shall be replaced by the 
+      phrase in field <font face="'Courier New',Monospaced,Monospace">Replace 
+      with</font>. Alternately the user can choose to replace all occurrences 
+      or to terminate the replace operation. Once done, the find and replace 
+      dialog appears again.
+    </p>
+    <p class="heading2">
+      Cancel
+    </p>
+    <p>
+      Button <font face="'Courier New',Monospaced,Monospace">Cancel</font> is 
+      used to terminate a find operation. It is only enabled (not dimmed) when 
+      a find operation is in progress (button <font face="'Courier New',Monospaced,Monospace">
+Find next...</font> has been pressed). With pressing button <font face="'Courier New',Monospaced,Monospace">
+Cancel</font> the current find operation is terminated and the find and 
+      replace dialog can be used to start a new find and replace operation 
+      with different settings.
+    </p>
+    <p class="heading2">
+      Close
+    </p>
+    <p>
+      With button <font face="'Courier New',Monospaced,Monospace">Close</font> 
+      the find and replace dialog is closed.
+    </p>
+    <p class="heading2">
+      Whole words only
+    </p>
+    <p>
+      Option <font face="'Courier New',Monospaced,Monospace">Whole words only</font>
+ is used to restrict matches to whole words. When not selected all occurrences 
+      of the phrase in field <font face="'Courier New',Monospaced,Monospace">
+      Text to find</font> are located even when they are found as part of a 
+      word.
+    </p>
+    <p class="heading2">
+      Match case
+    </p>
+    <p>
+      By selecting option <font face="'Courier New',Monospaced,Monospace">
+      Match case</font> a find operation only locates occurence of the phrase 
+      in field <font face="'Courier New',Monospaced,Monospace">Text to find</font>
+ when they match the exact case.
+    </p>
+    <p class="heading2">
+      Search from start
+    </p>
+    <p>
+      Selection of option <font face="'Courier New',Monospaced,Monospace">
+      Search from start</font> causes a find operation to begin either at the 
+      first or last position of the particular document regardless of the 
+      current caret position, depending on setting <font face="'Courier New',Monospaced,Monospace">
+Search up</font> and <font face="'Courier New',Monospaced,Monospace">Search 
+      down</font> respectively.
+    </p>
+    <p class="heading2">
+      Search whole project
+    </p>
+    <p>
+      Option <font face="'Courier New',Monospaced,Monospace">Search whole 
+      project</font> is only visible when more than one document is open at 
+      the moment. With selection of option <font face="'Courier New',Monospaced,Monospace">
+Search whole project</font> all documents are searched that are currently open.
+    </p>
+    <p class="heading2">
+      Search up
+    </p>
+    <p>
+      Option <font face="'Courier New',Monospaced,Monospace">Search up</font> 
+      causes the search to be performed from bottom to top of any given 
+      document.
+    </p>
+    <p class="heading2">
+      Search down
+    </p>
+    <p>
+      Option <font face="'Courier New',Monospaced,Monospace">Search down</font>
+       causes the search to be performed from top to bottom of any given 
+      document.
+    </p>
+    <p>
+      
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic57.htm b/src/com/lightdev/app/shtm/help/topic15/topic57.htm
new file mode 100644
index 0000000..66817be
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic57.htm
@@ -0,0 +1,41 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating new documents
+    </p>
+    <p>
+      To create a new empty document
+    </p>
+    <ul>
+      <li>
+        select 'New' from menu 'File'
+      </li>
+    </ul>
+    <p>
+      A new tab in the main frame of SimplyHTML will be opened with a new 
+      empty and untitled document to work with. All other open documents 
+      remain open which is indicated by respective tabs identifying other open 
+      documents. The display switches to the newly created document with its 
+      tab on top.
+    </p>
+    <p>
+      The document is now ready to be <a href="../topic15/topic60.htm">edited</a>
+ .
+    </p>
+    <p class="heading2">
+      Using an existing style sheet for new documents
+    </p>
+    <p>
+      Usually a reference between a document and a style sheet containing 
+      named styles is only created when named styles are added to a document 
+      explicitly. In cases where a new document shall use an existing style 
+      sheet which was previously created for another document, option 'Link 
+      new documents with default style sheet' has to be set in the <a href="../topic15/topic163/topic167.htm">
+options dialog</a>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic58.htm b/src/com/lightdev/app/shtm/help/topic15/topic58.htm
new file mode 100644
index 0000000..61cdf02
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic58.htm
@@ -0,0 +1,105 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Saving documents
+    </p>
+    <p>
+      To save a document, it has to be visible as the currently edited 
+      document. To save this document
+    </p>
+    <ul>
+      <li>
+        select 'Save' from menu 'File'
+      </li>
+    </ul>
+    <p>
+      The document will be saved at the location it was openend from. If 
+      respective document was newly created and thus not saved so far, you 
+      will be prompted for a location and file name for the document as with 
+      saving a document under a different name (see below).
+    </p>
+    <p>
+      <b>Important</b>: You have to enter a file name including extension 
+      (.htm or .html). The extension will not be completed by the application 
+      if it was omitted.
+    </p>
+    <p>
+      <b>Note</b>: Documents are opened using the HTML version set in the <a href="../topic15/topic163/topic167.htm">
+options dialog</a>. Unless set otherwise, HTML 3.2 is used as the default.
+    </p>
+    <p class="heading3">
+      Image directory
+    </p>
+    <p>
+      Along with the document file, an <a href="../topic15/topic60/topic135.htm">
+image directory</a> is created with any image file referenced in the saved 
+      document.
+    </p>
+    <p class="heading3">
+      Style sheet maintenance
+    </p>
+    <p>
+      If <a href="../topic15/topic60/topic139.htm">named styles were created 
+      or changed</a> for a document, a style sheet will be created during the 
+      save process if none is already present. If a style sheet with the same 
+      name is found at the target location, it is <a href="../topic16/topic140/topic150.htm">
+merged</a> with the style sheet to be saved. Instead of defining named styles 
+      for a document and merging them with an existing style sheet, a new 
+      document can also use an existing style sheet right away. See '<a href="../topic15/topic57.htm">
+Creating new documents</a>' and chapter '<a href="../topic15/topic163/topic167.htm">
+Options dialog</a>' for an explanation about this option.
+    </p>
+    <p>
+      <b>Caution</b>: An existing style sheet with the same name could have 
+      styles with the same name as altered ones in the saved style sheet. 
+      Overwriting such styles could cause unwanted styles to appear in other 
+      documents sharing the particular style sheet.
+    </p>
+    <p>
+      Therefore you should consider to either
+    </p>
+    <ol>
+      <li>
+        not save documents in the same directory when they do not share the 
+        same set of named styles or
+      </li>
+      <li>
+        use different style names for different styles over all documents 
+        sharing the same style sheet
+      </li>
+    </ol>
+    <p class="heading2">
+      Saving a document under a different name
+    </p>
+    <p>
+      To save a document under a different name or at a different location 
+      than where it has been openend from
+    </p>
+    <ul>
+      <li>
+        select 'Save as...' from menu 'File'
+      </li>
+      <li>
+        choose a new location and/or new file name and
+      </li>
+      <li>
+        press 'Save'
+      </li>
+    </ul>
+    <p>
+      Respective document again has to be visible as the currently edited 
+      document.
+    </p>
+    <p>
+      The document will be saved at the chosen location under the given file 
+      name. The original document remains intact at the original location but 
+      SimplyHTML switches the current document to be the newly saved one so 
+      subsequent save operations go to that file unless explicitly changed 
+      again.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic59.htm b/src/com/lightdev/app/shtm/help/topic15/topic59.htm
new file mode 100644
index 0000000..fb100ae
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic59.htm
@@ -0,0 +1,40 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Opening existing documents
+    </p>
+    <p>
+      To open an existing document
+    </p>
+    <ul>
+      <li>
+        select 'Open...' from menu 'File',
+      </li>
+      <li>
+        choose a document file to open from the selection frame possibly by 
+        navigating to a different location than initially shown
+      </li>
+      <li>
+        press 'Open'
+      </li>
+    </ul>
+    <p>
+      A new tab in the main frame of SimplyHTML will be opened with the chosen 
+      document opened into it. All other open documents remain open which is 
+      indicated by respective tabs identifying other open documents. The 
+      display switches to the opened document with its tab on top.
+    </p>
+    <p>
+      The document is now ready to be <a href="../topic15/topic60.htm">edited</a>
+ .
+    </p>
+    <p>
+      <b>Note</b>: Documents are opened using the HTML version set in the <a href="../topic15/topic163/topic167.htm">
+options dialog</a>. Unless set otherwise, HTML 3.2 is used as the default.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60.htm b/src/com/lightdev/app/shtm/help/topic15/topic60.htm
new file mode 100644
index 0000000..0fd5651
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60.htm
@@ -0,0 +1,54 @@
+<html>
+  <head>
+    <link href="../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Editing documents
+    </p>
+    <p class="standard">
+      The main functionality of SimplyHTML is to create and manipulate text so 
+      editing an existing text is a main part of this documentation as well. 
+      In this section all editing functions are explained in detail. They are 
+      divided into the follwing topics.
+    </p>
+    <ul>
+      <li>
+        <a href="../topic15/topic60/topic127.htm">Common edit functions</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic85.htm">Changing font settings</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic102.htm">Creating and manipulating 
+        tables</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic126.htm">Creating and manipulating 
+        lists</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic135.htm">Working with images</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic138.htm">Changing paragraph styles</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic139.htm">Creating and manipulating 
+        named styles</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic159.htm">Creating and manipulating 
+        links</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic162.htm">Creating and deleting anchor 
+        links</a>
+      </li>
+      <li>
+        <a href="../topic15/topic60/topic160.htm">Setting the element type</a>
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic102.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic102.htm
new file mode 100644
index 0000000..d13a092
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic102.htm
@@ -0,0 +1,89 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating and manipulating tables
+    </p>
+    <p>
+      To create a table,
+    </p>
+    <ul>
+      <li>
+        move the caret to the location where the table shall be inserted
+      </li>
+      <li>
+        select 'Table...' from menu 'Insert'
+      </li>
+      <li>
+        choose the number of columns the new table initially shall have and
+      </li>
+      <li>
+        press 'OK'
+      </li>
+    </ul>
+    <p>
+      A new table with a single row and the chosen number of columns will be 
+      inserted at the caret postion. The caret is placed into the first cell 
+      of the new table.
+    </p>
+    <p class="heading2">
+      Caret movement inside tables
+    </p>
+    <p>
+      By pressing the TAB key, the caret is moved into the next cell. Pressing 
+      SHIFT TAB moves the caret to the previous cell. Pressing the TAB key 
+      while the caret is in the last cell of the table will append a new row 
+      before moving to the next cell.
+    </p>
+    <p class="heading2">
+      Changing the table structure
+    </p>
+    <p>
+      Structural changes include inserting or appending rows and columns and 
+      deleting rows and columns. To change the table strucutre
+    </p>
+    <ul>
+      <li>
+        move the caret into the table and
+      </li>
+      <li>
+        select an option from menu 'Table' accordingly
+      </li>
+    </ul>
+    <p>
+      Rows and columns always are inserted before the current caret position. 
+      Column widths are adjusted to maintain the table width.
+    </p>
+    <p class="heading2">
+      Changing the table format
+    </p>
+    <p>
+      Table format includes all attributes of the table and its cells such as 
+      table width, cell width, background color of cells, text alignment 
+      inside cells, margins and borders, etc. To change the table format
+    </p>
+    <ul>
+      <li>
+        move the caret into a table,
+      </li>
+      <li>
+        select 'Table...' from menu 'Format',
+      </li>
+      <li>
+        set table and cell attributes in the table format dialog and
+      </li>
+      <li>
+        press 'OK'
+      </li>
+    </ul>
+    <p>
+      The table dialog initially shows all attributes currently set for that 
+      table. All changes made are applied to the underlying table at once when 
+      button 'OK' is pressed. Cell attributes can be applied to the current 
+      cell, the current row, the current column or to all cells.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic126.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic126.htm
new file mode 100644
index 0000000..e4f03cb
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic126.htm
@@ -0,0 +1,88 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating and manipulating lists
+    </p>
+    <p>
+      Lists are a consecutive amount of paragraphs being displayed with a 
+      symbol separating each paragraph at the beginning. There can be ordered 
+      lists, which follow an order such as <font face="'Courier New',Monospaced,Monospace">
+1., 2., 3., 4.</font> or <font face="'Courier New',Monospaced,Monospace">a., 
+      b., c., d.</font> and unordered lists following no specific order such 
+      as lists with a bullet symbol at the beginning of each paragraph.
+    </p>
+    <p>
+      Lists can be created in two ways
+    </p>
+    <ol>
+      <li>
+        start list formatting and then type content in the form of list items 
+        as needed or
+      </li>
+      <li>
+        type in content and then switch on list formatting for recently typed 
+        paragraphs
+      </li>
+    </ol>
+    <p class="heading2">
+      Turning list formatting on or off
+    </p>
+    <p>
+      To turn list formatting on or off
+    </p>
+    <ul>
+      <li>
+        place the caret to the position list formatting shall be switched on 
+        or off or
+      </li>
+      <li>
+        select a text portion for which list formatting shall be switched on 
+        or off and
+      </li>
+      <li>
+        select 'Bulleted list on/off' or 'Numbered list on/off' from menu 
+        'Format'
+      </li>
+    </ul>
+    <p>
+      Alternately, respective toggle buttons in the tool bar can be used as 
+      well.
+    </p>
+    <p class="heading2">
+      Caret movement inside lists
+    </p>
+    <p>
+      While typing text, the caret moves similar to a region not being 
+      formatted as list. Pressing [Enter] while the caret is inside a list 
+      will create a new list item after the item the caret is currently in.
+    </p>
+    <p class="heading2">
+      Changing the list formatting
+    </p>
+    <p>
+      List format can be changed individually through a list format dialog 
+      too. The list format dialog can be used to change the list type 
+      (bulleted, numbered, bullet symbol and order criteria) as well as the 
+      indentation of a list. To change list formatting individually
+    </p>
+    <ul>
+      <li>
+        select the the text portion to change list formatting for
+      </li>
+      <li>
+        select 'List...' from menu 'Format'
+      </li>
+      <li>
+        make settings in the list format dialog and
+      </li>
+      <li>
+        press 'OK'
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic127.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic127.htm
new file mode 100644
index 0000000..634f18c
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic127.htm
@@ -0,0 +1,34 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Common edit functions
+    </p>
+    <p>
+      SimplyHTML implements the common edit functions such as cut, copy and 
+      paste as usualy with any text processing application. They are available 
+      through menu 'Edit'.
+    </p>
+    <p>
+      To cut, copy or paste contents of SimplyHTML documents
+    </p>
+    <ul>
+      <li>
+        select a text portion and
+      </li>
+      <li>
+        choose an option from menu 'Edit'
+      </li>
+    </ul>
+    <p>
+      Cut, copy and paste are performed including styles. In addition, the 
+      editor of SimplyHTML has drag and drop capabilities, by which the same 
+      functionality can be reached simply by selecting, clicking and dragging 
+      certain text portions.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic135.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic135.htm
new file mode 100644
index 0000000..599551d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic135.htm
@@ -0,0 +1,123 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Working with images
+    </p>
+    <p>
+      In line with the <a href="../../topic16/topic128/topic134.htm">HTML 
+      specification for image references</a>, images can be added to any 
+      document of application SimplyHTML by inserting references to separate 
+      image files. To insert an image
+    </p>
+    <ul>
+      <li>
+        place the caret to the point in the document where an image shall 
+        appear
+      </li>
+      <li>
+        select 'Image...' from menu 'Insert'
+      </li>
+      <li>
+        in the <a href="../../topic15/topic163/topic166.htm">image dialog</a> 
+        press button 'Add'
+      </li>
+      <li>
+        locate the file containing the image in the file chooser
+      </li>
+      <li>
+        press 'OK' in the file chooser
+      </li>
+      <li>
+        adjust attributes in the <a href="../../topic15/topic163/topic166.htm">
+        image dialog</a> as needed and
+      </li>
+      <li>
+        press 'OK' in the image dialog
+      </li>
+    </ul>
+    <p>
+      The selected image is inserted by placing a reference to the selected <a href="../../topic16/topic128/topic129.htm">
+image file</a> into the document. The image appears at the chosen location as 
+      long as the associated image file is present in the <a href="../../topic16/topic128/topic129.htm">
+image repository</a>. The image repository is <a href="../../topic16/topic128/topic131.htm">
+created and maintained</a> by application SimplyHTML automatically. When 
+      adding image files as described above, they are copied to and kept in 
+      the image repository. Once an image file is present in the image 
+      repository of a document, it does not have to be located in the file 
+      system again.
+    </p>
+    <p>
+      <b>Important</b>: If a document containing image references is moved to 
+      another storage location by hand, the associated directory with image 
+      files (the image repository, a directory named <font face="'Courier New',Monospaced,Monospace">
+images</font>) has to be moved too.
+    </p>
+    <p class="heading2">
+      Making changes to images in documents
+    </p>
+    <p>
+      To change settings of an image
+    </p>
+    <ul>
+      <li>
+        click on the image
+      </li>
+      <li>
+        select 'Image...' from menu 'Format'
+      </li>
+      <li>
+        adjust attributes in the <a href="../../topic15/topic163/topic166.htm">
+        image dialog</a> as needed and
+      </li>
+      <li>
+        press 'OK' in the image dialog
+      </li>
+    </ul>
+    <p>
+      To remove an image and its file reference from a document
+    </p>
+    <ul>
+      <li>
+        click on the image
+      </li>
+      <li>
+        press the [Backspace] or [Delete] key
+      </li>
+    </ul>
+    <p>
+      To remove an image file from the image repository
+    </p>
+    <ul>
+      <li>
+        select 'Image' from menu 'Insert'
+      </li>
+      <li>
+        select the image file to remove from the list of files in the <a href="../../topic15/topic163/topic166.htm">
+image dialog</a>
+      </li>
+      <li>
+        press button 'Delete'
+      </li>
+      <li>
+        press 'Yes' in the option pane that appears
+      </li>
+      <li>
+        press button 'Cancel' in the <a href="../../topic15/topic163/topic166.htm">
+image dialog</a>
+      </li>
+    </ul>
+    <p>
+      This will permanently delete the image file from the image directory of 
+      the currently open document.
+    </p>
+    <p>
+      <b>Important</b>: When deleting an image file from the image repository, 
+      all references to that image file inside the document remain intact but 
+      the image is rendered as 'broken' link (broken icon picture).
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic138.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic138.htm
new file mode 100644
index 0000000..6e62602
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic138.htm
@@ -0,0 +1,44 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Changing paragraph styles
+    </p>
+    <p>
+      As opposed to <a href="../../topic15/topic60/topic85.htm">styles applied 
+      to single characters</a>, paragraph styles are a way to define a group 
+      of formatting settings for one or more paragraphs at once.
+    </p>
+    <p>
+      To set the style for one or more paragraphs
+    </p>
+    <ul>
+      <li>
+        select the paragraph(s) to be formatted in the editor
+      </li>
+      <li>
+        choose 'Paragraph...' in menu 'Format'
+      </li>
+      <li>
+        set formatting options accordingly and
+      </li>
+      <li>
+        press 'OK'
+      </li>
+    </ul>
+    <p>
+      All contents of the selected paragraph(s) will assume the settings 
+      formatted in the Paragraph Style Dialog accordingly, unless other 
+      individual styles have been set for single characters inside the 
+      respective paragraph(s).
+    </p>
+    <p>
+      <a href="../../topic15/topic60/topic139.htm">Read on</a> to find out how 
+      to define and store a set of predefined formats as named styles.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic139.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic139.htm
new file mode 100644
index 0000000..2d3e44d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic139.htm
@@ -0,0 +1,131 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating and manipulating named styles
+    </p>
+    <p>
+      The <a href="../../topic15/topic60/topic138.htm">previous chapter</a> 
+      describes how a certain format can be applied to one or more paragraphs 
+      at once. However, in many cases similar formats are applied to the 
+      content over and over again. To reduce maintenance effort and storage 
+      space, named styles can be defined for such formats.
+    </p>
+    <p>
+      Named styles are not applied directly to a document when created. 
+      Instead they are saved to the style sheet of a document. To use named 
+      styles two steps are necessary:
+    </p>
+    <ol>
+      <li>
+        define a named style by setting all its formatting attributes and 
+        saving it to the style sheet
+      </li>
+      <li>
+        select a portion of the document in the editor and pick a named style 
+        for it from the style selector in the tool bar
+      </li>
+    </ol>
+    <p>
+      Once a named style is saved in the style sheet, it will appear in the 
+      style selector in the tool bar of SimplyHTML. It is necessary to define 
+      named styles only once for a combination of document and style sheet. 
+      The style sheet for a document is maintained automatically by SimplyHTML 
+      and saved whenever a document is <a href="../../topic15/topic58.htm">
+      saved</a>.
+    </p>
+    <p class="heading2">
+      Creating a named style
+    </p>
+    <p>
+      To define and save a named style
+    </p>
+    <ul>
+      <li>
+        select 'Named style...' from menu 'Format'
+      </li>
+      <li>
+        set formatting attributes in the paragraph style dialog accordingly
+      </li>
+      <li>
+        select an <a href="../../topic15/topic60/topic160.htm">element type</a>
+         for the new style (selector located above list of named styles)
+      </li>
+      <li>
+        press button 'Save as...'
+      </li>
+      <li>
+        enter a name for the style and press 'OK'
+      </li>
+    </ul>
+    <p class="standard">
+      <b>Important</b>: Styles are created only for the <a href="../../topic15/topic60/topic160.htm">
+element type</a> that is currently selected (paragraph, link, heading, etc.). 
+      Only changed attributes are saved to the style sheet.
+    </p>
+    <p class="heading2">
+      Changing a name style
+    </p>
+    <p>
+      To change settings for an existing named style
+    </p>
+    <ul>
+      <li>
+        select 'Named style...' from menu 'Format'
+      </li>
+      <li>
+        select the <a href="../../topic15/topic60/topic160.htm">element type</a>
+ (selector located above list of named styles)
+      </li>
+      <li>
+        select the named style to change settings for in the list of existing 
+        named styles
+      </li>
+      <li>
+        change formatting attributes in the paragraph style dialog accordingly
+      </li>
+      <li>
+        switch back to the 'Paragraph' tab if you are on tab 'Font'
+      </li>
+      <li>
+        press button 'Save'
+      </li>
+      <li>
+        press button 'OK'
+      </li>
+    </ul>
+    <p>
+      The named style for the selected element type (paragraph, link, heading, 
+      etc.) will be overwritten with the new settings. At the same location 
+      named styles can be deleted from the style sheet too.
+    </p>
+    <p class="heading2">
+      Deleting a named style
+    </p>
+    <p>
+      To delete a named style
+    </p>
+    <ul>
+      <li>
+        select 'Named style...' from menu 'Format'
+      </li>
+      <li>
+        select the named style to change settings for in the list of existing 
+        named styles
+      </li>
+      <li>
+        press button 'Delete'
+      </li>
+    </ul>
+    <p>
+      <b>Caution</b>: Deleting a named style will cause content portions 
+      formatted with that style to be rendered in an unpredictable style. Be 
+      sure to delete only unused styles. Keep in mind that a named style could 
+      be used in another document sharing styles with the currently edited one.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic159.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic159.htm
new file mode 100644
index 0000000..a0a021c
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic159.htm
@@ -0,0 +1,81 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating and manipulating links
+    </p>
+    <p>
+      A link in HMTL is a reference to another location and/or document a user 
+      can jump to. See chapter '<a href="../../topic16/topic152/topic153.htm"> 
+      Links in HTML</a>' for a technical description of links.
+    </p>
+    <p>
+      To create a link
+    </p>
+    <ul>
+      <li>
+        select a portion of text to format as link in the editor
+      </li>
+      <li>
+        select 'Link...' from menu 'Format'
+      </li>
+      <li>
+        make link settings as appropriate and
+      </li>
+      <li>
+        press 'OK'
+      </li>
+    </ul>
+    <p>
+      To change settings for an existing link
+    </p>
+    <ul>
+      <li>
+        move the caret into text formatted as link
+      </li>
+      <li>
+        select 'Link...' in menu 'Format'
+      </li>
+      <li>
+        make link changes as appropriate and
+      </li>
+      <li>
+        press 'OK'
+      </li>
+    </ul>
+    <p>
+      With both selections above, a <a href="../../topic15/topic163/topic164.htm">
+link dialog</a> is brought up to set link attributes accordingly. Once the 
+      link dialog is completed, the previously selected text portion is 
+      formatted as link accordingly.
+    </p>
+    <p>
+      <b>Note</b>: A link is only shown as link. It does not work as a link in 
+      the way that the link target is shown when the link is clicked. This 
+      probably will be added in a future stage.
+    </p>
+    <p>
+      
+    </p>
+    <p class="heading3">
+      See also
+    </p>
+    <p class="standard">
+      <a href="../../topic16/topic152/topic153.htm">Links in HTML</a>
+    </p>
+    <p class="standard">
+      <a href="../../topic15/topic60/topic162.htm">Creating and manipulating 
+      link anchors</a>
+    </p>
+    <p>
+      <a href="../../topic15/topic163/topic164.htm">Link dialog</a>
+    </p>
+    <p>
+      <a href="../../topic15/topic163/topic165.htm">Link anchor dialog</a>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic160.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic160.htm
new file mode 100644
index 0000000..1212a35
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic160.htm
@@ -0,0 +1,61 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Setting the element type
+    </p>
+    <p>
+      A specialty of HTML is to have different element types for content of a 
+      document separate from the content formatting. Element types could be 
+      paragraph, link or a certain kind of heading. One can think of element 
+      types being a way to distinguish certain structures in a document while 
+      named styles are a way to differentiate between certain formats both 
+      independent from each other.
+    </p>
+    <p>
+      Element types are applied to one or more paragraphs always. By default a 
+      paragraph is of element type paragraph as well.
+    </p>
+    <p>
+      To set another element type,
+    </p>
+    <ul>
+      <li>
+        select one or more paragraphs in the editor pane
+      </li>
+      <li>
+        choose an element type from the element type combo box in the tool bar
+      </li>
+    </ul>
+    <p>
+      Currently the following element types can be set
+    </p>
+    <ul>
+      <li>
+        paragraph
+      </li>
+      <li>
+        heading 1
+      </li>
+      <li>
+        heading 2
+      </li>
+      <li>
+        heading 3
+      </li>
+      <li>
+        heading 4
+      </li>
+      <li>
+        heading 5
+      </li>
+      <li>
+        heading 6
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic162.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic162.htm
new file mode 100644
index 0000000..4ae05b1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic162.htm
@@ -0,0 +1,103 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating and deleting link anchors
+    </p>
+    <p>
+      <a href="../../topic16/topic152/topic153.htm">Link anchors</a> are a way 
+      to designate certain positions inside a document. By using link anchors 
+      a link can directly reference and jump to a certain position inside a 
+      document. To make this possible, a link anchor has to be defined in that 
+      document before any link can reference to that position.
+    </p>
+    <p>
+      To define a link anchor inside a document that is to be targeted by a 
+      link
+    </p>
+    <ul>
+      <li>
+        open the target document
+      </li>
+      <li>
+        select 'Anchors...' from menu 'Format'
+      </li>
+      <li>
+        in the <a href="../../topic15/topic163/topic165.htm">link anchor dialog</a>
+ select the text portion inside the document to be used as a link target
+      </li>
+      <li>
+        click button 'Add'
+      </li>
+      <li>
+        type in a name for the new link anchor
+      </li>
+      <li>
+        press 'OK'
+      </li>
+      <li>
+        select 'save' from menu 'File' to save the document
+      </li>
+    </ul>
+    <p>
+      A link to the newly defined link anchor can now be set in the <a href="../../topic15/topic60/topic159.htm">
+link dialog</a>. As an alternative to above steps a link and link anchor can 
+      be set in one step using the link dialog too.
+    </p>
+    <p>
+      To delete a link anchor
+    </p>
+    <ul>
+      <li>
+        open the target document
+      </li>
+      <li>
+        select 'Anchors...' from menu 'Format'
+      </li>
+      <li>
+        in the link anchor dialog select the name of the link anchor to delete
+      </li>
+      <li>
+        click button 'Delete'
+      </li>
+      <li>
+        press 'OK'
+      </li>
+      <li>
+        select 'save' from menu 'File' to save the document
+      </li>
+    </ul>
+    <p>
+      <b>Important</b>: Above steps only delete the selected link anchor. 
+      Links referencing this link anchor remain the same thus leading to a 
+      'dead' location.
+    </p>
+    <p>
+      As an alternative to above steps a link anchor can be deleted through 
+      the <a href="../../topic15/topic60/topic159.htm">link dialog</a> too.
+    </p>
+    <p>
+      
+    </p>
+    <p class="heading3">
+      See also
+    </p>
+    <p class="standard">
+      <a href="../../topic16/topic152/topic153.htm">Links in HTML</a>
+    </p>
+    <p class="standard">
+      <a href="../../topic15/topic60/topic159.htm">Creating and manipulating 
+      links</a>
+    </p>
+    <p>
+      <a href="../../topic15/topic163/topic164.htm">Link dialog</a>
+    </p>
+    <p>
+      <a href="../../topic15/topic163/topic165.htm">Link anchor dialog</a>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic172.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic172.htm
new file mode 100644
index 0000000..58464be
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic172.htm
@@ -0,0 +1,55 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Working with HTML code
+    </p>
+    <p>
+      For an experienced user being familiar with HTML it sometimes is quicker 
+      to manipulate a certain portion of HTML directly instead of having to 
+      wade through GUI elements. For this reason in stage 10 of application 
+      SimplyHTML a way to work on the HTML representation of any given text 
+      document is implemented.
+    </p>
+    <p>
+      To see and edit the HTML representation of a given text document
+    </p>
+    <ol>
+      <li>
+        <a href="../../topic15/topic59.htm">open the document</a>
+      </li>
+      <li>
+        click on the tab <font face="'Courier New',Monospaced,Monospace">HTML 
+        code view</font> at the bottom of the editor pane
+      </li>
+    </ol>
+    <p>
+      The display will switch from layout view to HTML code view. In the HTML 
+      code view the structural information for a particular document is shown 
+      along with its content. Tags and attributes are mixed with plain text.
+    </p>
+    <p>
+      The HTML code view does not show how the plain text will look. Instead 
+      it highlights the structural portions of HTML and allows to work on the 
+      HTML code.
+    </p>
+    <p>
+      All changes to the HTML code are transformed to the resulting layout 
+      automatically when switching back to layout view (clicking on tab <font face="'Courier New',Monospaced,Monospace">
+Layout view</font> at the bottom of the editor pane, that is).
+    </p>
+    <p>
+      <b>Important</b>: To work on HTML code should only be done by users 
+      being experienced in HTML use. Changing HTML code can destroy the 
+      structure of the document leading to unpredictable results in the layout 
+      of respective document and even loss of content.
+    </p>
+    <p>
+      <b>Note</b>: With bigger documents it can take a short while to display 
+      the HTML code initially.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic177.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic177.htm
new file mode 100644
index 0000000..6c3c571
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic177.htm
@@ -0,0 +1,33 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+<title>Using find and replace</title>  </head>
+  <body>
+    <p class="heading1">
+      Using find and replace
+    </p>
+    <p>
+      In development stage 11 of application SimplyHTML functionality to find 
+      and replace text phrases inside of documents was added. Find and replace 
+      is implemented as a dialog combining all relevant functions. To invoke 
+      find and replace
+    </p>
+    <ol>
+      <li>
+        open menu <font face="'Courier New',Monospaced,Monospace">Edit</font>
+      </li>
+      <li>
+        select <font face="'Courier New',Monospaced,Monospace">Find and replace</font>
+
+      </li>
+    </ol>
+    <p>
+      A <a href="../../topic15/topic163/topic181.htm">dialog</a> will appear 
+      allowing to set all relevant options and to initiate a find or replace 
+      operation. When more than one document is open while find and replace is 
+      invoked option 'Search whole project' allows to perform find and replace 
+      over all open documents.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60/topic85.htm b/src/com/lightdev/app/shtm/help/topic15/topic60/topic85.htm
new file mode 100644
index 0000000..136e986
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60/topic85.htm
@@ -0,0 +1,56 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Changing font settings
+    </p>
+    <p>
+      Stage 3 of application SimplyHTML adds font manipulation functionality 
+      in two ways. Font settings can be changed either through a font dialog 
+      or through respective controls in the tool bar.
+    </p>
+    <p class="heading2">
+      Changing several font settings at once
+    </p>
+    <p>
+      To change all font settings for a text portion at once
+    </p>
+    <ul>
+      <li>
+        select the part of text to change font settings for
+      </li>
+      <li>
+        select 'Font' from menu 'Format' or press respective button in the 
+        tool bar
+      </li>
+      <li>
+        select font settings from the dialog, that appears and
+      </li>
+      <li>
+        press 'OK'
+      </li>
+    </ul>
+    <p class="heading2">
+      Changing single font settings
+    </p>
+    <p>
+      A quick way to change single font settings is through the tool bar
+    </p>
+    <ul>
+      <li>
+        select the part of text to change a single font setting for and
+      </li>
+      <li>
+        press respective button in the tool bar
+      </li>
+    </ul>
+    <p>
+      This way the tool bar allows to switch font family and size as well as 
+      to toggle between bold/normal, italic/normal and underlined/not 
+      underlined each in one step.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic60a.htm b/src/com/lightdev/app/shtm/help/topic15/topic60a.htm
new file mode 100644
index 0000000..cb3bff6
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic60a.htm
@@ -0,0 +1,59 @@
+<html>
+  <head>
+    <link href="../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">Searching documents</p>
+    <p>
+      SimplyHTML supports find+replace which can be accessed using the
+      <i>find & replace</i> button next to the help icon,
+      or the <i>Edit->Find & Replace</i> menu item.
+    </p>
+    
+    <p class="heading2">Searching</p>
+    <p>
+    In order to search incrementally for a search term,
+    enter that term in the <i>Text to find</i> text box and hit
+    the <i>Find next...</i> button (or press enter)
+    each time to get the next search result.
+    
+    Have a look at the <a href="#options">Search/Replace options</a> below.
+    </p>
+    
+    <p class="heading2">Replacing</p>
+    <p>
+	In order to replace occurrences of a search term by a replacement string,
+	enter the search term in the <i>Text to find</i> text box and the replacement
+	string in the <i>"Replace with</i> text box, and hit the <i>Replace...</i>
+	button. You will be prompted whether you want to replace for each occurrence.
+    
+    Have a look at the <a href="#options">Search/Replace options</a> below.
+    In particular, when using approximate search, check every occurrence
+    that is to be replaced carefully!
+    </p>
+    
+    <p class="heading2"><a name="options">Search/Replace options</a></p>
+    <dl style="font-family: sans-serif; font-size: small">
+    	<dt>Match case</dt>
+    	<dd>Whether to honor case when matching.</dd>
+    	<dt>Match approximately</dt>
+    	<dd>Whether to use approximate ("similarity") matching, i.e. allow differences
+    	between the search term and the match(es) in the text. For example, searching for
+    	<i>files</i> will find <i>flies</i> or <i>setup<i>=<i>set up</i>.
+    	</dd>
+    	<dt>Whole words only</dt>
+    	<dd>
+    	Restrict matches to whole words. Not supported for approximate matching.
+    	</dd>
+    	<dt>Search up/down</dt>
+    	<dd>
+    	  Enter the direction for (incremental) search or replace.
+    	</dd>
+    	<dt>Search from start</dt>
+    	<dd>
+    	Whether to search from the beginning of the document or from the current cursor position.
+    	</dd>
+    </dl>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic15/topic61.htm b/src/com/lightdev/app/shtm/help/topic15/topic61.htm
new file mode 100644
index 0000000..5b4d808
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic15/topic61.htm
@@ -0,0 +1,50 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Closing documents
+    </p>
+    <p>
+      To close the document, that is currently shown in the editor
+    </p>
+    <ul>
+      <li>
+        select 'Close' from menu 'File'
+      </li>
+    </ul>
+    <p>
+      To close a currently open document, that is not shown in the editor
+    </p>
+    <ul>
+      <li>
+        click on the tab representing the document and
+      </li>
+      <li>
+        select 'Close' from menu 'File'
+      </li>
+    </ul>
+    <p>
+      To close all currently open documents
+    </p>
+    <ul>
+      <li>
+        select 'Close all' from menu 'File'
+      </li>
+    </ul>
+    <p>
+      Closing a document will attempt to <a href="../topic15/topic58.htm">save</a>
+ pending changes before closing. If this fails, an error message will be shown 
+      the document will remain open.
+    </p>
+    <p>
+      When exiting the application while documents are open, as well attempts 
+      are made to save pending changes for all open documents. If this fails, 
+      an error message will be shown for each document, where a save could not 
+      commence, respective document(s) stay open and the application is not 
+      terminated.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16.htm b/src/com/lightdev/app/shtm/help/topic16.htm
new file mode 100644
index 0000000..5d61c89
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16.htm
@@ -0,0 +1,86 @@
+<html>
+  <head>
+    <link href="style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Inside SimplyHTML
+    </p>
+    <p>
+      This section explains the way application SimplyHTML is built, its 
+      structure, design and internal functionality. Refer to section '<a href="topic15.htm">
+Using SimplyHTML</a>' to read about its usage.
+    </p>
+    <p class="heading2">
+      Stages sections
+    </p>
+    <p>
+      SimplyHTML is built in stages. By dividing development into pieces, it 
+      is easier to concentrate on a certain detail of the application, paying 
+      more attention to the particular design of this part. The application 
+      will be more modular making maintenance easier to achieve.
+    </p>
+    <p>
+      Each stage results in a complete application. The resulting application 
+      gets more complex with every stage added while retaining its modular 
+      design. This section has chapters directly corresponding to each stage 
+      of SimplyHTML.
+    </p>
+    <p class="heading2">
+      Source codes
+    </p>
+    <p>
+      A complete set of source codes is distributed together with this 
+      tutorial for each stage.
+    </p>
+    <p>
+      For stage 2 for instance there is a complete set of sources chapter 
+      'Stage 2' refers to. This set of sources contains all sources of stage 1 
+      and 2 making up one executable which - when compiled - represents stage 
+      2 of the application.
+    </p>
+    <p>
+      In essence, sources of stage 2 do not contain changes versus stage 1 
+      only, they represent a complete application stage inlcuding previous 
+      stages.
+    </p>
+    <p class="heading2">
+      Spotlights section
+    </p>
+    <p>
+      The <a href="topic16/topic34.htm">spotlights</a> section discusses 
+      certain topics from a process oriented point of view. Where the stages 
+      sections explain the parts of SimplyHTML in the way they are structured 
+      (by classes and methods), spotlight topics wrap several parts of the 
+      application together to explain one process.
+    </p>
+    <p class="heading2">
+      How to use this part of the documentation
+    </p>
+    <p>
+      This part of the tutorial should be used together with the source codes 
+      which have plenty of documentation in addition. Source codes are 
+      commented and most of the comments went into the API documentation 
+      accompanying the package. Additional (non Javadoc) comments make clear 
+      certain parts of code on top of that.
+    </p>
+    <p>
+      This tutorial does not repeat code. It is structured to lead the way 
+      into the very details of the application's source code by adressing 
+      certain topics in one block. Chapters usually refer to the source codes 
+      by naming certain fields or methods. It is recommended to open the 
+      source codes in parallel to reading this tutorial.
+    </p>
+    <p class="heading2">
+      Target audience
+    </p>
+    <p>
+      Basics of Java and programming in general are not covered here, so 
+      interested readers should have a basic knowledge about these already. 
+      This section concentrates on discussing best practices and how to's in 
+      conjunction with a particular part of the application, trying to make a 
+      top down approach in covering the key targets of SimplyHTML.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103.htm b/src/com/lightdev/app/shtm/help/topic16/topic103.htm
new file mode 100644
index 0000000..ce09f70
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103.htm
@@ -0,0 +1,34 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 5: Plug-ins, user settings and dynamic resources
+    </p>
+    <p>
+      While SimplyHTML concentrates completely on text processing for HTML/CSS 
+      documents, it shall not be limited to creating and editing such 
+      documents. By delivering a solid and powerful editor for single 
+      documents it can be the basis for other functions too. Added 
+      functionality however is not in the scope of SimplyHTML which is where a 
+      plug-in mechanism comes into view.
+    </p>
+    <p>
+      A plug-in mechanism could allow almost any extension to SimplyHTML while 
+      preserving the original scope, leaving additional functions to potential 
+      plug-ins. This stage implements such plug-in mechanism along with an 
+      enhanced way of working with resource bundles suitable for plug-in 
+      usage. To allow users to configure plug-ins individually, a simlpe way 
+      of persistently storing user prefernces is implemented too.
+    </p>
+    <p>
+      The plug-in mechanism is created with the idea of future enhancements 
+      according to the needs of plug-in developers. This is best done in an 
+      evolutionary process which is why it is started in this stage instead of 
+      waiting until <a href="../topic16/topic112.htm">additional edititing 
+      functions</a> are finalized.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic107.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic107.htm
new file mode 100644
index 0000000..4cca0fc
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic107.htm
@@ -0,0 +1,131 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Parts of the plug-in architecture
+    </p>
+    <p>
+      To meet the previously stated requirements SimplyHTML provides the 
+      following new parts
+    </p>
+    <p>
+      
+    </p>
+    <table style=" width:80%; background-color:#ffffff;">
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#dadad9; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            <b>Part </b>
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#dadad9; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            <b>Description</b>
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SHTMLPlugin
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            The interface all plug-ins to SimplyHTML must implement
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            AbstractPlugin
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            A base class plug-ins can extend
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic103/topic110.htm">
+PluginManager</a></font>
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            Class to find and load plug-ins
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            FrmMain
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            Extended by an initialization method for plug-ins using the 
+            PluginManager
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            PluginTemplate
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            Class and properties files forming a basic plug-in for explanatory 
+            purposes and as copy template for plug-in creation
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            ManagePluginsAction
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            Action to show a PluginManagerDialog
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            PluginManagerDialog
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ececeb; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            Dialog for managing plug-ins (activate/deactivate, dock location, 
+            etc.)
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p>
+      
+    </p>
+    <p>
+      While application SimplyHTML is distributed in package <font face="'Courier New',Monospaced,Monospace">
+com.lightdev.app.shtm</font>, the above parts are in package <font face="'Courier New',Monospaced,Monospace">
+com.lightdev.app.shtm.plugin</font>. Package <font face="'Courier New',Monospaced,Monospace">
+plugin</font> is also the root package for all plug-ins to be added to 
+      SimplyHTML.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic108.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic108.htm
new file mode 100644
index 0000000..40a2e5a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic108.htm
@@ -0,0 +1,42 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Incorporating plug-ins at runtime
+    </p>
+    <p>
+      To give access to functions of external objects, SimplyHTML adds a 
+      plug-in menu to its menu bar. For each plug-in one menu item is added to 
+      the plug-in menu. The menu item is to be provided by the plug-in and 
+      typically would contain one or more submenus with the functionality 
+      delivered by the plug-in.
+    </p>
+    <p>
+      In the same way SimplyHTML creates a new menu item in the help menu so 
+      that the plug-in can provide documentation about the way it is working.
+    </p>
+    <p>
+      If the plug-in delivers a component to SimplyHTML, it is displayed by 
+      SimplyHTML either as a new window or as a panel inside a section of 
+      SimplyHTML's main window, whatever is requested by the plug-in.
+    </p>
+    <p class="heading2">
+      Plug-in initialization
+    </p>
+    <p>
+      Upon construction class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font> uses method <font face="'Courier New',Monospaced,Monospace">
+initPlugins</font> to add all plug-ins present to the application. Method <font face="'Courier New',Monospaced,Monospace">
+initPlugins</font> uses class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic103/topic107.htm">
+PluginManager</a></font> to locate and load plug-ins. In method <font face="'Courier New',Monospaced,Monospace">
+initPlugins</font> a new instance of class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic103/topic107.htm">
+PluginManager</a></font> is created. All plug-ins returned by method <font face="'Courier New',Monospaced,Monospace">
+plugins</font> of <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic103/topic107.htm">
+PluginManager</a></font> are iterated and their parts (plug-in menu, help menu 
+      and component so far) are added to SimplyHTML as described above.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic109.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic109.htm
new file mode 100644
index 0000000..d9ab1c8
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic109.htm
@@ -0,0 +1,37 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Requirements
+    </p>
+    <p>
+      A plug-in architecture for SimplyHTML has to meet the following 
+      requirements
+    </p>
+    <ul>
+      <li>
+        allow to incorporate additional functionality without the necessity to 
+        change parts of SimplyHTML
+      </li>
+      <li>
+        provide a single interface for external objects to plug-in to 
+        SimplyHTML
+      </li>
+      <li>
+        allow to access functionality of external objects from within 
+        SimplyHTML without SimplyHTML 'knowing' about the particular functions
+      </li>
+      <li>
+        allow plug-ins to use SimplyHTML's functionality
+      </li>
+    </ul>
+    <p>
+      Read on to find out how the plug-in implementation meets these 
+      requirements.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic110.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic110.htm
new file mode 100644
index 0000000..a04b0ab
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic110.htm
@@ -0,0 +1,62 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Class PluginManager
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">PluginManager</font>
+ finds and loads plug-ins. Upon creation it calls its method <font face="'Courier New',Monospaced,Monospace">
+loadPlugins</font> which in turn calls method <font face="'Courier New',Monospaced,Monospace">
+findPlugins</font> to locate any plug-ins to be loaded and to create a class 
+      loader for them. Method <font face="'Courier New',Monospaced,Monospace">
+      findPlugins</font> uses method <font face="'Courier New',Monospaced,Monospace">
+readJar</font> to get the class names from any Java archive (JAR) file found. <font face="'Courier New',Monospaced,Monospace">
+readJar</font> finds out the URLs for respective plug-in classes too.
+    </p>
+    <p>
+      Once all JAR files are searched, the found classes are loaded by method <font face="'Courier New',Monospaced,Monospace">
+loadPlugins</font>. Method <font face="'Courier New',Monospaced,Monospace">
+      plugins</font> returns all loaded plug-ins as an Enumeration.
+    </p>
+    <p class="heading2">
+      Restrictions for making plug-ins available to SimplyHTML
+    </p>
+    <p>
+      Plug-in classes and their accompanying classes are to be installed as 
+      Java archive (JAR) files. They are to be placed into package <font face="'Courier New',Monospaced,Monospace">
+com.lightdev.app.shtm.plugin.installed</font>. The plug-ins in this package 
+      need to be present in the directory where package <font face="'Courier New',Monospaced,Monospace">
+com.lightdev.app.shtm</font> is installed. This restriction makes it easier 
+      and faster to locate and load plug-ins.
+    </p>
+    <p>
+      If the actual plug-in class (the class implementing interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLPlugin</font>, that is) needs additional classes as part of a plug-in 
+      package, the additional classes are best placed in sub-packages of 
+      package .<font face="'Courier New',Monospaced,Monospace">plugin.installed</font>
+ . This makes it faster to load the actual plug-in classes too.
+    </p>
+    <p class="heading2">
+      How plug-ins are found
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">PluginManager</font> 
+      looks for JAR files in the directory where the class file of <font face="'Courier New',Monospaced,Monospace">
+PluginManager</font> is installed (the application directory of SimplyHTML, 
+      that is). <font face="'Courier New',Monospaced,Monospace">PluginManager</font>
+ opens any JAR file found and goes through all content of the JAR file. Any 
+      class name found in package <font face="'Courier New',Monospaced,Monospace">
+com.lightdev.app.shtm.plugin.installed. </font><font face="Sans-Serif">is 
+      stored along with its URL.</font>
+    </p>
+    <p>
+      A class loader is created for the found URLs and all found classes are 
+      loaded.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic111.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic111.htm
new file mode 100644
index 0000000..b48dbda
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic111.htm
@@ -0,0 +1,72 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Dynamic resources
+    </p>
+    <p>
+      In <a href="../../topic16/topic62.htm">stage 2</a> of SimplyHTML a 
+      dynamic way of using resource bundles was implemented. It is capable of 
+      providing <a href="../../topic16/topic62/topic70.htm">
+      internationalization support</a> and of <a href="../../topic16/topic62/topic68.htm">
+dynamic creation of components</a> such as menus and tool bars from parameters 
+      from a resource bundle.
+    </p>
+    <p>
+      This functionality needs to be made available to plug-ins as well which 
+      is why a new class <font face="'Courier New',Monospaced,Monospace">
+      DynamicResource</font> now provides these features formerly contained in 
+      class <font face="'Courier New',Monospaced,Monospace">FrmMain</font>.
+    </p>
+    <p class="heading2">
+      Class DynamicResource
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">DynamicResource</font>
+ provides methods for menu and tool bar creation based on parameters stored in 
+      ResourceBundles. As well, it stores and associates actions with 
+      components created in such way allowing for rerieval of component by 
+      their associated action name.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> has 
+      been changed to now use class <font face="'Courier New',Monospaced,Monospace">
+DynamicResource</font> for all internationalization and menu creation. It now 
+      makes publicly available a static instance of <font face="'Courier New',Monospaced,Monospace">
+DynamicResource</font> referencing components and actions of SimplyHTML. By 
+      having one static instance of DynamicResource in FrmMain, any object can 
+      use its utility methods without instanciating DynamicResources again.
+    </p>
+    <p>
+      All classes relying on <font face="'Courier New',Monospaced,Monospace">
+      FrmMain's</font> former functionality have been changed accordingly. 
+      Please see the source code and SimplyHTML's main .<font face="'Courier New',Monospaced,Monospace">
+properties</font> file for examples of how parameters can be created for 
+      automatic component creation.
+    </p>
+    <p class="heading2">
+      Using class DynamicResource for plug-ins
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">AbstractPlugin</font>
+ is an abstract base class plug-ins can use. By extending class <font face="'Courier New',Monospaced,Monospace">
+AbstractPlugin</font> a plug-in inherits some automatic initialization methods 
+      being performed upon construction. If a .<font face="'Courier New',Monospaced,Monospace">
+properties</font> file exists in the plug-in package (e.g. <font face="'Courier New',Monospaced,Monospace">
+com.lightdev.app.shtm.plugin.installed.MyPlugIn.properties</font>), class <font face="'Courier New',Monospaced,Monospace">
+AbstractPlugin</font> automatically creates a ResourceBundle for that .<font face="'Courier New',Monospaced,Monospace">
+properties</font> file. It then uses FrmMain's DynamicResource instance to 
+      create menus from the menu definitions found in that .properties file.
+    </p>
+    <p>
+      If a different approach of plug-in construction is desired, a plug-in 
+      class either can be declared not to extend class <font face="'Courier New',Monospaced,Monospace">
+AbstractPlugin</font> or can override some or all methods of class <font face="'Courier New',Monospaced,Monospace">
+AbstractPlugin</font> accordingly.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic113.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic113.htm
new file mode 100644
index 0000000..3a1e58a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic113.htm
@@ -0,0 +1,102 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating plug-ins for SimplyHTML
+    </p>
+    <p>
+      A plug-in can be any Java object implementing interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLPlugin</font>. As specified by interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLPlugin</font>, a plug-in should provide
+    </p>
+    <ul>
+      <li>
+        a menu delivering access to all of the plug-ins functions (plug-in 
+        menu)
+      </li>
+      <li>
+        a menu providing documentation about the plug-in as required (help 
+        menu)
+      </li>
+      <li>
+        a component containing any GUI representation of the plug-in (plug-in 
+        component)
+      </li>
+      <li>
+        an indicator telling whether the plug-in component shall be 'docked' 
+        to SimplyHTML's main window (and where by default) or displayed in a 
+        separate window.
+      </li>
+      <li>
+        its name as it should be represented on a GUI
+      </li>
+      <li>
+        its internal name for possible internal referencing
+      </li>
+    </ul>
+    <p>
+      Above parts need not to be present in all cases, returning <font face="'Courier New',Monospaced,Monospace">
+null</font> in one or more parts is sufficient as well. Apart from above 
+      specification, plug-in developers are free to design their plug-in in 
+      any way they like. As SimplyHTML is open source (and will remain as 
+      such), plug-ins can access all its public parts as described in 
+      SimplyHTML's API documentation.
+    </p>
+    <p class="heading2">
+      Class AbstractPlugin
+    </p>
+    <p>
+      To further simplify plug-in creation, there is an <a href="../../topic16/topic103/topic111.htm">
+abstract base class</a> that can be used to build a new plug-in upon. It 
+      basically implements a generic way of creating menus from a resource 
+      bundle (if one is delivered with the plug-in). See chapter '<a href="../../topic16/topic103/topic111.htm">
+Dynamic resources</a>' and the source code for class <font face="'Courier New',Monospaced,Monospace">
+AbstractPlugin</font> for details.
+    </p>
+    <p>
+      Plug-ins are not obliged to extend <font face="'Courier New',Monospaced,Monospace">
+AbstractPlugin</font> or they can override some or all of its classes to 
+      adjust the plug-in accordingly. When extending AbstractPlugin unchanged, 
+      a .<font face="'Courier New',Monospaced,Monospace">properties</font> 
+      file should be provided with the new plug-in having menu definitions, 
+      etc.
+    </p>
+    <p class="heading2">
+      Class PluginTemplate
+    </p>
+    <p>
+      Another help for plug-in developers is class <font face="'Courier New',Monospaced,Monospace">
+PluginTemplate</font>. It constructs a working - though functionless - plug-in 
+      for SimplyHTML. Plug-in developers can use it as a copy template for own 
+      plug-ins or for explanatory purposes.
+    </p>
+    <p>
+      With class PluginTemplate two .properties files are provided too. They 
+      have the necessary menu definitions and texts for english and german 
+      language. Use these .properties files as an example for how to define 
+      appropriate .properties files for you plug-ins.
+    </p>
+    <p class="heading2">
+      Defining actions for plug-ins
+    </p>
+    <p>
+      A plug-in typically adds functionality to SimplyHTML which can best be 
+      provided to SimplyHTML through respective action classes. To integrate 
+      action classes of plug-ins with SimplyHTML, they should be connected to 
+      plug-in menu items.
+    </p>
+    <p>
+      Actions from plug-ins are added to SimplyHTML by using FrmMain's 
+      DynamicResource instance. Call method addAction of class DynamicResource 
+      passing it an instance of a plug-in action along with its command name. 
+      The action command should has to be the same expression as it was used 
+      to identify the menu item in the ResourceBundle. See method <font face="'Courier New',Monospaced,Monospace">
+initActions</font> of class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font> for an example.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic114.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic114.htm
new file mode 100644
index 0000000..b11e324
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic114.htm
@@ -0,0 +1,86 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Making plug-ins available to SimplyHTML
+    </p>
+    <p>
+      Plug-ins need to reside in Java archive (JAR) files. Inside the JAR file 
+      a plug-in must be in package <font face="'Courier New',Monospaced,Monospace">
+com.lightdev.app.shtm.plugin.installed</font>. If a plug-in is accompanied by .<font face="'Courier New',Monospaced,Monospace">
+properties</font> files for internationalization or dynamic menu creation, the 
+      .<font face="'Courier New',Monospaced,Monospace">properties</font> files 
+      have to reside in package <font face="'Courier New',Monospaced,Monospace">
+com.lighdev.app.shtm.plugin.installed</font> too.
+    </p>
+    <p>
+      Should there be additional classes distributed along with the actual 
+      plug-in class (the class implementing interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLPlugin</font>, that is), these additional classes should be placed into 
+      sub-packages such as <font face="'Courier New',Monospaced,Monospace">
+      com.lightdev.app.shtm.plugin.installed.mypluginaddons</font> inside the 
+      JAR file.
+    </p>
+    <p>
+      Any JAR file containing a plug-in must be placed into the application 
+      directory of SimplyHTML. The application directory of SimplyHTML is
+    </p>
+    <ol>
+      <li>
+        the directory in the file system, where the JAR file of SimplyHTML is 
+        installed or
+      </li>
+      <li>
+        the root package directory of file <font face="'Courier New',Monospaced,Monospace">
+PluginManager.class</font>, if SimplyHTML is not operated out of a JAR file
+      </li>
+    </ol>
+    <p class="heading2">
+      Removing plug-ins
+    </p>
+    <p>
+      To remove a plug-in from SimplyHTML, remove its JAR file from the 
+      application directory and restart SimplyHTML.
+    </p>
+    <p class="heading2">
+      Examples for plug-in installation
+    </p>
+    <p>
+      In the following examples it is assumed that a plug-in is to be added to 
+      SimplyHTML from a file MyPlugIn.jar
+    </p>
+    <p class="heading3">
+      Example 1
+    </p>
+    <p>
+      SimplyHTML is operated out of file <font face="'Courier New',Monospaced,Monospace">
+SimplyHTML.jar</font> and <font face="'Courier New',Monospaced,Monospace">
+      SimplyHTML.jar</font> is in directory <font face="'Courier New',Monospaced,Monospace">
+C.\Programs\SimplyHTML\</font>
+    </p>
+    <p>
+      <i><b>Installation:</b></i> File <font face="'Courier New',Monospaced,Monospace">
+MyPlugIn.jar</font> must be placed into directory <font face="'Courier New',Monospaced,Monospace">
+C:\Programs\SimplyHTML\</font>
+    </p>
+    <p class="heading3">
+      Example 2
+    </p>
+    <p>
+      SimplyHTML is operated as an uncompressed class file not residing in a 
+      JAR file, the SimplyHTML package is installed in <font face="'Courier New',Monospaced,Monospace">
+C:\Programs\SimplyHTML\classes\</font>, i.e. file <font face="'Courier New',Monospaced,Monospace">
+PluginManager.class</font> is installed in <font face="'Courier New',Monospaced,Monospace">
+C:\Programs\SimplyHTML\classes\com\lightdev\app\shtm\plugin\</font>
+    </p>
+    <p>
+      <i><b>Installation:</b></i> File <font face="'Courier New',Monospaced,Monospace">
+MyPlugIn.jar</font> must be placed into directory <font face="'Courier New',Monospaced,Monospace">
+C:\Programs\SimplyHTML\classes\ </font>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic117.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic117.htm
new file mode 100644
index 0000000..d1ef0e3
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic117.htm
@@ -0,0 +1,59 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Changing plug-in settings individually
+    </p>
+    <p>
+      In addition to its <a href="../../topic16/topic103/topic114.htm">
+      installation</a> each plug-in can be configured individually per user. 
+      With class <font face="'Courier New',Monospaced,Monospace">
+      PluginManagerDialog</font> all loaded plug-ins are displayed and can be 
+      configured. <font face="'Courier New',Monospaced,Monospace">
+      PluginManagerDialog</font> is shown with the help of class <font face="'Courier New',Monospaced,Monospace">
+ManagePluginsAction</font> which is registered with respective menu item of 
+      SimplyHTML's plug-in menu.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">ManagePluginDialog</font>
+       is the GUI representation of plug-in manipulation methods actually 
+      provided by class <font face="'Courier New',Monospaced,Monospace">
+      AbstractPlugin</font>. It uses the methods each plug-in class has to 
+      provide through implementing interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLPlugin</font> to display and change settings such as whether or not the 
+      plug-in is active or where it shall dock. Class <font face="'Courier New',Monospaced,Monospace">
+AbstractPlugin</font> provides an implementation of interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLPlugin</font> which persistently stores the settings made in <font face="'Courier New',Monospaced,Monospace">
+MangagePluginDialog</font> automatically. To do so, an additional class <font face="'Courier New',Monospaced,Monospace">
+Prefs</font> is used, which is introduced in this stage 5 of SimplyHTML (see 
+      below).
+    </p>
+    <p class="heading2">
+      Class Prefs
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">Prefs</font> 
+      provides a simple approach to store user settings persistently. It 
+      maintains a <font face="'Courier New',Monospaced,Monospace">Hastable</font>
+ of key/value pairs through a set of getter/setter methods. Whenever the <font face="'Courier New',Monospaced,Monospace">
+Hashtable</font> is changed, it is serialized to a file. Upon construction of 
+      class <font face="'Courier New',Monospaced,Monospace">Prefs</font> the 
+      serialized <font face="'Courier New',Monospaced,Monospace">Hashtable</font>
+ is read from disk. If none is found a new and empty one is created. The 
+      preferences file created by class <font face="'Courier New',Monospaced,Monospace">
+Prefs</font> is named <font face="'Courier New',Monospaced,Monospace">
+      SimplyHTML.prf</font> and is stored in the directory pointed to by 
+      expression <font face="'Courier New',Monospaced,Monospace">
+      System.getProperty("user.home")</font> which usually 
+      references the home directory of the user currently logged in.
+    </p>
+    <p>
+      By using the home directory of the user preferences can be stored 
+      individually per user.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic103/topic119.htm b/src/com/lightdev/app/shtm/help/topic16/topic103/topic119.htm
new file mode 100644
index 0000000..8eb3410
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic103/topic119.htm
@@ -0,0 +1,70 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Example: Making a new plug-in
+    </p>
+    <p>
+      To create a new plug-in for SimplyHTML,
+    </p>
+    <ol>
+      <li>
+        copy file <font face="'Courier New',Monospaced,Monospace">
+        PluginTemplate.java</font> into your plug-in project's source directoy
+      </li>
+      <li>
+        rename <font face="'Courier New',Monospaced,Monospace">
+        PluginTemplate.java</font> to a name you would like to give your new 
+        plug-in class
+      </li>
+      <li>
+        change the paramteters of call <font face="'Courier New',Monospaced,Monospace">
+super</font> in <font face="'Courier New',Monospaced,Monospace">PluginTemplate</font>
+ 's constructor according to names you choose (refer to class <font face="'Courier New',Monospaced,Monospace">
+AbstractPlugin</font> for a definition of these parameters)
+      </li>
+      <li>
+        create one or more .<font face="'Courier New',Monospaced,Monospace"> 
+        properties</font> files as needed for your new plug-in (you can use 
+        file <font face="'Courier New',Monospaced,Monospace">
+        PluginTemplate.properties</font> a an example)
+      </li>
+      <li>
+        adjust parameter <font face="'Courier New',Monospaced,Monospace">
+        "pluginTemplateLabel"</font> in method <font face="'Courier New',Monospaced,Monospace">
+getGUIName</font> to an ID String referring to respective entry in your .<font face="'Courier New',Monospaced,Monospace">
+properties</font> file(s)
+      </li>
+      <li>
+        add methods and fields to implement the functionality desired for your 
+        new plug-in
+      </li>
+      <li>
+        compile the new plug-in's source file (<font face="'Courier New',Monospaced,Monospace">
+.java</font>) to a <font face="'Courier New',Monospaced,Monospace">.class</font>
+ file
+      </li>
+      <li>
+        place <font face="'Courier New',Monospaced,Monospace">.class</font> 
+        file and .<font face="'Courier New',Monospaced,Monospace">properties</font>
+ file(s) into a Java archive (JAR) file, package <font face="'Courier New',Monospaced,Monospace">
+com.lightdev.app.shtm.plugin.installed</font>
+      </li>
+      <li>
+        place the JAR file into the directory <font face="'Courier New',Monospaced,Monospace">
+SimplyHTML.jar</font> is installed in
+      </li>
+    </ol>
+    <p>
+      
+    </p>
+    <p>
+      When starting SimplyHTML for the next time, your new plug-in should be 
+      listed in the 'Manage Plugins...' dialog.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic112.htm b/src/com/lightdev/app/shtm/help/topic16/topic112.htm
new file mode 100644
index 0000000..463f25d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic112.htm
@@ -0,0 +1,27 @@
+<html>
+  <head>
+    <link type="text/css" href="../style.css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Planned development stages
+    </p>
+    <p>
+      The following is an overview of planned stages to be completed in the 
+      future. The plan is subject to change but it shall document, what the 
+      author intends to add or change in SimplyHTML for upcoming releases:
+    </p>
+    <ol>
+      <li>
+        Link target window (clickable links)
+      </li>
+      <li>
+        Extension/consolidation of persistent application settings (Prefs)
+      </li>
+      <li>
+        Refine context sensitive help, popup menus, other GUI enhancements
+      </li>
+    </ol>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic120.htm b/src/com/lightdev/app/shtm/help/topic16/topic120.htm
new file mode 100644
index 0000000..3eb3130
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic120.htm
@@ -0,0 +1,45 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 6: Lists
+    </p>
+    <p>
+      The Java language already includes some standard actions to implement 
+      list formatting with documents in a JEditorPane. These actions however 
+      only provide a very basic approach to working with lists. On top of just 
+      starting a new empty list and to enter text into this new list, for 
+      application SimplyHTML the requirement is to offer a simple way of 
+      switching list formatting on or off for an arbitrary portion of existing 
+      text paragraphs. As well there should be a way to change formatting of 
+      an existing list partly or completely through a separate dialog.
+    </p>
+    <p>
+      This stage implements list handling as described above covering the 
+      following topics
+    </p>
+    <p>
+      <a href="../topic16/topic120/topic121.htm">Lists in HTML documents</a>
+    </p>
+    <p>
+      <a href="../topic16/topic120/topic122.htm">Implementing list formatting 
+      in SimplyHTML</a>
+    </p>
+    <p>
+      <a href="../topic16/topic120/topic123.htm">Switching list formatting on 
+      or off</a>
+    </p>
+    <p>
+      <a href="../topic16/topic120/topic124.htm">Creating a list format dialog</a>
+
+    </p>
+    <p>
+      <a href="../topic16/topic120/topic125.htm">Adding actions and GUI 
+      elements</a>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic120/topic121.htm b/src/com/lightdev/app/shtm/help/topic16/topic120/topic121.htm
new file mode 100644
index 0000000..f680a71
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic120/topic121.htm
@@ -0,0 +1,87 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Lists in HTML documents
+    </p>
+    <p>
+      In HTML documents content is embedded into tags such as <font face="'Courier New',Monospaced,Monospace">
+<p></font> or <font face="'Courier New',Monospaced,Monospace"><td></font>
+ etc. To apply list formatting to a set of paragraphs, they have to be 
+      enclosed into list item tags (<font face="'Courier New',Monospaced,Monospace">
+<li></li></font>) which in turn are enclosed by list tags for 
+      ordered or unordered lists (<font face="'Courier New',Monospaced,Monospace">
+<ol></ol></font> and <font face="'Courier New',Monospaced,Monospace">
+<ul></ul></font>).
+    </p>
+    <p>
+      For example, a list coded as
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <ul>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <li>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <p>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      Item 1
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      </p>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      </li>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <li>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <p>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      Item 2
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      </p>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      </li>
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      </ul>
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      would be rendered as
+    </p>
+    <ul>
+      <li>
+        Item 1
+      </li>
+      <li>
+        Item 2
+      </li>
+    </ul>
+    <p>
+      
+    </p>
+    <p>
+      Certain attributes can be applied to above HTML code by either storing 
+      them directly with a tag inside the HTML document or by defining styles 
+      for respective tag in a CSS style sheet.
+    </p>
+    <p>
+      <a href="../../topic16/topic120/topic122.htm">Read on</a> to see how 
+      above list formatting is applied with application SimplyHTML.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic120/topic122.htm b/src/com/lightdev/app/shtm/help/topic16/topic120/topic122.htm
new file mode 100644
index 0000000..5b4ea62
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic120/topic122.htm
@@ -0,0 +1,38 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Implementing list formatting in SimplyHTML
+    </p>
+    <p>
+      As described in the <a href="../../topic16/topic120.htm">introduction of 
+      stage 6</a>, to apply list formatting in SimplyHTML the requirement is 
+      to offer a simple way to switch list formatting on or off for an 
+      arbitrary portion of existing text paragraphs. As well there should be a 
+      way to change formatting of an existing list partly or completely 
+      through a separate dialog.
+    </p>
+    <p>
+      While parts of previous stages of SimplyHTML can be re-used to achieve 
+      list formatting thorugh a dialog, a certain difficulty is to change an 
+      arbitrary portion of existing text to list formatting because the 
+      element structure of the existing document content has to be changed.
+    </p>
+    <p class="heading2">
+      Changing the element structure
+    </p>
+    <p>
+      The only way to change the element structure of an HTML document which 
+      is publicly available in the Java classes is to insert HTML code 
+      replacing a given part of respective document. SimplyHTML uses class <font face="'Courier New',Monospaced,Monospace">
+SHTMLWriter</font> to synthesize HTML code as already done in <a href="../../topic16/topic86/topic95.htm">
+table formatting</a>. The process is described in more detail in the <a href="../../topic16/topic120/topic123.htm">
+following chapters</a>. Please see the source code of stage 6 for additional 
+      details.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic120/topic123.htm b/src/com/lightdev/app/shtm/help/topic16/topic120/topic123.htm
new file mode 100644
index 0000000..e93cef8
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic120/topic123.htm
@@ -0,0 +1,135 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Switching list formatting on or off
+    </p>
+    <p>
+      When an HTML document initially is filled with content by typing text, 
+      the content is not formatted as list. To reach list formatting for parts 
+      of a document the user could
+    </p>
+    <ol>
+      <li>
+        start list formatting and then type content in the form of list items 
+        as needed or
+      </li>
+      <li>
+        type in content and then switch on list formatting for the recently 
+        typed paragraphs
+      </li>
+    </ol>
+    <p>
+      While the first case is comparably easy to achieve, both cases require a 
+      simple toggle functionality to switch list formatting on or off.
+    </p>
+    <p class="heading2">
+      Basic approach
+    </p>
+    <p>
+      Such list toggle functionality basically this is achieved by
+    </p>
+    <ol>
+      <li>
+        detecting whether or not the required list formatting is present for a 
+        given text portion
+      </li>
+      <li>
+        if list formatting is present, switch list formatting <b>off</b>
+      </li>
+      <li>
+        if list formatting is not present (or not present as required), switch 
+        list formatting <b>on</b>
+      </li>
+    </ol>
+    <p class="heading2">
+      Method toggleList
+    </p>
+    <p>
+      Above scheme is implemented with method <font face="'Courier New',Monospaced,Monospace">
+toggleList</font> in class <font face="'Courier New',Monospaced,Monospace">
+      SHTMLEditorPane</font>. Method <font face="'Courier New',Monospaced,Monospace">
+toggleList</font> finds out the parent element of a selected text portion. It 
+      then uses method <font face="'Courier New',Monospaced,Monospace">switchOn</font>
+ to determine whether or not list formatting is already present in the 
+      selection inside the parent element. If method <font face="'Courier New',Monospaced,Monospace">
+switchOn</font> 'decides' to switch on list formatting (returns <font face="'Courier New',Monospaced,Monospace">
+true</font> that is), method <font face="'Courier New',Monospaced,Monospace">
+      toggleList</font> uses method <font face="'Courier New',Monospaced,Monospace">
+listOn</font> to switch on list formatting. Otherwise list formatting is 
+      turned off by calling method <font face="'Courier New',Monospaced,Monospace">
+listOff</font>.
+    </p>
+    <p class="heading2">
+      Difficulties
+    </p>
+    <p>
+      Up to here the solution sounds rather simple. In detail however, some 
+      difficulty is contained in the way how existing list formatting is to be 
+      changed. There are two cases we need to look at in more detail:
+    </p>
+    <ol>
+      <li>
+        list formatting is to be switched off for only parts of an existing 
+        list
+      </li>
+      <li>
+        list formatting is to be switched on for one or more lists having 
+        mixed list formatting
+      </li>
+    </ol>
+    <p class="heading3">
+      Splitting lists
+    </p>
+    <p>
+      The first case above requires to split an existing list into up to three 
+      sections: The list remaining at the beginning of the selection, the 
+      actual selection for which list formatting is to be switched off and the 
+      list part possibly following the selection.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">listOff</font> 
+      splits a list by iterating through all list items in three steps. In the 
+      first step, it generates HTML for the list portion remaining unchanged 
+      and creates a new list end tag at the start of the selection to mark the 
+      start of the list split.
+    </p>
+    <p>
+      Secondly it continues iterating through the list items belonging to the 
+      selection generating HTML code with <font face="'Courier New',Monospaced,Monospace">
+<li></font> tags removed.
+    </p>
+    <p>
+      Finally a new list start tag is created to mark the end of the split and 
+      iteration is continued over the remaining portion of the original list 
+      generating HTML code for the remaining list elements.
+    </p>
+    <p>
+      The resulting HTML code is inserted into the document replacing the 
+      'old' part.
+    </p>
+    <p class="heading3">
+      Merging lists
+    </p>
+    <p>
+      The second case above requires to merge different list formattings to 
+      one new list formatting. In addition, possible list formatting preceding 
+      or following the selection has to be split as described in the previous 
+      paragraph.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">listOn</font> 
+      merges lists by iterating through all list items and adjusts list start 
+      and end tags, merging and splitting lists as needed. <font face="'Courier New',Monospaced,Monospace">
+<li></font> start and end tags are inserted if necessary.
+    </p>
+    <p>
+      The resulting HTML code is inserted into the document replacing the 
+      'old' part.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic120/topic124.htm b/src/com/lightdev/app/shtm/help/topic16/topic120/topic124.htm
new file mode 100644
index 0000000..149b31f
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic120/topic124.htm
@@ -0,0 +1,73 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a list format dialog
+    </p>
+    <p>
+      Switching lists on and off as described in the <a href="../../topic16/topic120/topic123.htm">
+previous chapter</a> formats lists in their default formatting as defined in 
+      the style sheet of respective document (i.e. applies tags <font face="'Courier New',Monospaced,Monospace">
+<ul></font> and <font face="'Courier New',Monospaced,Monospace"><ol></font>
+ without additional attributes). To adjust list formatting, additional 
+      functionality is needed.
+    </p>
+    <p>
+      To change list formatting, a dialog is created acting on both list 
+      attributes and list elements.
+    </p>
+    <p>
+      When changing an existing ordered list from number to letter ordering 
+      for instance, attributes of the list are to be changed. When switching 
+      from an existing list ordered by numbers to an unordered bullet list 
+      with square bullet symbol, the list element itself <i>and</i> its 
+      attributes are to be changed in one step.
+    </p>
+    <p class="heading2">
+      Re-use of existing parts
+    </p>
+    <p>
+      List formatting functionality in part is similar to what has been 
+      implemented for <a href="../../topic16/topic86.htm">table formatting</a> 
+      already. Consequently, some of the existing functionality of SimplyHTML 
+      can be re-used: Classes <font face="'Courier New',Monospaced,Monospace">
+      DialogShell</font>, <font face="'Courier New',Monospaced,Monospace">
+      AttributeComboBox</font> and <font face="'Courier New',Monospaced,Monospace">
+BoundariesPanel</font> which share common classes to work with attributes and 
+      attribute sets themselves. In stage 6 class <font face="'Courier New',Monospaced,Monospace">
+AttributeComboBox</font> has been turned into an own class from the former 
+      inner class in class <font face="'Courier New',Monospaced,Monospace">
+      TableDialog</font>.
+    </p>
+    <p class="heading2">
+      New parts to implement
+    </p>
+    <p>
+      To create the new list format dialog, class <font face="'Courier New',Monospaced,Monospace">
+ListDialog</font> is created extending class <font face="'Courier New',Monospaced,Monospace">
+DialogShell</font>. Class <font face="'Courier New',Monospaced,Monospace">
+      ListDialog</font> is a container for the class showing the actual list 
+      attributes, new class <font face="'Courier New',Monospaced,Monospace">
+      ListPanel</font>. Class <font face="'Courier New',Monospaced,Monospace">
+      ListPanel</font> in turn uses classes <font face="'Courier New',Monospaced,Monospace">
+AttributeComboBox</font> and <font face="'Courier New',Monospaced,Monospace">
+      BoundariesPanel</font> to make available respective list attributes.
+    </p>
+    <p>
+      How the list attributes actually are shown and changed is implemented 
+      exactly the same as in class <a href="../../topic16/topic86/topic93.htm">
+      TableDialog</a>.
+    </p>
+    <p>
+      To apply list attributes as set with <font face="'Courier New',Monospaced,Monospace">
+ListDialog</font>, a new method <font face="'Courier New',Monospaced,Monospace">
+applyListAttributes</font> is added to class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> which is again similar to what <a href="../../topic16/topic86/topic93.htm">
+applyTableAttributes</a> does.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic120/topic125.htm b/src/com/lightdev/app/shtm/help/topic16/topic120/topic125.htm
new file mode 100644
index 0000000..6eeca08
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic120/topic125.htm
@@ -0,0 +1,47 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Adding actions and GUI elements
+    </p>
+    <p>
+      To finally use the new list functionality it has to be made available to 
+      the user by adding it to SimplyHTML's GUI. Three new actions are created 
+      in class <font face="'Courier New',Monospaced,Monospace">FrmMain</font>
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">ToggleBulletsAction</font>
+
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">ToggleNumbersAction</font>
+
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">FormatListAction</font>
+      </li>
+    </ul>
+    <p>
+      They are added to <font face="'Courier New',Monospaced,Monospace">
+      FrmMain's</font> <font face="'Courier New',Monospaced,Monospace">
+      initActions</font> method and inlcuded into menu and tool bar 
+      definitions of the <a href="../../topic16/topic103/topic111.htm">
+      resource bundle</a> of application SimplyHTML. Through SimyplHTML's <a href="../../topic16/topic103/topic111.htm">
+dynamic resource mechanism</a>, new menu items and tool bar buttons are 
+      created for above actions automatically.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">SHTMLEditorPane</font>
+ has an additional action <font face="'Courier New',Monospaced,Monospace">
+      NewListItemAction</font> which is registered with the key map of the 
+      editor pane (see also the explanations in the <a href="../../topic16/topic86/topic94.htm">
+tables</a> section). This action is used to create a new list item when the 
+      user presses the [Enter] key while the caret is inside a list.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic128.htm b/src/com/lightdev/app/shtm/help/topic16/topic128.htm
new file mode 100644
index 0000000..1fce046
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic128.htm
@@ -0,0 +1,39 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 7: Images
+    </p>
+    <p>
+      This stage is enabling application SimplyHTML to add images to documents 
+      and to adjust the display of images in documents. It implements an image 
+      repository and dialog for all image manipulation inside SimplyHTML.
+    </p>
+    <p>
+      The functionality for image support in SimplyHTML is described in the 
+      following chapters:
+    </p>
+    <p>
+      <a href="../topic16/topic128/topic134.htm">Image references in HTML</a>
+    </p>
+    <p>
+      <a href="../topic16/topic128/topic129.htm">General concept for image 
+      support</a>
+    </p>
+    <p>
+      <a href="../topic16/topic128/topic131.htm">Implementing image storage</a>
+    </p>
+    <p>
+      <a href="../topic16/topic128/topic130.htm">Creating a GUI to manipulate 
+      image references</a>
+    </p>
+    <p>
+      <a href="../topic16/topic128/topic133.htm">Making the GUI available to 
+      the user</a>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic128/topic129.htm b/src/com/lightdev/app/shtm/help/topic16/topic128/topic129.htm
new file mode 100644
index 0000000..589ba84
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic128/topic129.htm
@@ -0,0 +1,124 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      General concept for image support
+    </p>
+    <p>
+      In HTML images are separated from documents. Documents contain <a href="../../topic16/topic128/topic134.htm">
+references</a> to image files in the place where images should appear inside a 
+      document. An <a href="../../topic16/topic128/topic134.htm">image 
+      reference</a> describes the location and name of respective image file 
+      as well as how it is to be rendered. The actual images are stored 
+      separately in image files and loaded dynamically when documents are 
+      displayed.
+    </p>
+    <p>
+      SimplyHTML supports <a href="../../topic16/topic128/topic134.htm">image 
+      references</a> by maintaining an image repository for each document. An 
+      image repository in this context is a directory containing all images 
+      referenced by a HTML document.
+    </p>
+    <p class="heading2">
+      Restrictions
+    </p>
+    <p>
+      To keep image maintenance simple, the following restrictions are used in 
+      SimplyHTML
+    </p>
+    <ul>
+      <li>
+        image files referenced from HTML documents are automatically placed 
+        into directory <font face="'Courier New',Monospaced,Monospace">images</font>
+
+      </li>
+      <li>
+        directory <font face="'Courier New',Monospaced,Monospace">images</font>
+         is created automatically inside the directory, a HTML file is saved
+      </li>
+    </ul>
+    <p>
+      SimplyHTML has no support for creation or manipulation of image files as 
+      in image editing software . Image files need to be present already to be 
+      added to documents created or maintained with SimplyHTML.
+    </p>
+    <p class="heading2">
+      Supported image formats
+    </p>
+    <p>
+      SimplyHTML supports the following image file formats
+    </p>
+    <ul>
+      <li>
+        Graphics Interchange Format (GIF)
+      </li>
+      <li>
+        Joint Photographic Expert Group (JPEG) format
+      </li>
+    </ul>
+    <p class="heading2">
+      Temporary storage
+    </p>
+    <p>
+      To allow image processing for newly created documents (i.e. documents 
+      not having been saved at the time images are added) a temporary 
+      directory is maintained. The temporary storage is maintained 
+      automatically by SimplyHTML in directory
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">[user 
+      home]/SimplyHTML/temp/</font>.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">[user home]</font> in 
+      this context is the directory returned by the Java expression <font face="'Courier New',Monospaced,Monospace">
+System.getProperty("user.home")</font>. It is usually the directory 
+      where a user logged in to a given system has all rights and where no 
+      other user except for system administrators has access rights unless 
+      explicitly granted by the owner or system administrator.
+    </p>
+    <p>
+      Using directory <font face="'Courier New',Monospaced,Monospace">[user 
+      home]</font> has the effect that every user has an own temporary storage 
+      area.
+    </p>
+    <p class="heading2">
+      Images in new documents
+    </p>
+    <p>
+      For each newly created document a directory is created inside the 
+      temporary directory named after the document,
+    </p>
+    <p>
+      e.g. <font face="'Courier New',Monospaced,Monospace">[user 
+      home]/SimplyHTML/temp/Untitled 1/</font>.
+    </p>
+    <p>
+      If images are added to a document which has not been saved so far, 
+      directory images is created inside the temporary directory,
+    </p>
+    <p>
+      e.g. <font face="'Courier New',Monospaced,Monospace">[user 
+      home]/SimplyHTML/temp/Untitled 1/images/</font>.
+    </p>
+    <p>
+      Once a new document is saved, the image directory is copied from the 
+      temporary storage to the directory the new document has been saved.
+    </p>
+    <p class="heading2">
+      Images in existing documents
+    </p>
+    <p>
+      If images are added to an existing document, respective image files are 
+      stored in directory <font face="'Courier New',Monospaced,Monospace">
+      images</font> inside the directory the document was loaded from. 
+      Directory <font face="'Courier New',Monospaced,Monospace">images</font> 
+      is created in the directory the document was loaded from by application 
+      SimplyHTML when it is not already present an images are added to that 
+      document.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic128/topic130.htm b/src/com/lightdev/app/shtm/help/topic16/topic128/topic130.htm
new file mode 100644
index 0000000..e473c51
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic128/topic130.htm
@@ -0,0 +1,159 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a GUI to manipulate image references
+    </p>
+    <p>
+      As with <a href="../../topic16/topic86.htm">table</a> and <a href="../../topic16/topic120.htm">
+list</a> support, to create and manipulate image references a graphical user 
+      interface (GUI) is needed. Class <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font> is created for this purpose.
+    </p>
+    <p class="heading2">
+      Class ImageDialog
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">ImageDialog</font> 
+      is used to insert image references and to set all relevant attributes 
+      for these references. As well it provides a <a href="../../topic16/topic128/topic129.htm">
+repository</a> from which images can be selected, added and removed. An <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font> is divided into three panels from left to right. The left 
+      panel has a list which shows all files present in the image directory of 
+      the given document as well as buttons to add and remove images from the 
+      list. The middle panel is used as a preview region for any image 
+      selected from the image list. In the right panel all attributes of a 
+      selected image are shown and can be set.
+    </p>
+    <p class="heading2">
+      Image list maintenance
+    </p>
+    <p>
+      When an <font face="'Courier New',Monospaced,Monospace">ImageDialog</font>
+ is created, it is passed a directory which is to be used as the <a href="../../topic16/topic128/topic129.htm">
+image repository</a>. The image list is filled with the names of all files 
+      found in this directory by calls to method <font face="'Courier New',Monospaced,Monospace">
+updateFileList</font> (the method has only one line setting the <font face="'Courier New',Monospaced,Monospace">
+JList</font> content to the the current result of a directory listing of the 
+      directory referenced by <font face="'Courier New',Monospaced,Monospace">
+      imgDir</font>).
+    </p>
+    <p class="heading3">
+      Method handleAddImage
+    </p>
+    <p>
+      When button 'Add' is pressed, a file chooser is opened to allow 
+      selection of an image file to be placed into the repository. If a file 
+      is picked in the file chooser it is copied to the image repository with 
+      the help of method <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic128/topic131.htm">
+Util.copyFile</a></font> and method <font face="'Courier New',Monospaced,Monospace">
+updateFileList</font> is called to reflect the new file in the file list.
+    </p>
+    <p class="heading3">
+      Method handleDeleteImage
+    </p>
+    <p>
+      When button 'Delete' is pressed, an option dialog asks the user whether 
+      or not to delete the image file currently selected in the image list (if 
+      any). If the user chooses to really delete the selected file, it is 
+      deleted and the image list and preview are updated accordingly.
+    </p>
+    <p class="heading2">
+      Image attribute manipulation
+    </p>
+    <p>
+      Once an image is selected from the list of images, all attributes of the 
+      selected image are displayed in the panel on the right of an <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font>. From there all attributes of the image can be set 
+      accordingly. Changes to image attributes such as size or scale are 
+      reflected in the preview immediately. In addition, attributes such as 
+      border width or distance to the surrounding text can be set and will be 
+      effective on the image in the document once applied (see below).
+    </p>
+    <p>
+      In class <font face="'Courier New',Monospaced,Monospace">ImageDialog</font>
+ a set of listeners is used to synchronize all parts of the dialog to user 
+      changes of particular attributes. Section 'event handling' in the source 
+      code of class <font face="'Courier New',Monospaced,Monospace">ImageDialog</font>
+ has the mentioned listeners which are applied to respective components in the 
+      constructor of the dialog. Each listener calls helper methods such as <font face="'Courier New',Monospaced,Monospace">
+applyPreviewHeight</font>, <font face="'Courier New',Monospaced,Monospace">
+      applyPreviewWidth</font> or <font face="'Courier New',Monospaced,Monospace">
+applyPreviewScale</font> in case an event occurs which a listener is bound to.
+    </p>
+    <p class="heading3">
+      Returning image reference and image attributes
+    </p>
+    <p>
+      Once an image is selected and all attributes settings meet the desired 
+      display in the document, method <font face="'Courier New',Monospaced,Monospace">
+getImageHTML</font> returns the HTML code representing an image reference with 
+      all attributes according to the selection in the <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font>. Method <font face="'Courier New',Monospaced,Monospace">
+      getImageHTML</font> uses class <font face="'Courier New',Monospaced,Monospace">
+SHTMLWriter</font> to create an image tag and attributes from the settings on 
+      the <font face="'Courier New',Monospaced,Monospace">ImageDialog</font>.
+    </p>
+    <p>
+      The components on the <font face="'Courier New',Monospaced,Monospace">
+      ImageDialog</font> used for setting image attributes are implementing 
+      the <font face="'Courier New',Monospaced,Monospace">AttributeComponent</font>
+ interface so each of them returns its value in an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> object. All such settings are brought together in an 
+      instance of <font face="'Courier New',Monospaced,Monospace">
+      SimpleAttributeSet</font> and passed to method <font face="'Courier New',Monospaced,Monospace">
+startTag</font> of class <font face="'Courier New',Monospaced,Monospace">
+      SHTMLWriter</font> along with the actual image reference returned by 
+      method <font face="'Courier New',Monospaced,Monospace">getImageSrc</font>
+       .
+    </p>
+    <p class="heading3">
+      Setting an initial image reference and attributes
+    </p>
+    <p>
+      Besides creating new image references class <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font> can be used to display and manipulate an existing image 
+      reference too. The same functionality is used as described above after 
+      the <font face="'Courier New',Monospaced,Monospace">ImageDialog</font> 
+      has been set to an existing image reference with method <font face="'Courier New',Monospaced,Monospace">
+setImageAttributes</font>.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">setImageAttributes</font>
+ iterates through the <font face="'Courier New',Monospaced,Monospace">Vector</font>
+ of <font face="'Courier New',Monospaced,Monospace">AttributeComponents</font> 
+      and applies attributes from a given <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> to the components. As well it sets the <font face="'Courier New',Monospaced,Monospace">
+ImagePreview</font> to the image reference found in the <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font>.
+    </p>
+    <p class="heading2">
+      Image preview
+    </p>
+    <p>
+      When an image is selected from the list of images or when attributes af 
+      a selected image are changed, the resulting image as it would appear in 
+      the document is shown in the preview section of class <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font>. The preview is produced by class <font face="'Courier New',Monospaced,Monospace">
+ImagePreview</font> which is an extension to class <font face="'Courier New',Monospaced,Monospace">
+JComponent</font>.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">ImagePreview</font>
+       takes care of displaying any image and has methods to apply a given 
+      scale percentage to that image. It implements the <font face="'Courier New',Monospaced,Monospace">
+Scrollable</font> interface so it can be embedded in a <font face="'Courier New',Monospaced,Monospace">
+JScrollPane</font> for cases where an image is to be viewed in a region being 
+      smaller than respective image.
+    </p>
+    <p>
+      You can refer to the source code of <font face="'Courier New',Monospaced,Monospace">
+ImagePreview</font> for more details about how the preview of images is 
+      achieved.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic128/topic131.htm b/src/com/lightdev/app/shtm/help/topic16/topic128/topic131.htm
new file mode 100644
index 0000000..b141bce
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic128/topic131.htm
@@ -0,0 +1,194 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Implementing image storage
+    </p>
+    <p>
+      To enable image reference manipulation functionality as described in the <a href="../../topic16/topic128/topic130.htm">
+next chapter</a>, maintenance of an <a href="../../topic16/topic128/topic129.htm">
+image repository</a> is required. The following parts have been created to 
+      support image repository maintenance:
+    </p>
+    <p>
+      
+    </p>
+    <table style=" width:80%; background-color:#ffffff;">
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#cccccc; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            Class, Method, Field
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#cccccc; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            Description
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            FrmMain.appTempDir
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            new field referencing the temporary directory of application 
+            SimplyHTML
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            FrmMain.initAppTempDir()
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            method to initialize the temporary directory of application 
+            SimplyHTML
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            FrmMain.getAppTempDir()
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            method to get the directory for temporary storage of application 
+            SimplyHTML
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            DocumentPane.getImageDir()
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            method to get the image directory for a particular document open 
+            in SimplyHTML
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            DocumentPane.saveImages()
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            method to save images at a new location
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            Util.copyFile()
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e9e7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            method to copy files
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p>
+      
+    </p>
+    <p>
+      Generally speaking, an image repository always is kept with the document 
+      it belongs to. Whenever a document is saved, the image directory of the 
+      document is saved at the same location, necessarily copying image files 
+      as described below.
+    </p>
+    <p class="heading2">
+      Methods initAppTempDir and getAppTempDir
+    </p>
+    <p>
+      With method <font face="'Courier New',Monospaced,Monospace">
+      initAppTempDir</font> of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> new field <font face="'Courier New',Monospaced,Monospace">
+      appTempDir</font> is initialized. The method creates a file object 
+      referencing a directory named <font face="'Courier New',Monospaced,Monospace">
+[user home]/SimplyHTML/temp</font>. If the directory does not exist it is 
+      created by method <font face="'Courier New',Monospaced,Monospace">
+      initAppTempDir</font>.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">getAppTempDir</font>
+ publicly makes available field <font face="'Courier New',Monospaced,Monospace">
+appTempDir</font> for read only access.
+    </p>
+    <p class="heading2">
+      Method saveImages
+    </p>
+    <p>
+      In class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font>
+ documents are being saved with method <font face="'Courier New',Monospaced,Monospace">
+saveDocument</font>. With the new image support of stage 7 of SImplyHTML 
+      document storage has to be extended by a method to save any image files 
+      referenced in a particular document.
+    </p>
+    <p>
+      New method <font face="'Courier New',Monospaced,Monospace">saveImages</font>
+ of class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      is called by method <font face="'Courier New',Monospaced,Monospace">
+      saveDocument</font> for this task. It uses new method <font face="'Courier New',Monospaced,Monospace">
+getImageDir</font> (see below) to find out the source location of any image 
+      files. It then copies all image files to the location, the document is 
+      being saved to using method <font face="'Courier New',Monospaced,Monospace">
+copyFile</font> of class <font face="'Courier New',Monospaced,Monospace">Util</font>
+ (see below).
+    </p>
+    <p class="heading3">
+      Method getImageDir
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">getImageDir</font>
+       finds out the source location of image files for a document to be 
+      saved. The method checks whether images are currently stored in a 
+      temporary directory for a given document. If the document was not newly 
+      created, <font face="'Courier New',Monospaced,Monospace">getImageDir</font>
+ finds out if the document is about to be saved at a new location (save as) or 
+      if it is being saved at the location it was loaded from (save) in which 
+      cases the source locations are to be taken from different locations in 
+      class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font>
+       .
+    </p>
+    <p>
+      The source image directory is returned to the calling method.
+    </p>
+    <p class="heading2">
+      Method copyFile
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">copyFile</font> 
+      in class <font face="'Courier New',Monospaced,Monospace">Util</font> is 
+      a simple way to copy a file from one location to another. It accepts two 
+      file objects as parameters for the source and destination file to be 
+      copied. It opens <font face="'Courier New',Monospaced,Monospace">
+      RandomAccessFile</font> objects for the two files and creates the 
+      destination file if necessary. It then reads blocks of content bytes 
+      from the source file and writes them to the destination file.
+    </p>
+    <p>
+      If the destination file already exists, <font face="'Courier New',Monospaced,Monospace">
+copyFile</font> does nothing.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic128/topic133.htm b/src/com/lightdev/app/shtm/help/topic16/topic128/topic133.htm
new file mode 100644
index 0000000..8064f09
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic128/topic133.htm
@@ -0,0 +1,62 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Making the GUI available to the user
+    </p>
+    <p>
+      As functionality and GUI for manipulation of image references as 
+      described in <a href="../../topic16/topic128/topic130.htm">previous 
+      chapters</a> is present, a way to use it is needed in addition.
+    </p>
+    <p class="heading2">
+      Actions InsertImage and FormatImage
+    </p>
+    <p>
+      Similar to the procedure used in previous stages, two actions are added 
+      to class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      as inner classes. The new actions are added to the <font face="'Courier New',Monospaced,Monospace">
+DynamicResource</font> instance of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> with method <font face="'Courier New',Monospaced,Monospace">
+      initActions</font> (see the documentation of <a href="../../topic16/topic62.htm">
+stage 2</a> and <a href="../../topic16/topic103.htm">stage 5</a> for a 
+      detailed description of actions and dynamic resources).
+    </p>
+    <p>
+      Actions <font face="'Courier New',Monospaced,Monospace">InsertImageAction</font>
+ and <font face="'Courier New',Monospaced,Monospace">FormatImageAction</font> 
+      both create an instance of class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic128/topic130.htm">
+ImageDialog</a></font>. <font face="'Courier New',Monospaced,Monospace">
+      FormatImageAction</font> shows the dialog reflecting settings for an 
+      image currently selected in the editor to allow for attribute 
+      adjustments or to change the image file. <font face="'Courier New',Monospaced,Monospace">
+InsertImageAction</font> brings up the dialog to select a file from the image 
+      repository and adjust attributes.
+    </p>
+    <p class="heading2">
+      How image settings are applied
+    </p>
+    <p>
+      When a selection is made in class <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font> <font face="'Courier New',Monospaced,Monospace">
+      InsertImageAction</font> applies the settings with the help of method <font face="'Courier New',Monospaced,Monospace">
+insertBeforeStart</font> of class <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>. The chosen image from class <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font> is taken as HTML code got from method <font face="'Courier New',Monospaced,Monospace">
+getImageHTML</font> and passed to method <font face="'Courier New',Monospaced,Monospace">
+insertBeforeStart</font>.
+    </p>
+    <p>
+      When an existing image reference is changed with <font face="'Courier New',Monospaced,Monospace">
+FormatImageAction</font>, method <font face="'Courier New',Monospaced,Monospace">
+getImageHTML</font> is used to get the image settings as HTML code again. The 
+      HTML code is passed to method <font face="'Courier New',Monospaced,Monospace">
+setOuterHTML</font> of class <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font> in this case, replacing the changed image reference.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic128/topic134.htm b/src/com/lightdev/app/shtm/help/topic16/topic128/topic134.htm
new file mode 100644
index 0000000..25bd672
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic128/topic134.htm
@@ -0,0 +1,92 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Image references in HTML
+    </p>
+    <p>
+      In HTML images are separated from documents. Documents contain 
+      references to image files in the place where images should appear inside 
+      a document. An image reference describes the location and name of 
+      respective image file as well as how it is to be rendered. The actual 
+      images are stored separately in image files and loaded dynamically when 
+      documents are displayed.
+    </p>
+    <p>
+      An image reference in HTML is expressed by an <font face="'Courier New',Monospaced,Monospace">
+img</font> tag having the reference attribute and additional attributes such 
+      as in
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace"><img 
+      src="images/picture.jpg" border=0 width=100 height=200></font>
+
+    </p>
+    <p>
+      The image reference attribute (attribute <font face="'Courier New',Monospaced,Monospace">
+src</font>) can be either an absolute or relative path and file name 
+      expression. The other attributes specify information about how the image 
+      is to be displayed such as image width and height or how much space 
+      between text and image is to be rendered.
+    </p>
+    <p class="heading2">
+      Absolute references
+    </p>
+    <p>
+      An absolute reference is an expression containig the full path and name 
+      of an image file such as in
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">
+      file:/C:/data/documents/myDoc/images/picture.jpg</font>
+    </p>
+    <p>
+      Absolute image references should be avoided as they need to be changed 
+      whenever the image file is moved to another location.
+    </p>
+    <p class="heading2">
+      Relative references
+    </p>
+    <p>
+      A relative reference has path and file name information relative to the 
+      location a HTML document is stored. An expression such as
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">images/picture.jpg</font>
+    </p>
+    <p>
+      inside a document stored as
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">
+      c:\data\document\myDoc\doc.htm</font>
+    </p>
+    <p>
+      would mean the same as the absolute reference expression from previous 
+      paragraph. The main difference however is that whenever the document and 
+      image file are moved to a new location together, the relative reference 
+      can remain unchanged.
+    </p>
+    <p class="heading2">
+      Resolving relative references
+    </p>
+    <p>
+      In SimplyHTML's implementation of image support only relative references 
+      are used. To resolve relative image references, class <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> allows to specify a base location with method <font face="'Courier New',Monospaced,Monospace">
+setBase</font>. When a document is loaded, its source path is passed to method <font face="'Courier New',Monospaced,Monospace">
+setBase</font> as the the base directory. When a new document is created, a <a href="../../topic16/topic128/topic129.htm">
+temporary directory</a> is set with method <font face="'Courier New',Monospaced,Monospace">
+setBase</font>.
+    </p>
+    <p>
+      In both cases all relative references are resolved against the base 
+      directory set with method <font face="'Courier New',Monospaced,Monospace">
+setBase</font>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140.htm b/src/com/lightdev/app/shtm/help/topic16/topic140.htm
new file mode 100644
index 0000000..9a6a5fa
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140.htm
@@ -0,0 +1,71 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 8: Paragraph styles and named styles
+    </p>
+    <p class="heading2">
+      Paragraph styles
+    </p>
+    <p>
+      In <a href="../topic16/topic74.htm">stage 3</a> of SimplyHTML font 
+      manipulation was added to the application. Font settings are applied to 
+      individual parts of a document down to single characters with this 
+      functionality. With paragraph styles such settings can be applied to one 
+      or more paragraphs in one step too. As well paragraph styles allow to 
+      manipulate additional attributes such as alignment or margins.
+    </p>
+    <p class="heading2">
+      Named styles
+    </p>
+    <p>
+      Named styles in turn are an elegant way to define styles that are 
+      frequently used and store them in a separate <a href="../topic16/topic4/topic25/topic42.htm">
+style sheet</a>. Usage of style sheets was already part of application 
+      SimplyHTML since the <a href="../topic16/topic4.htm">first stage</a> 
+      however this stage finally adds functionality to use style sheets to 
+      their original purpose.
+    </p>
+    <p class="heading2">
+      Contents of this stage
+    </p>
+    <p>
+      Implementation of both paragraph styles and named styles is the subject 
+      of this stage and explained in detail in the follwoing chapters
+    </p>
+    <ul>
+      <li>
+        <a href="../topic16/topic140/topic141.htm">Styles in HTML and CSS</a>
+      </li>
+      <li>
+        <a href="../topic16/topic140/topic144.htm">Parts needed to implement 
+        style manipulation</a>
+      </li>
+      <li>
+        <a href="../topic16/topic140/topic145.htm">Approach to work with 
+        paragraph and named styles</a>
+      </li>
+      <li>
+        <a href="../topic16/topic140/topic146.htm">Class ParaStyleDialog</a>
+      </li>
+      <li>
+        <a href="../topic16/topic140/topic147.htm">Class StyleSelector</a>
+      </li>
+      <li>
+        <a href="../topic16/topic140/topic148.htm">Interaction between style 
+        components and style sheet</a>
+      </li>
+      <li>
+        <a href="../topic16/topic140/topic149.htm">Adding the new style 
+        components to the GUI</a>
+      </li>
+      <li>
+        <a href="../topic16/topic140/topic150.htm">Style sheet storage</a>
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140/topic141.htm b/src/com/lightdev/app/shtm/help/topic16/topic140/topic141.htm
new file mode 100644
index 0000000..d4b0a44
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140/topic141.htm
@@ -0,0 +1,72 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Styles in HTML and CSS
+    </p>
+    <p class="heading2">
+      Character attributes vs. paragraph attributes
+    </p>
+    <p>
+      The simplest way to apply a certain format to a portion of a HTML 
+      document is to store HTML format attributes such as <font face="'Courier New',Monospaced,Monospace">
+b</font>, <font face="'Courier New',Monospaced,Monospace">i</font> or <font face="'Courier New',Monospaced,Monospace">
+align</font> with any tag to be formatted in the particular way. While this 
+      approach is most flexible in terms of combination of such attributes, 
+      plain HTML attributes allow only limited formatting compared to CSS 
+      styles. As well this method adds a lot of formatting information to the 
+      plain content of a document with much rendundancy in most cases.
+    </p>
+    <p class="heading2">
+      CSS attributes
+    </p>
+    <p>
+      By using the <font face="'Courier New',Monospaced,Monospace">style</font>
+       attribute, CSS attributes such as <font face="'Courier New',Monospaced,Monospace">
+margin-top</font>, <font face="'Courier New',Monospaced,Monospace">
+      padding-right</font>, <font face="'Courier New',Monospaced,Monospace">
+      text-align</font>, etc. can be added to HTML tags instead. This method 
+      opens additional formatting settings but it still requires attributes to 
+      be stored with each tag having the same impact as HTML attributes.
+    </p>
+    <p class="heading2">
+      Paragraph styles
+    </p>
+    <p>
+      To reduce the formatting overhead HTML and CSS attributes can be applied 
+      to paragraph tags so that they are valid on any tag contained in such 
+      paragraph.
+    </p>
+    <p class="heading2">
+      Style sheets with named styles
+    </p>
+    <p>
+      The most flexibility and power however is reached with usage of <a href="../../topic16/topic4/topic25/topic42.htm">
+Cascading Style Sheets (CSS)</a> in combination with a given HTML document. By 
+      defining styles in a separate <a href="../../topic16/topic4/topic25/topic42.htm">
+style sheet</a> groups of format attributes can be held independent from HTML 
+      documents resulting in significant advantages
+    </p>
+    <ul>
+      <li>
+        styles are defined only once avoiding rendundancies and increasing 
+        maintainability
+      </li>
+      <li>
+        styles can be shared over many documents again reducing redundancy and 
+        maintenance efforts
+      </li>
+      <li>
+        documents only need references to styles reducing storage space
+      </li>
+      <li>
+        a predefined group of attributes can be applied in a single making 
+        formatting faster
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140/topic144.htm b/src/com/lightdev/app/shtm/help/topic16/topic140/topic144.htm
new file mode 100644
index 0000000..614f26a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140/topic144.htm
@@ -0,0 +1,181 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Parts needed to implement style manipulation
+    </p>
+    <p>
+      While many existing functions of SimplyHTML and the Java classes can be 
+      used to build the new style setting functionality, some additional parts 
+      are needed too. The following table gives an overview of all new or 
+      changed items
+    </p>
+    <p>
+      
+    </p>
+    <table style=" width:80%; background-color:#ffffff;">
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            <b>Class </b>
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e3e3e3; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            <b>Purpose, Changes</b>
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            AttributePanel
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            Panel to set a group of attributes, base class for other classes 
+            such as margin or style panel
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            CSSWriter
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            Enhanced method structure for writing individual styles
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            DocumentPane
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            additional methods for style sheet storage and merging style sheets
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            FrmMain
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new actions for paragraph and named style formatting as well as 
+            new tool bar component for setting named styles, some methods and 
+            inner classes consolidated to avoid redundancies
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            MarginPanel
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new class to set margins and paddings, made stand alone class from 
+            former inner class to share functionality between table and 
+            paragraph dialog
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            ParaStyleDialog
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            dialog for setting either paragraph styles or named styles
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            StylePanel
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new class to set paragraph attributes, made stand alone class from 
+            former inner class to share functionality between table and 
+            paragraph dialog
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            StyleSelector
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            component to apply named styles through the tool bar
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            Util
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            utility methods for working with internationalized option panes, 
+            resolving nested attribute sets and style sheets
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p class="heading2">
+      Mostly GUI changes
+    </p>
+    <p>
+      Functionality to read, modify and apply attributes has already been 
+      created in previous stages and can be re-used in this stage unchanged. 
+      Working with named styles and style sheets is covered by class <font face="'Courier New',Monospaced,Monospace">
+StyleSheet</font> of the Java Swing package in addition.
+    </p>
+    <p>
+      Therefore above parts almost all are GUI elements. Some 'non-GUI' 
+      methods and changes had to be added in this stage mainly to classes <font face="'Courier New',Monospaced,Monospace">
+CSSWriter</font> and <font face="'Courier New',Monospaced,Monospace">Util</font>
+ and the only other 'non-GUI' method <font face="'Courier New',Monospaced,Monospace">
+saveStyleAs</font> in class <font face="'Courier New',Monospaced,Monospace">
+      ParaStyleDialog</font> was too small to create an extension to class <font face="'Courier New',Monospaced,Monospace">
+StyleSheet</font> for it.
+    </p>
+    <p>
+      In essence this stage mainly adds GUI extensions and relies on exisiting 
+      functionality of previous stages and the Java classes to implement style 
+      manipulation.
+    </p>
+    <p class="heading3">
+      Much interaction
+    </p>
+    <p>
+      Nevertheless a lot of interaction between the mentioned parts is 
+      necessary so that an emphasis in this stage of the tutorial lies on 
+      explaining these interactions and their implementation as well.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140/topic145.htm b/src/com/lightdev/app/shtm/help/topic16/topic140/topic145.htm
new file mode 100644
index 0000000..faf47c6
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140/topic145.htm
@@ -0,0 +1,77 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Approach to work with paragraph and named styles
+    </p>
+    <p>
+      As <a href="../../topic16/topic140/topic144.htm">pointed out</a>, style 
+      manipulation functionality is already exisiting in the Java classes and 
+      the previous stages of application SimplyHTML. What is needed in 
+      addition is a GUI to visualize the existing styles and to let the user 
+      add new, change existing or delete styles.
+    </p>
+    <p class="heading2">
+      Dialog to manipulate styles
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic140/topic146.htm">
+ParaStyleDialog</a></font> is added to SimplyHTML as a new component to 
+      achieve this. Class <font face="'Courier New',Monospaced,Monospace">
+      ParaStyleDialog</font> has two major functions:
+    </p>
+    <ul>
+      <li>
+        to manipulate any given paragraph style and
+      </li>
+      <li>
+        to maintain all paragraph styles in a given style sheet.
+      </li>
+    </ul>
+    <p>
+      Because both tasks require the same elements (components to reflect 
+      settings of paragraph attributes), they are combined inside class <font face="'Courier New',Monospaced,Monospace">
+ParaStyleDialog</font> and made available as two separate operation modes of 
+      the component.
+    </p>
+    <p class="heading2">
+      Components to select named styles and alignment
+    </p>
+    <p>
+      To make available existing named styles for paragraphs as defined in the 
+      style sheet, class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic140/topic147.htm">
+StyleSelector</a></font> is created. It shows all available named paragraph 
+      styles and lets the user apply a given style to the currently selected 
+      paragraph(s).
+    </p>
+    <p>
+      A paragraph attribute which is used quite often is the text alignment 
+      setting (left, center or right). For setting text alignmen in one step, 
+      inner class <font face="'Courier New',Monospaced,Monospace">
+      ToggleFontAction</font> has been changed to class <font face="'Courier New',Monospaced,Monospace">
+ToggleAction</font> and can now can be used as a generic action to toggle 
+      certain character and paragraph attributes including text aligment. The 
+      new action is used by SimplyHTML's <a href="../../topic16/topic103/topic111.htm">
+dynamic resource mechanism</a> to add respective <a href="../../topic16/topic140/topic149.htm">
+toggle button</a> components to the tool bar.
+    </p>
+    <p class="heading2">
+      Style sheet storage
+    </p>
+    <p>
+      As stage 8 allows to change contents of a given style sheet, the way a 
+      style sheet is saved has to be <a href="../../topic16/topic140/topic150.htm">
+revised</a>. When a document is saved, SimplyHTML now recogniszes whether or 
+      not a style sheet with the same name exists in the location where a 
+      document is to be saved.
+    </p>
+    <p>
+      Is a style sheet present already, it is merged with the style sheet to 
+      be saved.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140/topic146.htm b/src/com/lightdev/app/shtm/help/topic16/topic140/topic146.htm
new file mode 100644
index 0000000..07a18ff
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140/topic146.htm
@@ -0,0 +1,163 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Class ParaStyleDialog
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font>
+ has two major functions:
+    </p>
+    <ul>
+      <li>
+        to manipulate any given paragraph style and
+      </li>
+      <li>
+        to maintain all paragraph styles in a given style sheet.
+      </li>
+    </ul>
+    <p>
+      The two tasks are available as two separate operation modes of the 
+      component, <font face="'Courier New',Monospaced,Monospace">
+      MODE_PARAGRAPH_STYLE</font> and <font face="'Courier New',Monospaced,Monospace">
+MODE_NAMED_STYLES</font>.
+    </p>
+    <p>
+      In <font face="'Courier New',Monospaced,Monospace">MODE_PARAGRAPH_STYLE</font>
+ class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font> 
+      is used to directly manipulate a given set of paragraph style 
+      attributes. In <font face="'Courier New',Monospaced,Monospace">
+      MODE_NAMED_STYLES</font>, the dialog is used to manipulate styles in a 
+      style sheet which does not affect formats of the underlying document 
+      directly (only indirect through style sheet changes).
+    </p>
+    <p class="heading2">
+      Setting the operation mode
+    </p>
+    <p>
+      The operation mode is derived from the constructor used to create a <font face="'Courier New',Monospaced,Monospace">
+ParaStyleDialog</font>. When constructed to operate with a certain <font face="'Courier New',Monospaced,Monospace">
+Document</font>, <font face="'Courier New',Monospaced,Monospace">
+      MODE_NAMED_STYLES</font> is assumed and the <font face="'Courier New',Monospaced,Monospace">
+Document's</font> style sheet is taken to be operated upon.
+    </p>
+    <p>
+      If no <font face="'Courier New',Monospaced,Monospace">Document</font> is 
+      passed to the constructor of <font face="'Courier New',Monospaced,Monospace">
+ParaStyleDialog</font>, it is constructed in <font face="'Courier New',Monospaced,Monospace">
+MODE_PARAGRAPH_STYLE</font>, i.e. not using a style sheet.
+    </p>
+    <p class="heading2">
+      Passing initial dialog settings
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font>
+ implements interface <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic86/topic93.htm">
+AttributeComponent</a></font> (introduced as <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic74/topic75.htm">
+FontComponent</a></font> initially in stage 3) so that its contents can be set 
+      or read through a set of attributes in an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> object. When in <font face="'Courier New',Monospaced,Monospace">
+MODE_PARAGRAPH_STYLE</font>, initial dialog contents need to be set by a call 
+      to method <font face="'Courier New',Monospaced,Monospace">setValue</font>
+       passing an <font face="'Courier New',Monospaced,Monospace">AttributeSet</font>
+ object having all initial paragraph styles to be manipulated.
+    </p>
+    <p>
+      When in <font face="'Courier New',Monospaced,Monospace">MODE_NAMED_STYLES</font>
+ , a list of existing named paragraph styles is read from the style sheet of 
+      the <font face="'Courier New',Monospaced,Monospace">Document</font> 
+      passed in the constructor. Whenever a style is picked from those, the 
+      dialog is set to show the attributes of this style.
+    </p>
+    <p class="heading2">
+      Reading dialog settings
+    </p>
+    <p>
+      As an <font face="'Courier New',Monospaced,Monospace">AttributeComponent</font>
+ class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font> 
+      returns its currents attribute settings in an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> object through method <font face="'Courier New',Monospaced,Monospace">
+getValue</font>. In <font face="'Courier New',Monospaced,Monospace">
+      MODE_PARAGRAPH_STYLE</font> method <font face="'Courier New',Monospaced,Monospace">
+getValue</font> can be used to get the set of attrbutes to be applied.
+    </p>
+    <p>
+      In <font face="'Courier New',Monospaced,Monospace">MODE_NAMED_STYLES</font>
+ class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font> 
+      is not meant to deliver a set of attribute settings, although method <font face="'Courier New',Monospaced,Monospace">
+setValue</font> certainly can be used too. Instead, the dialog only makes 
+      available all named paragraph styles found in a given style sheet.
+    </p>
+    <p>
+      All changes to a given set of paragraph attributes can be saved to that 
+      style sheet using class <font face="'Courier New',Monospaced,Monospace">
+      ParaStyleDialog</font>. By changing attribute settings of an existing 
+      named paragraph style and storing them back to the style sheet, format 
+      of all paragraphs using respective named style is changed implicitly, 
+      immediately and automatically in the underlying document.
+    </p>
+    <p>
+      Thus no direct reading of attribute settings is necessary in <font face="'Courier New',Monospaced,Monospace">
+MODE_NAMED_STYLES</font>.
+    </p>
+    <p class="heading2">
+      Style sheet manipulation
+    </p>
+    <p>
+      In <font face="'Courier New',Monospaced,Monospace">MODE_NAMED_STYLES</font>
+ class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font> 
+      offers to
+    </p>
+    <ul>
+      <li>
+        save settings to an existing named style
+      </li>
+      <li>
+        create a new named style and
+      </li>
+      <li>
+        to remove an exsting named style from the style sheet
+      </li>
+    </ul>
+    <p>
+      Saving attributes to an existing style and creation of a new style both 
+      is done using method <font face="'Courier New',Monospaced,Monospace">
+      addRule</font> of class <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet</font>. This method expects a style to be passed in the form 
+      of a CSS declaration string,
+    </p>
+    <p>
+      e.g. <font face="'Courier New',Monospaced,Monospace">p.myStyle { 
+      text-align:center; }</font>.
+    </p>
+    <p>
+      To transform attribute settings from class <font face="'Courier New',Monospaced,Monospace">
+ParaStyleDialog</font> in to this format, method <font face="'Courier New',Monospaced,Monospace">
+writeRule</font> of class <font face="'Courier New',Monospaced,Monospace">
+      CSSWriter</font> is used.To remove an existing style from the style 
+      sheet class <font face="'Courier New',Monospaced,Monospace">
+      ParaStyleDialog</font> uses method <font face="'Courier New',Monospaced,Monospace">
+removeStyle</font> of class <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet</font>.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font>
+ adds methods necessary to interact with the user upon style changes 
+      accordingly, e.g. by asking whether or not to really delete a particular 
+      style or by checking whether or not a style shall be overwritten having 
+      the same name as a name entered by the user.
+    </p>
+    <p>
+      With stage 8 class <font face="'Courier New',Monospaced,Monospace">Util</font>
+ has some new methods combining a generic <font face="'Courier New',Monospaced,Monospace">
+JOptionPane</font> with calls to SimplyHTML's class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic103/topic111.htm">
+DynamicResource</a></font> for support of messages in <a href="../../topic16/topic62/topic70.htm">
+other languages</a>. These methods are applied to other usages of <font face="'Courier New',Monospaced,Monospace">
+JOptionPane</font> in SimplyHTML as well.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140/topic147.htm b/src/com/lightdev/app/shtm/help/topic16/topic140/topic147.htm
new file mode 100644
index 0000000..2b50799
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140/topic147.htm
@@ -0,0 +1,36 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Class StyleSelector
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">StyleSelector</font>
+ is a component used to make available a list of existing named paragraph 
+      styles and to apply a named style to the currently selected 
+      parapraph(s). It extends class <font face="'Courier New',Monospaced,Monospace">
+JComboBox</font> by implementing interfaces <font face="'Courier New',Monospaced,Monospace">
+AttributeComponent</font> and <font face="'Courier New',Monospaced,Monospace">
+      ChangeListener</font>.
+    </p>
+    <p>
+      Added to a tool bar its method <font face="'Courier New',Monospaced,Monospace">
+getValue</font> allows access to the currently set style while method <font face="'Courier New',Monospaced,Monospace">
+setValue</font> can be used to reflect the style of the paragraph the caret is 
+      currently in.
+    </p>
+    <p>
+      As desribed in more detail in the next chapter, class <font face="'Courier New',Monospaced,Monospace">
+StyleSelector</font> listens to changes in the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> of class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font> and to changes of a given style sheet. Whenever the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> or the style sheet changes (i.e. another document is active 
+      or the styles have changed), the list of named paragraph styles in the <font face="'Courier New',Monospaced,Monospace">
+StyleSelector</font> is updated.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140/topic148.htm b/src/com/lightdev/app/shtm/help/topic16/topic140/topic148.htm
new file mode 100644
index 0000000..58e8454
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140/topic148.htm
@@ -0,0 +1,109 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Interaction between style components and style sheet
+    </p>
+    <p>
+      As described <a href="../../topic16/topic140/topic144.htm">previously</a>
+       , several components are involved in paragraph and named styles 
+      manipulation:
+    </p>
+    <ul>
+      <li>
+        the style sheet of the document currently edited,
+      </li>
+      <li>
+        the <font face="'Courier New',Monospaced,Monospace">JTabbedPane</font> 
+        of class <font face="'Courier New',Monospaced,Monospace">FrmMain</font>
+         ,
+      </li>
+      <li>
+        the <font face="'Courier New',Monospaced,Monospace">StyleSelector</font>
+ in the tool bar,
+      </li>
+      <li>
+        the list of named styles in class <font face="'Courier New',Monospaced,Monospace">
+ParaStyleDialog</font>.
+      </li>
+    </ul>
+    <p>
+      Components reflecting named styles have to be updated accordingly when
+    </p>
+    <ul>
+      <li>
+        a new document is created,
+      </li>
+      <li>
+        an existing document is opened,
+      </li>
+      <li>
+        another document in the group of currently open documents is activated 
+        or
+      </li>
+      <li>
+        the style sheet of the currently edited document changes.
+      </li>
+    </ul>
+    <p class="heading2">
+      Listeners to watch for changes
+    </p>
+    <p>
+      Instead of implementing hard wired relations between objects to handle 
+      style related events, application SimplyHTML implements listeners with 
+      these objects.
+    </p>
+    <p class="heading3">
+      StyleSelector
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">StyleSelector</font>
+ implements the <font face="'Courier New',Monospaced,Monospace">ChangeListener</font>
+ interface to handle <font face="'Courier New',Monospaced,Monospace">
+      ChangeEvents</font>. The <font face="'Courier New',Monospaced,Monospace">
+      StyleSelector</font> object in the tool bar is registered as a <font face="'Courier New',Monospaced,Monospace">
+ChangeListener</font> with the style sheet of any document with method <font face="'Courier New',Monospaced,Monospace">
+registerDocument</font> of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>. With that the <font face="'Courier New',Monospaced,Monospace">
+      StyleSelector</font> object is notified whenever a style sheet changes. 
+      When a document is closed, class <font face="'Courier New',Monospaced,Monospace">
+StyleSelector</font> is removed as a <font face="'Courier New',Monospaced,Monospace">
+ChangeListener</font> in method <font face="'Courier New',Monospaced,Monospace">
+unregisterDocument</font> of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>.
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">createToolBar</font>
+ of class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> class <font face="'Courier New',Monospaced,Monospace">
+StyleSelector</font> is registered with <font face="'Courier New',Monospaced,Monospace">
+FrmMain's</font> <font face="'Courier New',Monospaced,Monospace">JTabbedPane</font>
+ as <font face="'Courier New',Monospaced,Monospace">ChangeListener</font> too. 
+      Whenever another document is activated in the JTabbedPane, the <font face="'Courier New',Monospaced,Monospace">
+StyleSelector</font> object in the tool bar is notified.
+    </p>
+    <p class="heading3">
+      ParaStyleDialog
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font>
+ is also implementing the <font face="'Courier New',Monospaced,Monospace">
+      ChangeListener</font> interface. It registers itself as a <font face="'Courier New',Monospaced,Monospace">
+ChangeListener</font> with the style sheet of the currently active document. 
+      Whenever class <font face="'Courier New',Monospaced,Monospace">
+      ParaStyleDialog</font> is used in <font face="'Courier New',Monospaced,Monospace">
+MODE_NAMED_STYLE</font> and a style is saved to the style sheet, the 
+      respective change event triggers an update of class <font face="'Courier New',Monospaced,Monospace">
+ParaStyleDialog's</font> list of named styles.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">ParaStyleDialog</font>
+ overrides method <font face="'Courier New',Monospaced,Monospace">dispose</font>
+ to remove itself from the list of <font face="'Courier New',Monospaced,Monospace">
+ChangeListeners</font> of the underlying style sheet.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140/topic149.htm b/src/com/lightdev/app/shtm/help/topic16/topic140/topic149.htm
new file mode 100644
index 0000000..0e08b4d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140/topic149.htm
@@ -0,0 +1,95 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Adding the new style components to the GUI
+    </p>
+    <p>
+      As in previous stages actions are used to connect the new functionality 
+      to the GUI elements such as menus or the tool bar. There are three new 
+      actions and one changed action in class FrmMain
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">FormatParaAction</font>
+         - action to set paragraph styles
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">EditNamedStyleAction</font>
+ - action to manipulate named styles
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">SetStyleAction</font> 
+        - action to apply a given named style to the current selection
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">ToggleAction</font> - 
+        adaption of former ToggleFontAction to support paragraph alignment too
+      </li>
+    </ul>
+    <p>
+      The actions are initialized in method <font face="'Courier New',Monospaced,Monospace">
+initActions</font> of class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font> and are added to <font face="'Courier New',Monospaced,Monospace">
+FrmMain's</font> dynamic resource.
+    </p>
+    <p class="heading3">
+      FormatParaAction and EditNamedStyleAction
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">FormatParaAction</font> 
+      and <font face="'Courier New',Monospaced,Monospace">EditNamedStyleAction</font>
+ both create an instance of <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic140/topic146.htm">
+ParaStyleDialog</a></font>. <font face="'Courier New',Monospaced,Monospace">
+      FormatParaAction</font> uses the set of attributes returned by <font face="'Courier New',Monospaced,Monospace">
+ParaStyleDialog</font> and applies them to the currently selected 
+      paragraph(s). <font face="'Courier New',Monospaced,Monospace">
+      EditNamedStyleAction</font> does nothing on return of <font face="'Courier New',Monospaced,Monospace">
+ParastyleDialog</font>, the dialog does all the work for manipulation of named 
+      styles.
+    </p>
+    <p class="heading3">
+      SetStyleAction
+    </p>
+    <p>
+      SetStyleAction takes the class attribute returned by the StyleSelector 
+      component in the tool bar and applies it to the currently selected 
+      paragraph(s).
+    </p>
+    <p class="heading3">
+      ToggleAction
+    </p>
+    <p>
+      ToggleAction applies the attribute returned by its getValue method to 
+      the current selection. Depending on the attribute key the action object 
+      represents attriubtes are applied to either on paragraph or character 
+      level. The action then sets a state indicator to allow a bound component 
+      such as a JToggleButton to reflect the state accordingly (selected or 
+      unselected).
+    </p>
+    <p class="heading2">
+      New components
+    </p>
+    <p>
+      Besides the new <font face="'Courier New',Monospaced,Monospace">
+      StyleSelector</font> component, in method <font face="'Courier New',Monospaced,Monospace">
+createToolBar</font> of class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font>, additional toggle buttons are created to toggle between 
+      different paragrpah alignments (left, center, right). A new tool bar 
+      button for setting a paragraph style is added too. In menu 'Format', new 
+      menu items are created for setting paragraph style, style sheet 
+      manipulation and paragraph alignment.
+    </p>
+    <p>
+      All new components are added by including their associated action names 
+      in the properties file of SimplyHTML as described in <a href="../../topic16/topic62.htm">
+stage 2</a> and especially '<a href="../../topic16/topic62/topic66.htm">Adding 
+      an edit menu</a>' as well as '<a href="../../topic16/topic103/topic111.htm">
+Dynamic resources</a>' from <a href="../../topic16/topic103.htm">stage 5</a>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic140/topic150.htm b/src/com/lightdev/app/shtm/help/topic16/topic140/topic150.htm
new file mode 100644
index 0000000..e4c6883
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic140/topic150.htm
@@ -0,0 +1,95 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Style sheet storage
+    </p>
+    <p>
+      Style sheets are part of SimplyHTML since <a href="../../topic16/topic4.htm">
+stage 1</a> of the application. Since then they were only saved along with a 
+      document with a set of static styles. With stage 8 of SimplyHTML 
+      manipulation of named styles is supported so that the original style 
+      sheet handling needs to be extended.
+    </p>
+    <p class="heading2">
+      Loading style sheets
+    </p>
+    <p>
+      Class DocumentPane now has two ways of creating a document with respect 
+      to style sheets. A new document is created with the underlying EditorKit 
+      creating a default style sheet from the resources package of SimplyHTML 
+      (as done in previous stages).
+    </p>
+    <p>
+      This is not longer done when an existing document is loaded. In such 
+      case the underlying EditorKit creates a default document without a 
+      default style sheet. Class DocumentPane instead looks for the style 
+      sheet reference inside this document and loads this style sheet for the 
+      particular document instead.
+    </p>
+    <p>
+      The EditorKit not longer shares a single style sheet among different 
+      documents, each document has associated its own style sheet.
+    </p>
+    <p class="heading2">
+      Saving style sheets
+    </p>
+    <p>
+      When a style sheet is saved, four cases are now handled
+    </p>
+    <ol>
+      <li>
+        no styles are present at save location, create new style sheet
+      </li>
+      <li>
+        the style sheet was loaded from somewhere else and now is being saved 
+        at a new location where a style sheet exists havig the same name
+      </li>
+      <li>
+        the style sheet is saved at the same location where it was loaded from
+      </li>
+      <li>
+        the style sheet was newly created and now is being saved at a location 
+        where a style sheet exists havig the same name
+      </li>
+    </ol>
+    <p>
+      In case 2 and 4 above, the style sheets are merged overwriting existing 
+      styles in the found style sheet with styles from the saved style sheet. 
+      Styles from the found style sheet not existing in the saved style sheet 
+      are kept in the newly saved style sheet.
+    </p>
+    <p>
+      In case 3 above the existing style sheet is overwritten by the new 
+      version.
+    </p>
+    <p class="heading3">
+      Tradeoffs
+    </p>
+    <p>
+      While above save strategy does not require user interaction other than 
+      to choose a save loaction and name for the respective document (as 
+      before) it still leaves the problem that an existing style sheet with 
+      the same name could have styles with the same name as altered ones in 
+      the saved style sheet. Overwriting such styles could cause unwanted 
+      styles to appear in other documents sharing the particular style sheet.
+    </p>
+    <p>
+      Therefore the user is obliged to either
+    </p>
+    <ol>
+      <li>
+        not save documents in the same directory when they do not share the 
+        same set of named styles or
+      </li>
+      <li>
+        use different style names for different styles over all documents 
+        sharing the same style sheet
+      </li>
+    </ol>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic152.htm b/src/com/lightdev/app/shtm/help/topic16/topic152.htm
new file mode 100644
index 0000000..e61a10c
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic152.htm
@@ -0,0 +1,55 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 9: Links
+    </p>
+    <p>
+      In this stage creation and manipulation of links is implemented. While a 
+      link seems to be a rather trivial element in an HTML document, working 
+      with links without knowing how to to type in HTML code requires a quite 
+      complex GUI. This is because links can have many different forms with 
+      several exceptional handling of certain link types.
+    </p>
+    <p>
+      To allow for links referencing certain parts inside a given document, a 
+      way to edit so called link anchors is needed in addition.
+    </p>
+    <p>
+      Besides links and link anchors, stage 9 has some refined handling of 
+      paragraph tags and named styles from previous stage. And last but not 
+      least it compensates a somehow ugly effect of Java showing font sizes 
+      smaller than any web browser.
+    </p>
+    <p>
+      Read all about above topics in more detail in the following chapters
+    </p>
+    <ul>
+      <li>
+        <a href="../topic16/topic152/topic153.htm">Links in HTML</a>
+      </li>
+      <li>
+        <a href="../topic16/topic152/topic154.htm">New parts in this stage</a>
+      </li>
+      <li>
+        <a href="../topic16/topic152/topic155.htm">How to apply links</a>
+      </li>
+      <li>
+        <a href="../topic16/topic152/topic156.htm">Creating a GUI to define 
+        links</a>
+      </li>
+      <li>
+        <a href="../topic16/topic152/topic157.htm">Creating a GUI to define 
+        link anchors</a>
+      </li>
+      <li>
+        <a href="../topic16/topic152/topic158.htm">Using LinkDialog and 
+        AnchorDialog</a>
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic152/topic153.htm b/src/com/lightdev/app/shtm/help/topic16/topic152/topic153.htm
new file mode 100644
index 0000000..27f7bc7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic152/topic153.htm
@@ -0,0 +1,117 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Links in HTML
+    </p>
+    <p>
+      A link in HMTL is a reference to another location a user can jump to. 
+      The common syntax for a HTML link is
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace"><a href="URI">link 
+      text</a></font>
+    </p>
+    <p class="heading2">
+      Link types
+    </p>
+    <p>
+      Link types are reflected by the type of uniform resource identifier 
+      (URI) of attribute <font face="'Courier New',Monospaced,Monospace">href</font>
+ . The following formats for an URI are possible
+    </p>
+    <ol>
+      <li>
+        anchor in the same document (e.g. <font face="'Courier New',Monospaced,Monospace">
+#anchorname</font>)
+      </li>
+      <li>
+        other document (e.g. <font face="'Courier New',Monospaced,Monospace">
+        myDoc.htm</font>)
+      </li>
+      <li>
+        other document in other directory (e.g. <font face="'Courier New',Monospaced,Monospace">
+../directory/myDoc.htm</font>)
+      </li>
+      <li>
+        anchor in other document (e.g. <font face="'Courier New',Monospaced,Monospace">
+myDoc.htm#anchorname</font>)
+      </li>
+      <li>
+        anchor in other document in other directoy (e.g. <font face="'Courier New',Monospaced,Monospace">
+../directory/myDoc.htm#anchorname</font>)
+      </li>
+      <li>
+        WWW address (<font face="'Courier New',Monospaced,Monospace">http://...</font>
+ )
+      </li>
+      <li>
+        address to local document (<font face="'Courier New',Monospaced,Monospace">
+file://...</font>)
+      </li>
+      <li>
+        Gopher address (<font face="'Courier New',Monospaced,Monospace"> 
+        gopher://...</font>)
+      </li>
+      <li>
+        FTP address (<font face="'Courier New',Monospaced,Monospace">ftp://...</font>
+ )
+      </li>
+      <li>
+        Telnet address (<font face="'Courier New',Monospaced,Monospace"> 
+        telnet://...</font>)
+      </li>
+      <li>
+        Newsgroup address (<font face="'Courier New',Monospaced,Monospace"> 
+        news:...</font>)
+      </li>
+      <li>
+        E-Mail address (<font face="'Courier New',Monospaced,Monospace"> 
+        mailto:name at domain.xy</font>)
+      </li>
+    </ol>
+    <p>
+      Link types 1 to 5 above can be summarized as links with relative 
+      addresses (i.e. relative to the location the document containing the 
+      link is stored), all others work with absolute link addresses. Instead 
+      of a link text an image can be specified as well, for instance
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace"><a href="home.htm"> </font>
+
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:40pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace"><img 
+      src="anImageFile.jpg" width="160" height="34" border="0"> </font>
+
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace"></a></font>
+    </p>
+    <p>
+      SimplyHTML models all types of links and supports links of type 1 to 7 
+      above.
+    </p>
+    <p class="heading2">
+      Link anchors
+    </p>
+    <p>
+      As shown in link types 1, 4 and 5 above, links not only refer to other 
+      files, they can point to specific locations inside a given file too. To 
+      enable a link to point to a certain location inside a file, so called <i>
+      link anchors</i> have to be defined as target locations in respective 
+      target files. Link anchors are defined by inserting HTML code such as
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <a name="anchorname">link anchor text</a>
+    </p>
+    <p>
+      Link anchors can be defined with or without an anchor text, however 
+      SimplyHTML only allows to create link anchors with text.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic152/topic154.htm b/src/com/lightdev/app/shtm/help/topic16/topic152/topic154.htm
new file mode 100644
index 0000000..5097668
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic152/topic154.htm
@@ -0,0 +1,202 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      New parts in this stage
+    </p>
+    <p>
+      As with previous stages several adjustments to existing classes as well 
+      as some new classes are needed to build the new link functionality
+    </p>
+    <p>
+      
+    </p>
+    <table style=" width:80%; background-color:#ffffff;">
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            <b>Class </b>
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e3e3e3; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            <b>Purpose, Changes</b>
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            LinkDialog
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            Dialog to create and edit links
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            AnchorDialog
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            Dialog to create and edit anchor links
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            FrmMain
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new actions for link creation and formatting
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            SHTMLEditorPane
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new methods to apply and change links and anchor links
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            Util
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new methods to build relative paths and to locate link elements
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p>
+      
+    </p>
+    <p>
+      Addtional to working with links, stage 9 has some refined features for 
+      working with paragraph tags and named styles as well as for rendering 
+      HTML:
+    </p>
+    <p>
+      
+    </p>
+    <table style=" width:80%; background-color:#ffffff;">
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            <b>Class </b>
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e3e3e3; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            <b>Purpose, Changes</b>
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            SHTMLEditorKit
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            support for additional views
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            SHTMLInlineView
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new view compensating font size differences between Java and web 
+            browsers
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            SHTMLParagraphView
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new view compensating font size differences between Java and web 
+            browsers
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            TagSelector
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new component to select paragraph tag types from the tool bar
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            ParaStyleDialog
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            additional tag type selector to set named styles for tags other 
+            than paragraph
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#e2e1e1; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            SHTMLEditorPane
+          </p>
+        </td>
+        <td style=" text-align:left; width:70%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#f1f1f0; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; border-top-width:0pt; margin-top:1pt;" valign="top">
+          <p class="table">
+            new method to apply tag types to paragraph tags
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p>
+      
+    </p>
+    <p>
+      Classes <font face="'Courier New',Monospaced,Monospace">SHTMLTableView</font>
+ and <font face="'Courier New',Monospaced,Monospace">SHTMLBlockView</font> 
+      have been changed and moved to package com.lightdev.app.shtm. Class <font face="'Courier New',Monospaced,Monospace">
+LengthValue</font> has been abandoned and removed from the project.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic152/topic155.htm b/src/com/lightdev/app/shtm/help/topic16/topic152/topic155.htm
new file mode 100644
index 0000000..424a1e2
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic152/topic155.htm
@@ -0,0 +1,112 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      How to apply links
+    </p>
+    <p>
+      In Java links inside HTML documents are represented different to other 
+      HTML tags. As <a href="../../topic16/topic152/topic153.htm">previously 
+      described</a> a link usually is denoted by a tag such as
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace"><a href="URI">link 
+      text</a></font>
+    </p>
+    <p>
+      But instead of being a branch element of type <font face="'Courier New',Monospaced,Monospace">
+HTML.Tag.A</font> inside a <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font>, a link is represented as an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> for a given content element. To complicate things a 
+      little, images are represented as an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> for a content element too, so image links in turn are 
+      represented as two <font face="'Courier New',Monospaced,Monospace">
+      AttributeSets</font> each nested inside the <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> of a given content element.
+    </p>
+    <p class="heading2">
+      Applying links
+    </p>
+    <p>
+      To apply a text or image link, class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> has two new methods both called <font face="'Courier New',Monospaced,Monospace">
+setLink</font>. The two methods only differ in the parameters they expect. One 
+      of the methods just wraps the other one into a more convenient call with 
+      fewer parameters for text links. Method <font face="'Courier New',Monospaced,Monospace">
+setLink</font> determines, whether or not the selection currently is inside a 
+      link with the help of method <font face="'Courier New',Monospaced,Monospace">
+findLinkElementUp</font> of class <font face="'Courier New',Monospaced,Monospace">
+Util</font> (see below).
+    </p>
+    <p class="heading3">
+      Text links and image links
+    </p>
+    <p>
+      If inside a link, this link is replaced by the new link. If the 
+      selection is not inside a link, the new link just is created at the 
+      current caret position. Possibly selected text is replaced by the text 
+      of the new link in this case.
+    </p>
+    <p>
+      After it has determined, whether the selection is inside a link, method <font face="'Courier New',Monospaced,Monospace">
+setLink</font> splits into calls to methods <font face="'Courier New',Monospaced,Monospace">
+setTextLink</font> and <font face="'Courier New',Monospaced,Monospace">
+      setImageLink</font> respectivley, whatever applies from the parameters 
+      received from the calling method. If no image file is passed (<font face="'Courier New',Monospaced,Monospace">
+linkImage</font> is <font face="'Courier New',Monospaced,Monospace">null</font>
+       ), a text link is assumed and vice versa (<font face="'Courier New',Monospaced,Monospace">
+linkText</font> is <font face="'Courier New',Monospaced,Monospace">null</font> 
+      instead).
+    </p>
+    <p class="heading2">
+      Method setTextLink
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">setTextLink</font>
+       takes the link reference and stores it as <font face="'Courier New',Monospaced,Monospace">
+HTML.Attribute.HREF</font> in a new <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font>. If a style name was passed, it is stored as <font face="'Courier New',Monospaced,Monospace">
+HTML.Attribute.CLASS</font> in the <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> for the link. The new link then is applied to the 
+      selection depending on what is inside the selection.
+    </p>
+    <p>
+      If the selection contains a link, this link is replaced by the new link. 
+      Otherwise, the selected text is replaced by the new link text and the 
+      link attributes are applied to this new text.
+    </p>
+    <p class="heading2">
+      Method setImageLink
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">setImageLink</font>
+ works similar to method <font face="'Courier New',Monospaced,Monospace">
+      setTextLink</font>. The only difference is that it creates an additional 
+      AttributeSet for representing the image (file, width and height). This 
+      AttributeSet is applied instead of link text to the selection replacing 
+      any existing link or other text along with the new link attributes.
+    </p>
+    <p class="heading2">
+      Method findLinkElementUp
+    </p>
+    <p>
+      To find a link element from the position of a given element upwards in 
+      the element strucutre of a document, the attribute sets of elements have 
+      to be inspected (not the element names). Method <font face="'Courier New',Monospaced,Monospace">
+findLinkElementUp</font> does this by iterating through parent elements of a 
+      given element and looking for an attribute with key <font face="'Courier New',Monospaced,Monospace">
+HTML.Tag.A</font>. If such an attribute is found, this attribute represents a 
+      nested <font face="'Courier New',Monospaced,Monospace">AttributeSet</font>
+ . Method <font face="'Courier New',Monospaced,Monospace">findLinkElementUp</font>
+ then looks for an attribute with key <font face="'Courier New',Monospaced,Monospace">
+HTML.Attribute.HREF</font> inside this nested <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font>. If <font face="'Courier New',Monospaced,Monospace">
+      HTML.Attribute.HREF</font> is found, a content element with a link 
+      attached has been found and this element is returned.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic152/topic156.htm b/src/com/lightdev/app/shtm/help/topic16/topic152/topic156.htm
new file mode 100644
index 0000000..4c4aaef
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic152/topic156.htm
@@ -0,0 +1,90 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a GUI to define links
+    </p>
+    <p>
+      With methods to apply links as explained in <a href="../../topic16/topic152/topic155.htm">
+previous chapter</a>, a new dialog is required to allow for convenient link 
+      creation and manipulation. New class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic15/topic163/topic164.htm">
+LinkDialog</a></font> is the central place to allow for link entries of all 
+      kind.
+    </p>
+    <p class="heading2">
+      Class LinkDialog
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">LinkDialog</font> 
+      has a collection of components for all relevant <a href="../../topic16/topic152/topic153.htm">
+link attributes</a>. It can be used to set a new link or to view and 
+      manipulate an exisiting link.
+    </p>
+    <p>
+      As several dialogs of application SimplyHTML have been explained in 
+      earlier stages already, we only look at some additional 'specialties' of 
+      class <font face="'Courier New',Monospaced,Monospace">LinkDialog</font> 
+      here. <font face="'Courier New',Monospaced,Monospace">LinkDialog</font> 
+      establishes a central <font face="'Courier New',Monospaced,Monospace">
+      ActionListener</font> to handle changes to any of its components. If the 
+      link type combo box changes for instance, the buttons to select a local 
+      file or <a href="../../topic16/topic152/topic157.htm">link anchor</a> 
+      are enabled or disabled accordingly.
+    </p>
+    <p class="heading3">
+      Switching of relative and absolute paths
+    </p>
+    <p>
+      If the link type is set to 'relative' or to 'local', the link address is 
+      switched between absolute (<font face="'Courier New',Monospaced,Monospace">
+file:/C:/Data/aFile.htm</font>) or relative (<font face="'Courier New',Monospaced,Monospace">
+../../aDir/aFile.htm</font>) notation with the help of methods <font face="'Courier New',Monospaced,Monospace">
+resolveRelativePath</font> and <font face="'Courier New',Monospaced,Monospace">
+      getRelativePath</font> of class <font face="'Courier New',Monospaced,Monospace">
+Util</font>.
+    </p>
+    <p class="heading3">
+      Selection of local files and link anchors
+    </p>
+    <p>
+      A link type of '<font face="'Courier New',Monospaced,Monospace">local</font>
+ ' allows to use a <font face="'Courier New',Monospaced,Monospace">JFileChooser</font>
+ dialog to browse for a local file. Link types '<font face="'Courier New',Monospaced,Monospace">
+local</font>' and '<font face="'Courier New',Monospaced,Monospace">relative</font>
+ ' as well allow to define a <a href="../../topic16/topic152/topic157.htm">
+      link anchor</a> with respective browse button.
+    </p>
+    <p>
+      Link address and link anchor can be typed directly into respective text 
+      fields too.
+    </p>
+    <p class="heading3">
+      Image selection
+    </p>
+    <p>
+      By selecting 'show link as image', the dialog switches to display an 
+      image panel with a browse button to set an image from the <a href="../../topic16/topic128.htm">
+repository</a>. In the <font face="'Courier New',Monospaced,Monospace">
+      LinkDialog</font> any selected image is only shown with the width and 
+      height selected in the <font face="'Courier New',Monospaced,Monospace">
+      ImageDialog</font>. These settings can only be changed by using the <font face="'Courier New',Monospaced,Monospace">
+ImageDialog</font> through respective browse button.
+    </p>
+    <p class="heading2">
+      Returning link settings
+    </p>
+    <p>
+      Once all link attributes are set with class <font face="'Courier New',Monospaced,Monospace">
+LinkDialog</font>, methods <font face="'Courier New',Monospaced,Monospace">
+      getLinkText</font>, <font face="'Courier New',Monospaced,Monospace">
+      getHref</font>, <font face="'Courier New',Monospaced,Monospace">
+      getStyleName</font>, <font face="'Courier New',Monospaced,Monospace">
+      getLinkImage</font> and <font face="'Courier New',Monospaced,Monospace">
+      getLinkImageSize</font> can be used to find out the user settings.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic152/topic157.htm b/src/com/lightdev/app/shtm/help/topic16/topic152/topic157.htm
new file mode 100644
index 0000000..1d17a9d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic152/topic157.htm
@@ -0,0 +1,90 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a GUI to define link anchors
+    </p>
+    <p>
+      <a href="../../topic16/topic152/topic153.htm">Link anchors</a> denote 
+      certain positions inside a document making it possible to link to that 
+      particular position directly. Link anchors are identified by a link 
+      anchor name which is internally stored in the document at the position 
+      it denotes. Link anchors typically are not visible in the document, they 
+      are present only in the HTML code making up such document.
+    </p>
+    <p>
+      to enable a user to create and manipulate link anchors requires some 
+      extra work because SimplyHTML hides HTML code with the intention to let 
+      an author concentrate on content rather than HTML coding.
+    </p>
+    <p class="heading2">
+      Class AnchorDialog
+    </p>
+    <p>
+      With class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic15/topic163/topic165.htm">
+AnchorDialog</a></font> a GUI is built for making link anchors of a document 
+      visible and for creating or deleting link anchors. As several dialogs of 
+      application SimplyHTML have been explained in earlier stages already, we 
+      only look at some additional 'specialties' of class <font face="'Courier New',Monospaced,Monospace">
+AnchorDialog</font> here.
+    </p>
+    <p class="heading3">
+      Document as object or file
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">AnchorDialog</font> can 
+      be constructed either with a <font face="'Courier New',Monospaced,Monospace">
+Document</font> object or with a URL leading to a document. When constructed 
+      with a URL, <font face="'Courier New',Monospaced,Monospace">AnchorDialog</font>
+ loads the <font face="'Courier New',Monospaced,Monospace">Document</font> 
+      found at that location. When link anchors are added to or removed from a 
+      document loaded from a URL, the changes are saved to the document before <font face="'Courier New',Monospaced,Monospace">
+AnchorDialog</font> is destroyed.
+    </p>
+    <p class="heading3">
+      Method getAnchors
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">AnchorDialog</font>
+       displays a list of link anchors existing in the document associated to 
+      the dialog with the help of method <font face="'Courier New',Monospaced,Monospace">
+getAnchors</font>. Method <font face="'Courier New',Monospaced,Monospace">
+      getAnchors</font> iterates through all elements of the document and 
+      looks for <font face="'Courier New',Monospaced,Monospace">HTML.Tag.A</font>
+ in the attribute set of each element. If such attribute is found, <font face="'Courier New',Monospaced,Monospace">
+getAnchors</font> looks for <font face="'Courier New',Monospaced,Monospace">
+      HTML.Attribute.NAME</font>. Any element having <font face="'Courier New',Monospaced,Monospace">
+HTML.Attribute.NAME</font> inside <font face="'Courier New',Monospaced,Monospace">
+HTML.Tag.A</font> is listed as a link anchor.
+    </p>
+    <p>
+      Whenever method <font face="'Courier New',Monospaced,Monospace">
+      getAnchors</font> is called to find all anchors in a document, a <font face="'Courier New',Monospaced,Monospace">
+Hashtable</font> <font face="'Courier New',Monospaced,Monospace">anchorTable</font>
+ is filled with the anchors found. <font face="'Courier New',Monospaced,Monospace">
+Hashtable</font> <font face="'Courier New',Monospaced,Monospace">anchorTable</font>
+ references elements with anchor names. The <font face="'Courier New',Monospaced,Monospace">
+Hashtable</font> is used to fill the list of available anchors too.
+    </p>
+    <p class="heading3">
+      Making anchors visible
+    </p>
+    <p>
+      As mentioned previously, anchors are only visible in the HTML code of a 
+      document. To make a link anchor visible a <font face="'Courier New',Monospaced,Monospace">
+Highlighter</font> is used in class <font face="'Courier New',Monospaced,Monospace">
+AnchorDialog</font>. A <font face="'Courier New',Monospaced,Monospace">
+      ListSelectionListener</font> is implemented by class <font face="'Courier New',Monospaced,Monospace">
+AnchorDialog</font> and registered with the list of anchors. Whenever an item 
+      is selected in the list, the element the anchor name refers to is taken 
+      from the <font face="'Courier New',Monospaced,Monospace">anchorTable</font>
+ <font face="'Courier New',Monospaced,Monospace">Hashtable</font>. The element 
+      is used to determine the anchor position in the document and the 
+      position is passed to the Highlighter to be shown.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic152/topic158.htm b/src/com/lightdev/app/shtm/help/topic16/topic152/topic158.htm
new file mode 100644
index 0000000..3d8167f
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic152/topic158.htm
@@ -0,0 +1,87 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using LinkDialog and AnchorDialog
+    </p>
+    <p>
+      The two dialogs making up the new link functionality in this stage are 
+      made available through new actions in FrmMain.
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">InsertLinkAction</font>
+         - action to create a new link
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">EditLinkAction</font> 
+        - action to edit an exisiting link
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">EditAnchorsAction</font>
+ - action to create or remove anchor links
+      </li>
+    </ul>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">InsertLinkAction</font> 
+      and <font face="'Courier New',Monospaced,Monospace">EditLinkAction</font>
+       both create an instance of class <font face="'Courier New',Monospaced,Monospace">
+LinkDialog</font> to let the user create or work on a link. When the user has 
+      not cancelled upon return of the dialog, method <font face="'Courier New',Monospaced,Monospace">
+setLink</font> of class <font face="'Courier New',Monospaced,Monospace">
+      SHTMLEditorPane</font> is called to apply the link settings from the <font face="'Courier New',Monospaced,Monospace">
+LinkDialog</font> object.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">EditAnchorsAction</font> 
+      is used similar to the above, the only difference is usage of method <font face="'Courier New',Monospaced,Monospace">
+insertAnchor</font> of class <font face="'Courier New',Monospaced,Monospace">
+      SHTMLEditorPane</font> instead.
+    </p>
+    <p class="heading2">
+      Usage of AnchorDialog through LinkDialog
+    </p>
+    <p>
+      Additional to using <font face="'Courier New',Monospaced,Monospace">
+      AnchorDialog</font> directly on a document currently edited, the dialog 
+      can be used from out of class <font face="'Courier New',Monospaced,Monospace">
+LinkDialog</font>. The idea is that either
+    </p>
+    <ol>
+      <li>
+        an anchor link is applied to a document in one step and a link is 
+        created to reference this anchor link in a second step later or
+      </li>
+      <li>
+        an anchor link is created in the course of creating a link both in one 
+        step.
+      </li>
+    </ol>
+    <p>
+      To create a link to a newly created anchor link in one step, as in case 
+      2. above, the anchor link needs to be created directly out of class <font face="'Courier New',Monospaced,Monospace">
+LinkDialog</font>. To do so, <font face="'Courier New',Monospaced,Monospace">
+      LinkDialog</font> has a browse button next to the text field for typing 
+      in a link anchor name. When the browse button is pressed class <font face="'Courier New',Monospaced,Monospace">
+LinkDialog</font> creates an instance of <font face="'Courier New',Monospaced,Monospace">
+AnchorDialog</font> passing the URL currently entered as the link address.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">AnchorDialog</font> 
+      opens the document referenced by the URL received from <font face="'Courier New',Monospaced,Monospace">
+LinkDialog</font> and shows existing anchors of this document. The user now 
+      can choose an existing anchor link or create a new one which then is 
+      chosen.
+    </p>
+    <p>
+      Once a link anchor is selected, its name is taken back to the calling <font face="'Courier New',Monospaced,Monospace">
+LinkDialog</font> and the anchor name is included with the new link currently 
+      worked on in the <font face="'Courier New',Monospaced,Monospace">
+      LinkDialog</font> object.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic168.htm b/src/com/lightdev/app/shtm/help/topic16/topic168.htm
new file mode 100644
index 0000000..4eb3492
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic168.htm
@@ -0,0 +1,42 @@
+<html>
+  <head>
+    <link href="../style.css" type="text/css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 10: HTML code editor and syntax highlighting
+    </p>
+    <p>
+      SimplyHTML focuses on creation and manipulation of text documents. The 
+      fact that the documents are stored as HTML files along with cascading 
+      style sheets (CSS) was hidden from the user interface of SimplyHTML 
+      intentionally. The autor should not be forced to know or work with HTML 
+      code to write a text document.
+    </p>
+    <p>
+      On the other hand, for an experienced user being familiar with HTML it 
+      sometimes is quicker to manipulate a certain portion of HTML directly 
+      instead of having to wade through GUI elements. For this reason this 
+      stage of SimplyHTML implements a way to work on the HTML representation 
+      of any given text document.
+    </p>
+    <p>
+      The following parts are covered in this stage:
+    </p>
+    <ul>
+      <li>
+        <a href="../topic16/topic168/topic169.htm">HTML code editor: a simple 
+        approach</a>
+      </li>
+      <li>
+        <a href="../topic16/topic168/topic170.htm">how to add syntax 
+        highlighting</a>
+      </li>
+      <li>
+        <a href="../topic16/topic168/topic171.htm">how to integrate the new 
+        component</a>
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic168/topic169.htm b/src/com/lightdev/app/shtm/help/topic16/topic168/topic169.htm
new file mode 100644
index 0000000..4517ed9
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic168/topic169.htm
@@ -0,0 +1,58 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      HTML code editor: a simple approach
+    </p>
+    <p>
+      Although SimplyHTML is mainly meant for text processing, sometimes it is 
+      useful to do a change directly in the HTML representation of a document. 
+      For this purpose a component to display and edit HTML code is required. 
+      The editor shall not replace a powerful web page HTML editor, it only 
+      adds basic HTML manipulation functions.
+    </p>
+    <p>
+      To implement such an editor an ordinary <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font> is used. Setting the content type to "text/plain" and 
+      adding the HTML code of a given document as content for the JEditorPane 
+      leads to have a fully working editor.
+    </p>
+    <p class="heading2">
+      Obtaining the HTML code for a given text document
+    </p>
+    <p>
+      To get the HTML code for a given document which can be shown in above 
+      mentioned editor pane, class <font face="'Courier New',Monospaced,Monospace">
+HTMLWriter</font> (or <font face="'Courier New',Monospaced,Monospace">
+      SHTMLWriter</font>, depending on the user selection) is used. The writer 
+      creates HTML code for any given instance of class <font face="'Courier New',Monospaced,Monospace">
+Document</font> and its subclasses. By using method <font face="'Courier New',Monospaced,Monospace">
+getEditorKit</font> of an <font face="'Courier New',Monospaced,Monospace">
+      EditorPane</font> the <font face="'Courier New',Monospaced,Monospace">
+      EditorKit</font> for a displayed document is taken. Method write of 
+      class <font face="'Courier New',Monospaced,Monospace">EditorKit</font> 
+      uses <font face="'Courier New',Monospaced,Monospace">HTMLWriter</font> 
+      implicitly.
+    </p>
+    <p>
+      See new method <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic168/topic171.htm">
+setHTMLView</a></font> of class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> about how this approach is used.
+    </p>
+    <p class="heading2">
+      Simple but not enough
+    </p>
+    <p>
+      While the above would already be enough to edit HTML for any given text 
+      document it is comparably hard to work with HTML in a plain text 
+      display. In plain text the structural elements of HTML are not visually 
+      separated from content elements. Thus, the <a href="../../topic16/topic168/topic170.htm">
+next chapter</a> explains how syntax highlighting is added to our new simple 
+      HTML editor for improved legibility.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic168/topic170.htm b/src/com/lightdev/app/shtm/help/topic16/topic168/topic170.htm
new file mode 100644
index 0000000..b13e6f4
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic168/topic170.htm
@@ -0,0 +1,159 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Adding syntax highlighting
+    </p>
+    <p>
+      The <a href="../../topic16/topic168/topic169.htm">previous chapter</a> 
+      describes how a simple HTML code editor can be built. But with a plain 
+      text view structure and content of a HTML file is not visually 
+      separated. To improve legibility, syntax highlighting can be used: By 
+      displaying certain parts such as tags or attributes in a color or style 
+      different to the one used for content the reader can easily find certain 
+      parts of the document.
+    </p>
+    <p>
+      There are different approaches possible to implement syntax 
+      highlighting. For SimplyHTML regular expressions are used for their 
+      simple way of defining patterns in a single expression.
+    </p>
+    <p class="heading2">
+      Class SyntaxPane
+    </p>
+    <p class="standard">
+      A new class <font face="'Courier New',Monospaced,Monospace">SyntaxPane</font>
+ is created as a subclass of <font face="'Courier New',Monospaced,Monospace">
+      JEditorPane</font>. In the constructor of <font face="'Courier New',Monospaced,Monospace">
+SyntaxPane</font> method <font face="'Courier New',Monospaced,Monospace">
+      setupPatterns</font> is called, which defines the patterns for HTML 
+      tags, attributes and attribute content. Method <font face="'Courier New',Monospaced,Monospace">
+setMarks</font> (see below) is used to apply syntax highlighting to a given 
+      part of the document in the <font face="'Courier New',Monospaced,Monospace">
+SyntaxPane</font>.
+    </p>
+    <p>
+      The <font face="'Courier New',Monospaced,Monospace">SyntaxPane</font> 
+      registers itself as a <font face="'Courier New',Monospaced,Monospace">
+      CaretListener</font> and uses method <font face="'Courier New',Monospaced,Monospace">
+caretUpdate</font> to keep the syntax highlighting up to date for any changed 
+      text. When a document is shown initially, <font face="'Courier New',Monospaced,Monospace">
+setMarks</font> is called for the entire content (making it a lengthier 
+      process for bigger documents to display the highlighting initially). 
+      During changes only the highlighting of the current line is updated so 
+      that typing text is not slowed down too much.
+    </p>
+    <p>
+      A tradeoff with above approach is that multiline formats such as 
+      multiline comments are not handled with it.
+    </p>
+    <p class="heading3">
+      Method setupPatterns
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">setupPatterns</font>
+ uses regular expressions to define a pattern for each element to be shown 
+      different from normal content. A HTML tag for instance is enclosed in < 
+      and > and can have letters and numbers with or without a slash inside 
+      those markers. An attribute ends with =, etc. For each <font face="'Courier New',Monospaced,Monospace">
+Pattern</font> an <font face="'Courier New',Monospaced,Monospace">AttributeSet</font>
+ is created having the style to apply for that particular <font face="'Courier New',Monospaced,Monospace">
+Pattern</font>.
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">setupPatterns</font>
+ a <font face="'Courier New',Monospaced,Monospace">Vector</font> is used to 
+      hold pairs of one <font face="'Courier New',Monospaced,Monospace">Pattern</font>
+ and one <font face="'Courier New',Monospaced,Monospace">AttributeSet</font> 
+      wrapped into inner class <font face="'Courier New',Monospaced,Monospace">
+      RegExStyle</font>.
+    </p>
+    <p class="heading3">
+      Inner class RegExStyle
+    </p>
+    <p>
+      Inner class <font face="'Courier New',Monospaced,Monospace">RegExStyle</font>
+ is used as a convenience class to bundle a <font face="'Courier New',Monospaced,Monospace">
+Pattern</font> with a set of attributes. It simply has two class fields for 
+      the <font face="'Courier New',Monospaced,Monospace">Pattern</font> and 
+      the <font face="'Courier New',Monospaced,Monospace">AttributeSet</font> 
+      and respective getters and setters. All defined <font face="'Courier New',Monospaced,Monospace">
+RegExStyles</font> are stored in <font face="'Courier New',Monospaced,Monospace">
+Vector</font> <font face="'Courier New',Monospaced,Monospace">patterns</font> 
+      of class <font face="'Courier New',Monospaced,Monospace">SyntaxPane</font>
+ .
+    </p>
+    <p class="heading3">
+      Method setMarks
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">setMarks</font> 
+      is the public member of <font face="'Courier New',Monospaced,Monospace">
+      SyntaxPane</font> which is used to apply syntax highlighting to a given 
+      portion of the current document. Method <font face="'Courier New',Monospaced,Monospace">
+setMarks</font> creates an instance of inner class <font face="'Courier New',Monospaced,Monospace">
+StyleUpdater</font> (see below) and calls <font face="'Courier New',Monospaced,Monospace">
+invokeLater</font> of class <font face="'Courier New',Monospaced,Monospace">
+      SwingUtilities</font> to have styles updated without conflicts in the 
+      event dispatch thread.
+    </p>
+    <p class="heading3">
+      Inner class StyleUpdater
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">StyleUpdater</font>
+       implements the <font face="'Courier New',Monospaced,Monospace">Runnable</font>
+ interface by wrapping its functionality in a public method named <font face="'Courier New',Monospaced,Monospace">
+run</font>. Its main task is to apply styles associated with regular 
+      expression patterns to a given portion of the document which is 
+      currently edited.
+    </p>
+    <p>
+      This is done by iterating through <font face="'Courier New',Monospaced,Monospace">
+Vector</font> <font face="'Courier New',Monospaced,Monospace">patterns</font> 
+      of class <font face="'Courier New',Monospaced,Monospace">SyntaxPane</font>
+ . For each <font face="'Courier New',Monospaced,Monospace">Pattern</font> 
+      found a <font face="'Courier New',Monospaced,Monospace">Matcher</font> 
+      is created. To all instances of the the <font face="'Courier New',Monospaced,Monospace">
+Pattern</font> found by the <font face="'Courier New',Monospaced,Monospace">
+      Matcher</font> the style associated to the <font face="'Courier New',Monospaced,Monospace">
+Pattern</font> is applied.
+    </p>
+    <p class="heading3">
+      Method caretUpdate
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">caretUpdate</font>
+       finds out the start and end position of the line the caret currently is 
+      in and calls method <font face="'Courier New',Monospaced,Monospace">
+      setMarks</font> for this portion of text each time the caret position 
+      changes.
+    </p>
+    <p class="heading2">
+      Recommended readings
+    </p>
+    <p>
+      'Regular Expressions and the JavaTM Programming Language' at
+    </p>
+    <p>
+      <font color="#3333ff">
+      http://developer.java.sun.com/developer/technicalArticles/releases/1.4regex/ 
+</font>
+    </p>
+    <p>
+      and
+    </p>
+    <p>
+      presentation slides 'Rich Clients for Web Services' from JavaOne 2002 at
+    </p>
+    <p>
+      <font color="#3333ff">
+      http://servlet.java.sun.com/javaone/resources/content/sf2002/conf/sessions/pdfs/2274.pdf 
+</font>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic168/topic171.htm b/src/com/lightdev/app/shtm/help/topic16/topic168/topic171.htm
new file mode 100644
index 0000000..9201b8a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic168/topic171.htm
@@ -0,0 +1,139 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Integrating the new component
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font>
+       is used as the GUI representation of a document in application 
+      SimplyHTML. To let the user switch between layout view and HTML view in 
+      stage 10 class <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font> has some additional parts:
+    </p>
+    <ul>
+      <li>
+        an editor pane to show and edit HTML code additional to the one used 
+        to show and edit the text and layout
+      </li>
+      <li>
+        a <font face="'Courier New',Monospaced,Monospace">JTabbedPane</font> 
+        to hold two editor panes and to switch between the two
+      </li>
+      <li>
+        a method to track the state of the new <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> and to react on state changes
+      </li>
+      <li>
+        methods that handle transfer of content between the two editor panes
+      </li>
+    </ul>
+    <p class="heading2">
+      Initializing the two views
+    </p>
+    <p>
+      The <font face="'Courier New',Monospaced,Monospace">JTabbedPane</font> 
+      is initialized in the constructor of <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> and a reference is kept in new class field <font face="'Courier New',Monospaced,Monospace">
+tpView</font>. The <font face="'Courier New',Monospaced,Monospace">JTabbedPane</font>
+ is added to the center area of the content pane of class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font>.
+    </p>
+    <p class="heading3">
+      Adding two editor panes
+    </p>
+    <p>
+      A new class field <font face="'Courier New',Monospaced,Monospace">
+      htmlEditor</font> of class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> references the new <font face="'Courier New',Monospaced,Monospace">
+SyntaxPane</font>. The field is initialized in the constructor of class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> with a new instance of class <font face="'Courier New',Monospaced,Monospace">
+SyntaxPane</font>.
+    </p>
+    <p>
+      The <font face="'Courier New',Monospaced,Monospace">SHTMLEditorPane</font>
+ in class field <font face="'Courier New',Monospaced,Monospace">editor</font> 
+      and the <font face="'Courier New',Monospaced,Monospace">SyntaxPane</font>
+       in class field <font face="'Courier New',Monospaced,Monospace">
+      htmlEditor</font> are added to the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> in the constructor of class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font>. Now the two resulting tabs in the <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> can be used to toggle display between layout view and HTML 
+      view.
+    </p>
+    <p class="heading3">
+      Tracking tab clicks
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font>
+       implements interface <font face="'Courier New',Monospaced,Monospace">
+      ChangeListener</font> by adding new method <font face="'Courier New',Monospaced,Monospace">
+stateChanged</font>. Class <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font> is added to the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> as a <font face="'Courier New',Monospaced,Monospace">
+      ChangeListener</font>. Method <font face="'Courier New',Monospaced,Monospace">
+stateChanged</font> is called by the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> whenever its state changes (another tab has been clicked, 
+      that is).
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">stateChanged</font>
+ of class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      checks if the state of the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> of class <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font> has changed. Every time the state of the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> chages, the view associated to the clicked tab is opened 
+      through methods <font face="'Courier New',Monospaced,Monospace">
+      setLayoutView</font> and <font face="'Courier New',Monospaced,Monospace">
+      setHTMLView</font>.
+    </p>
+    <p class="heading2">
+      Method setLayoutView
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">setLayoutView</font>
+ the current content of the <font face="'Courier New',Monospaced,Monospace">
+      SyntaxPane</font> is taken (the HTML code) and transferred over to the <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font>. Because method <font face="'Courier New',Monospaced,Monospace">
+setLayoutView</font> is used when the HTML display is hidden and the layout 
+      display is shown, it removes the instance of <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> as a <font face="'Courier New',Monospaced,Monospace">
+      DocumentListener</font> from the <font face="'Courier New',Monospaced,Monospace">
+SyntaxPane</font> and adds it to the <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> so that changes are tracked by <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> accordingly.
+    </p>
+    <p class="heading2">
+      Method setHTMLView
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">setHTMLView</font>
+       works the same as <font face="'Courier New',Monospaced,Monospace">
+      setLayoutView</font> in the way that it removes and adds class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> as a <font face="'Courier New',Monospaced,Monospace">
+      DocumentListener</font> accordingly. It takes contents of <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> and adds them to the <font face="'Courier New',Monospaced,Monospace">
+SyntaxPane</font> too.
+    </p>
+    <p>
+      To see the HTML code instead of the textual representation of the 
+      document however, method <font face="'Courier New',Monospaced,Monospace">
+      setHTMLView</font> transforms the document content, before storing the 
+      resulting HTML code in the <font face="'Courier New',Monospaced,Monospace">
+SyntaxPane</font>. It uses the <font face="'Courier New',Monospaced,Monospace">
+      HTMLWriter</font> or <font face="'Courier New',Monospaced,Monospace">
+      SHTMLWriter</font> of the editor kit of class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> to generate HTML code for the particular document. This 
+      HTML code then is set to be the initial content of the <font face="'Courier New',Monospaced,Monospace">
+SyntaxPane</font>.
+    </p>
+    <p>
+      Finally it calls method <font face="'Courier New',Monospaced,Monospace">
+      setMarks</font> to apply syntax highlighting initially.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic173.htm b/src/com/lightdev/app/shtm/help/topic16/topic173.htm
new file mode 100644
index 0000000..aca4b61
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic173.htm
@@ -0,0 +1,45 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+<title>Stage 11: Find and replace</title>  </head>
+  <body>
+    <p class="heading1">
+      Stage 11: Find and replace
+    </p>
+    <p>
+      Java[tm] technology already offers generic functionality to find 
+      portions of text within a given string. This stage of SimplyHTML uses 
+      such functions to build a user interface suitable for most find and 
+      replace operations. In addition the new find and replace logic 
+      implements a way of replacing text over an arbitrary number of separate 
+      documents.
+    </p>
+    <p>
+      This chapter does not go into every detail of how to build respective 
+      user interface. It concentrates on aspects in conjunction with find and 
+      replace as shown in the following topics
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <a href="../topic16/topic173/topic174.htm">Find and replace basics</a>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <a href="../topic16/topic173/topic179.htm">Find and replace user 
+      interface</a>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <a href="../topic16/topic173/topic175.htm">Find logic</a>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <a href="../topic16/topic173/topic178.htm">Replace logic</a>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <a href="../topic16/topic173/topic176.htm">Supporting find and replace 
+      over multiple documents</a>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <a href="../topic16/topic173/topic180.htm">Using FindReplaceDialog in 
+      SimplyHTML</a>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic173/topic174.htm b/src/com/lightdev/app/shtm/help/topic16/topic173/topic174.htm
new file mode 100644
index 0000000..67e90db
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic173/topic174.htm
@@ -0,0 +1,59 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+<title>Find and replace basics</title>  </head>
+  <body>
+    <p class="heading1">
+      Find and replace basics
+    </p>
+    <p class="heading2">
+      Search direction and start position
+    </p>
+    <p>
+      The actual finding of a given text phrase is achieved with usage of 
+      methods <font face="'Courier New',Monospaced,Monospace">indexOf</font> 
+      and <font face="'Courier New',Monospaced,Monospace">lastIndexOf</font> 
+      of class <font face="'Courier New',Monospaced,Monospace">String</font>. 
+      Both methods return the position a given text phrase is found at inside 
+      another string. <font face="'Courier New',Monospaced,Monospace">indexOf</font>
+ and <font face="'Courier New',Monospaced,Monospace">lastIndexOf</font> accept 
+      an optional position to start the search from so that the variations of 
+      these methods already can be taken to implement searching from start or 
+      from end of a document in either upward or downward direction.
+    </p>
+    <p class="heading2">
+      Whole word search
+    </p>
+    <p>
+      Methods <font face="'Courier New',Monospaced,Monospace">indexOf</font> 
+      and <font face="'Courier New',Monospaced,Monospace">lastIndexOf</font> 
+      find any occurrence of a given search phrase as either part of a word or 
+      whole word. To restrict matches to whole words a character array of word 
+      separators <font face="'Courier New',Monospaced,Monospace">
+      WORD_SEPARATORS</font> is used. Method <font face="'Courier New',Monospaced,Monospace">
+isSeparator</font> is used in method <font face="'Courier New',Monospaced,Monospace">
+doFind</font> of class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic173/topic179.htm">
+FindReplaceDialog</a></font> to determine whether or not a found occurrence is 
+      a full word.
+    </p>
+    <p class="heading2">
+      Case sensitive search
+    </p>
+    <p>
+      Methods <font face="'Courier New',Monospaced,Monospace">indexOf</font> 
+      and <font face="'Courier New',Monospaced,Monospace">lastIndexOf</font> 
+      are case sensitive. They return a found occurence only when 
+      capitalization of letters matches the given search phrase. To do a case 
+      insensitive search method <font face="'Courier New',Monospaced,Monospace">
+toLowerCase</font> of class <font face="'Courier New',Monospaced,Monospace">
+      String</font> is applied to both the search phrase and the text to 
+      search in before a find operation is initiated.
+    </p>
+    <p>
+      Read on in the <a href="../../topic16/topic173/topic179.htm">next topics</a>
+ to find ouit more about how these basics are applied in the user interface 
+      and logic of SimplyHTML.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic173/topic175.htm b/src/com/lightdev/app/shtm/help/topic16/topic173/topic175.htm
new file mode 100644
index 0000000..49e91c7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic173/topic175.htm
@@ -0,0 +1,109 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+<title>Find logic</title>  </head>
+  <body>
+    <p class="heading1">
+      Find logic
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      In a design that separates functionality from user interface another 
+      class would have been needed for the logic such as <font face="'Courier New',Monospaced,Monospace">
+FindReplaceLogic</font> for instance. Instead the following methods of <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font> have the main logic
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      
+    </p>
+    <table style=" background-color:#ffffff; width:80%;">
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#e7e4e4; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-top:2pt; text-align:left; color:#000000; background-color:#e7e4e4; text-decoration:none; font-size:12pt; font-style:normal; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font size="2"><b>Method </b></font>
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#e7e4e4; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:70%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-top:2pt; text-align:left; color:#000000; background-color:#e7e4e4; text-decoration:none; font-size:12pt; font-style:normal; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font size="2"><b>Purpose</b></font>
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font face="'Courier New',Monospaced,Monospace">findNext</font>
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            find the next occurrence of a given phrase from start or end of a 
+            given document either in upwards or downwards direction.
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font face="'Courier New',Monospaced,Monospace">findWholeWords</font>
+
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            Find the next whole word occurrence of the searched phrase from a 
+            given position.
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font face="'Courier New',Monospaced,Monospace">isSeparator</font>
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            determine whether or not a character is a word separator with the 
+            help of character array <font face="'Courier New',Monospaced,Monospace">
+WORD_SEPARATORS</font>.
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      In addition methods <font face="'Courier New',Monospaced,Monospace">
+      initFind</font>, <font face="'Courier New',Monospaced,Monospace">doFind</font>
+ and <font face="'Courier New',Monospaced,Monospace">find</font> are used on 
+      top of the above methods to
+    </p>
+    <ul>
+      <li>
+        initiate a find process (<font face="'Courier New',Monospaced,Monospace">
+initFind</font>)
+      </li>
+      <li>
+        manage multi document processing, if applicable (<font face="'Courier New',Monospaced,Monospace">
+find</font>) and
+      </li>
+      <li>
+        handle results of <font face="'Courier New',Monospaced,Monospace">
+        findNext</font> (<font face="'Courier New',Monospaced,Monospace">doFind</font>
+ )
+      </li>
+    </ul>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      Above methods are called by <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font> when either the 'find next' button is pressed or when 
+      the next occurrence of a phrase to be replaced is searched during a 
+      replace operation.
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      See the <a href="../../topic16/topic173/topic178.htm">next topic</a> to 
+      find out more about how the replace logic works.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic173/topic176.htm b/src/com/lightdev/app/shtm/help/topic16/topic173/topic176.htm
new file mode 100644
index 0000000..f3d83e4
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic173/topic176.htm
@@ -0,0 +1,50 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+<title>Supporting find and replace over multiple documents</title>  </head>
+  <body>
+    <p class="heading1">
+      Supporting find and replace over multiple documents
+    </p>
+    <p>
+      With SimplyHTML more than one document can be open at the same time. The 
+      find and replace logic introduced in stage 11 offers a way to apply find 
+      and replace to all open documents optionally. The way to apply find and 
+      replace to multiple documents can be customized in addition to account 
+      for different purposes such as applying find and replace to a set of 
+      documents inside a kind of 'project' as delivered by a possible 
+      SimplyHTML plug-in.
+    </p>
+    <p class="heading2">
+      FindReplaceListener and FindReplaceEvent
+    </p>
+    <p>
+      To support find and replace over multiple documents interface <font face="'Courier New',Monospaced,Monospace">
+FindReplaceListener</font> and class <font face="'Courier New',Monospaced,Monospace">
+FindReplaceEvent</font> are used. An instance of class <font face="'Courier New',Monospaced,Monospace">
+FindReplaceListener</font> can be passed as a parameter during construction of 
+      a <font face="'Courier New',Monospaced,Monospace">FindReplaceDialog</font>
+. Passing a <font face="'Courier New',Monospaced,Monospace">FindReplaceListener</font>
+ signals <font face="'Courier New',Monospaced,Monospace">FindReplaceDialog</font>
+ that find and replace is to be performed over more than one document. <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font> fires <font face="'Courier New',Monospaced,Monospace">
+      FindReplaceEvents</font> to the given <font face="'Courier New',Monospaced,Monospace">
+FindReplaceListener</font> to signal that it is through with searching a 
+      particular document and that another document is required to continue.
+    </p>
+    <p class="heading3">
+      Feedback during a multiple document process
+    </p>
+    <p>
+      The object registered as <font face="'Courier New',Monospaced,Monospace">
+      FindReplaceListener</font> has to give feedback to <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font> during multiple document operations. Methods <font face="'Courier New',Monospaced,Monospace">
+getFirstDocument</font> and <font face="'Courier New',Monospaced,Monospace">
+      getNextDocument</font> have to call either <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog.resumeOperation</font> or <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog.terminateOperation</font> at their end, depending on whether 
+      or not there are documents left to process.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic173/topic178.htm b/src/com/lightdev/app/shtm/help/topic16/topic173/topic178.htm
new file mode 100644
index 0000000..4fd1770
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic173/topic178.htm
@@ -0,0 +1,90 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+<title>Replace logic</title>  </head>
+  <body>
+    <p class="heading1">
+      Replace logic
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      Similar to the find logic described in <a href="../../topic16/topic173/topic175.htm">
+previous topic</a> the following methods of <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font> have the main logic for replacing occurrences of a 
+      given phrase:
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      
+    </p>
+    <table style=" background-color:#ffffff; width:80%;">
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#e7e4e4; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-top:2pt; text-align:left; color:#000000; background-color:#e7e4e4; text-decoration:none; font-size:12pt; font-style:normal; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font size="2"><b>Method </b></font>
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#e7e4e4; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:70%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-top:2pt; text-align:left; color:#000000; background-color:#e7e4e4; text-decoration:none; font-size:12pt; font-style:normal; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font size="2"><b>Purpose</b></font>
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font face="'Courier New',Monospaced,Monospace">replace</font>
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            Initiate a replace operation. If no (more) hits are found, a 
+            message is displayed and the dialog is unlocked for a new search 
+            operation.
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font face="'Courier New',Monospaced,Monospace">replaceOne</font>
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            Replace the currently selected occurrence of the search phrase.
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      By pressing button <font face="'Courier New',Monospaced,Monospace">
+      jbtnReplace</font> a find operation is initiated with a call to method <font face="'Courier New',Monospaced,Monospace">
+initFind</font> and above methods are called with an initial replace option of <font face="'Courier New',Monospaced,Monospace">
+RO_YES</font>. Subsequent iterations through the replace process are driven by 
+      the user through a selection in method <font face="'Courier New',Monospaced,Monospace">
+getReplaceChoice</font> which is called each time an instance of the search 
+      phrase is found and which can be one of
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">RO_YES</font> - 
+        replace and find next
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">RO_NO</font> - do not 
+        replace and find next
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">RO_ALL</font> - 
+        replace all occurrences
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">RO_DONE</font> - exit 
+        replace process
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic173/topic179.htm b/src/com/lightdev/app/shtm/help/topic16/topic173/topic179.htm
new file mode 100644
index 0000000..caf4dea
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic173/topic179.htm
@@ -0,0 +1,113 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+<title>Find and replace user interface</title>  </head>
+  <body>
+    <p class="heading1">
+      Find and replace user interface
+    </p>
+    <p>
+      To build the find and replace user interface in SimplyHTML the following 
+      set of classes is used that already existed from another project:
+    </p>
+    <p>
+      
+    </p>
+    <table style=" background-color:#ffffff; width:80%;">
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#e7e4e4; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-top:2pt; text-align:left; color:#000000; background-color:#e7e4e4; text-decoration:none; font-size:12pt; font-style:normal; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font size="2"><b>Class </b></font>
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#e7e4e4; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:70%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-top:2pt; text-align:left; color:#000000; background-color:#e7e4e4; text-decoration:none; font-size:12pt; font-style:normal; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font size="2"><b>Purpose</b></font>
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font face="'Courier New',Monospaced,Monospace">FindReplaceDialog</font>
+
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            User interface and main functionality
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font face="'Courier New',Monospaced,Monospace">FindReplaceListener</font>
+
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            Listener to achieve search and replace over multiple documents
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            <font face="'Courier New',Monospaced,Monospace">FindReplaceEvent</font>
+
+          </p>
+        </td>
+        <td style=" margin-left:1pt; margin-top:1pt; text-align:left; padding-bottom:2pt; border-left-width:0pt; background-color:#f4f0f0; padding-top:0pt; border-right-width:0pt; border-bottom-width:0pt; padding-right:4pt; margin-right:1pt; margin-bottom:1pt; border-top-width:0pt; padding-left:4pt; width:30%;" valign="top">
+          <p style=" font-family:Arial,Sans-Serif; margin-left:1pt; margin-top:2pt; text-align:left; color:#000000; background-color:#f4f0f0; text-decoration:none; font-size:12pt; font-style:normal; margin-right:1pt; margin-bottom:2pt; font-weight:normal;" class="table">
+            Event being thrown when a document search is finalized and another 
+            document would be needed for multi document find and replace
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      Above classes are taken from package <font face="'Courier New',Monospaced,Monospace">
+de.calcom.cclib.text</font> and encapsulate the complete logic and user 
+      interface needed to implement find and replace in a typical dialog. <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font> only has been extended with internationalization 
+      supprt so that it can be used language independent inside SimplyHTML.
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      Usage of the dialog is very simple. Once added to SimplyHTML (or any 
+      other project) it is instanciated with a <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font> as a parameter. The <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font> is expected to have the document to perform search and 
+      replace upon. <font face="'Courier New',Monospaced,Monospace">
+      FindReplaceDialog</font> then does all find and replace operations 
+      including document manipulation, user messages, state handling and 
+      optional multi document processing.
+    </p>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      To control the state of the dialog <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font> uses a flag to indicate the current operation in 
+      process. It can be one of
+    </p>
+    <ul>
+      <li>
+        OP_NONE
+      </li>
+      <li>
+        OP_FIND and
+      </li>
+      <li>
+        OP_REPLACE
+      </li>
+    </ul>
+    <p style=" margin-bottom:2pt; background-color:#ffffff; margin-top:2pt; font-weight:normal; text-align:left; font-family:Arial,Sans-Serif; color:#000000; text-decoration:none; font-style:normal; font-size:12pt;">
+      See the <a href="../../topic16/topic173/topic175.htm">following topics</a>
+ to learn more about how find and replace logic is implemented in these 
+      classes.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic173/topic180.htm b/src/com/lightdev/app/shtm/help/topic16/topic173/topic180.htm
new file mode 100644
index 0000000..a94b142
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic173/topic180.htm
@@ -0,0 +1,30 @@
+<html>
+  <head>
+    <link href="../../style.css" type="text/css" rel="stylesheet">
+    
+<title>Using FindReplaceDialog in SimplyHTML</title>  </head>
+  <body>
+    <p class="heading1">
+      Using FindReplaceDialog in SimplyHTML
+    </p>
+    <p>
+      Application SimplyHTML uses a new action in class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> to invoke <font face="'Courier New',Monospaced,Monospace">
+      FindReplaceDialog</font>. Inner class <font face="'Courier New',Monospaced,Monospace">
+FindReplaceAction</font> instanciates a <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font> in its <font face="'Courier New',Monospaced,Monospace">
+actionPerformed</font> method. Class <font face="'Courier New',Monospaced,Monospace">
+FindReplaceAction</font> implements interface <font face="'Courier New',Monospaced,Monospace">
+FindReplaceListener</font>. Whenever more than one document is open inside 
+      SimplyHTML <font face="'Courier New',Monospaced,Monospace">
+      FindReplaceAction</font> passes itself as <font face="'Courier New',Monospaced,Monospace">
+FindReplaceListener</font> to the newly instanciated <font face="'Courier New',Monospaced,Monospace">
+FindReplaceDialog</font>. Methods <font face="'Courier New',Monospaced,Monospace">
+getFirstDocument</font>, <font face="'Courier New',Monospaced,Monospace">
+      getNextDocument</font> and <font face="'Courier New',Monospaced,Monospace">
+findReplaceTerminated</font> in class <font face="'Courier New',Monospaced,Monospace">
+FindReplaceAction</font> hold functionality to implement find and replace for 
+      all documents currently open in SimplyHTML.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic34.htm b/src/com/lightdev/app/shtm/help/topic16/topic34.htm
new file mode 100644
index 0000000..a279abe
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic34.htm
@@ -0,0 +1,24 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Spotlights
+    </p>
+    <p>
+      While most functions of SimplyHTML are explained from the perspective of 
+      the structure in the source code by explaining certain methods or 
+      classes, for some functionality it makes sense to view it from a rather 
+      process oriented perspective.
+    </p>
+    <p>
+      In this section, such cases are explained in the process context, 
+      wrapping together several functions located at different places but 
+      belonging to a particular process. As well topics are reflected which do 
+      belong to certain part or class of SimplyHTML but rather should be 
+      explained in more general context.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic34/topic115.htm b/src/com/lightdev/app/shtm/help/topic16/topic34/topic115.htm
new file mode 100644
index 0000000..1f28968
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic34/topic115.htm
@@ -0,0 +1,170 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Discrepancies in HTML and CSS rendering
+    </p>
+    <p>
+      SimplyHTML tries to implement HTML and CSS usage as close to the 
+      specified standard as possible. Still there are discrepancies for 
+      rendering of the resulting documents when viewed in different 
+      environments.
+    </p>
+    <p>
+      This chapter lists known discrepancies, why they seem to occur and how 
+      SimplyHTML tries to compensate the effects, if possible. Any additional <a href="../../topic1/topic7.htm">
+hints and ideas to the author</a> are appreciated.
+    </p>
+    <p>
+      Results have been tested in the following environments so far:
+    </p>
+    <ul>
+      <li>
+        Netscape 6.2.1 (SuSE Linux 8.0)
+      </li>
+      <li>
+        Opera 6.0 B 1 (SuSE Linux 8.0)
+      </li>
+      <li>
+        Internet Explorer 5.5 (Windows Me)
+      </li>
+      <li>
+        Java J2SE 1.4 (SuSE Linux 8.0, Windows Me, Windows NT 3.51)
+      </li>
+    </ul>
+    <p>
+      Following is a list of known discrepancies.
+    </p>
+    <p class="heading2">
+      Font names
+    </p>
+    <p>
+      Fonts are locally bound to the machine SimplyHTML is running on. When 
+      formatting text to display font '<font face="'Courier New',Monospaced,Monospace">
+Palatino</font>' for instance it is not possible to predict if respective 
+      document will display similarly in any given environment. To make it 
+      easier to exchange similar font settings over different system 
+      environments, some standardized font names can be used. Common font 
+      names for that purpose are
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">Sans-Serif</font>
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">Serif</font>
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">Monospace</font>
+      </li>
+    </ul>
+    <p>
+      Unfortunately, the Java language has the name <font face="'Courier New',Monospaced,Monospace">
+SansSerif</font> for the font that most other applications know as <font face="'Courier New',Monospaced,Monospace">
+Sans<b>-</b>Serif</font>. As well Java uses name <font face="'Courier New',Monospaced,Monospace">
+Monospace<b>d</b></font>, while other applications partly use <font face="'Courier New',Monospaced,Monospace">
+Monospace</font>.
+    </p>
+    <p class="heading3">
+      Solution
+    </p>
+    <p>
+      This effect is fixed by mapping between the possible values mentioned 
+      above with class <font face="'Courier New',Monospaced,Monospace">
+      AttributeMapper</font>. Class <font face="'Courier New',Monospaced,Monospace">
+AttributeMapper</font> is used in class <font face="'Courier New',Monospaced,Monospace">
+SHTMLWriter</font> to map from Java to HTML and in class <font face="'Courier New',Monospaced,Monospace">
+SHTMLDocument.SHTMLReader.SHTMLCharacterAction</font> to map from HTML to Java.
+    </p>
+    <p>
+      In the defualt style sheet of SimplyHTML this is solved by having 
+      several font family names with the one relevant for Java as the first, 
+      e.g. <font face="'Courier New',Monospaced,Monospace">p { 
+      font-family:SansSerif, Sans-Serif; }</font>. For some reason, however, 
+      this does not work with Java on Linux, i.e. having more than one font 
+      family name in the style sheet causes Java to not recognize the font 
+      stlye name at all under Linux.
+    </p>
+    <p class="heading2">
+      Font sizes
+    </p>
+    <p>
+      Due to a bug in the <font face="'Courier New',Monospaced,Monospace">
+      javax.swing</font> package, font sizes are rendered approximately 1.3 
+      times smaller in <font face="'Courier New',Monospaced,Monospace">
+      JEditorPane</font> than in any browser (bug id 4765271, see <font face="'Courier New',Monospaced,Monospace">
+http://developer.java.sun.com/developer/bugParade/bugs/4765271.html</font>).
+    </p>
+    <p class="heading3">
+      Solution
+    </p>
+    <p>
+      SimplyHTML compensates this bug by providing customized views in class 
+      SHTMLEditorKit.SHTMLFactory. The views adjust font sizes before they are 
+      rendered so inside SimplyHTML fonts are displayed similar to as they are 
+      displayed in web browsers.
+    </p>
+    <p>
+      Unfortunately this does not fix the bug for cases where HTML is being 
+      displayed through Java APIs such as JavaHelp. So a bug fix from Sun to 
+      become available soon would still be highly welcome.
+    </p>
+    <p class="heading2">
+      Table cell borders
+    </p>
+    <p>
+      Up to J2SE 1.4 cell borders are not rendered individually and there is 
+      no way to have different colors for borders of different sides of a 
+      cell. Either a border is drawn around all sides of a table cell or no 
+      border is drawn. There is no way for example to draw a vertical border 
+      between two cells only while the other sides of these cells have no 
+      borders.
+    </p>
+    <p class="heading3">
+      Solution
+    </p>
+    <p>
+      SimplyHTML uses customized views to establish individual border 
+      rendering for table cells. Unfortunately this does not apply for cases 
+      where HTML is being displayed through Java APIs such as JavaHelp. A fix 
+      from Sun to become available soon would still be highly welcome.
+    </p>
+    <p class="heading2">
+      Table cell margins
+    </p>
+    <p>
+      The CSS specification describes CSS attribute <font face="'Courier New',Monospaced,Monospace">
+margin</font> and its variations <font face="'Courier New',Monospaced,Monospace">
+margin-top</font>, <font face="'Courier New',Monospaced,Monospace">
+      margin-bottom</font>, etc. as a way to set the distance between two 
+      block elements such as two paragraphs to each other but also for 
+      elements such as a table cell. However, a setting of <font face="'Courier New',Monospaced,Monospace">
+margin-left:2pt</font> for an arbitrary table cell is not being rendered up to 
+      now in any of the tested browsers.
+    </p>
+    <p>
+      Instead, only HTML attribute <font face="'Courier New',Monospaced,Monospace">
+cellspacing</font> is rendered so far, which is applicable only in the <font face="'Courier New',Monospaced,Monospace">
+table</font> tag (i.e. affecting all cells of respective table). Therefore 
+      specification and rendering of distances between individual table cells 
+      or for individual sides of a table cell is done correctly in SimplyHTML 
+      but it will not be shown in a web browser as it is shown in SimplyHTML.
+    </p>
+    <p>
+      Because SimplyHTML is built around formatting through CSS attributes, 
+      the <font face="'Courier New',Monospaced,Monospace">cellspacing</font> 
+      attribute can not be set for a given table in SimplyHTML. Attribute <font face="'Courier New',Monospaced,Monospace">
+cellspacing</font> is rendered in SimplyHTML, when contained in an exisitng 
+      HTML file.
+    </p>
+    <p class="heading3">
+      Solution
+    </p>
+    <p>
+      There is no solution for this effect up to now.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic34/topic151.htm b/src/com/lightdev/app/shtm/help/topic16/topic34/topic151.htm
new file mode 100644
index 0000000..89a68d4
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic34/topic151.htm
@@ -0,0 +1,212 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <title>    </title>
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using Java Web Start to launch SimplyHTML
+    </p>
+    <p>
+      <a href="../../topic22/topic6.htm">Java Web Start</a> - a technology for 
+      simplifying deployment of Java applications - gives users the power to 
+      launch full-featured applications with a single click from a Web 
+      browser. Introduced in version 1.4 of the Java 2 Standard Edition (J2SE) 
+      Java Web Start allows to download and launch applications, such as 
+      SimplyHTML, without going through complicated installation procedures.
+    </p>
+    <p class="heading3">
+      Benefits
+    </p>
+    <p>
+      The following benefits as listed in the Java Network Launching Protocol 
+      (JNLP) specification result from using Java Web Start:
+    </p>
+    <p>
+      
+    </p>
+    <ul>
+      <li>
+        <b>No installation phase</b>: A JNLP Client simply needs to download 
+        and cache the application’s resources. The user does not need to be 
+        prompted about install directories and the like.
+      </li>
+      <li>
+        <b>Transparent update</b>: A JNLP Client can check the currently 
+        cached resources against the versions hosted on the Web Server and 
+        transparently download newer versions.
+      </li>
+      <li>
+        <b>Incremental update</b>: The JNLP Client only needs to download the 
+        resources that have been changed when an application is updated. If 
+        only a few of the application’s resources have been modified, this can 
+        significantly reduce the amount of data that needs to be downloaded 
+        when upgrading to a new version of an application. Furthermore, 
+        incremental update of individual JAR files is also supported.
+      </li>
+      <li>
+        <b>Incremental download</b>: A JNLP Client does not need to download 
+        an entire application before it is launched. For example, for a 
+        spreadsheet application the downloading of the graphing module could 
+        be postponed until first use. JNLP supports this model by allowing the 
+        developer to specify what resources are needed before an application 
+        is launched (eager), and what resources can be downloaded later 
+        (lazy). Furthermore, JNLP provides an API so the developer can check 
+        if a resource is local or not (e.g., need to be downloaded or not), 
+        and to request non-local resources to be downloaded.
+      </li>
+      <li>
+        <b>Offline support</b>: A JNLP Client can launch an application 
+        offline if a sufficient set of resources are cached locally. However, 
+        most applications deployed using JNLP are expected to be Web-centric, 
+        i.e., they will typically connect back to a Web server or database to 
+        retrieve their state. Hence, many applications will only work online. 
+        The application developer specifies if offline operation is supported, 
+        and what resources are needed locally to launch the application 
+        offline.
+      </li>
+    </ul>
+    <p class="heading2">
+      How Java Web Start works for SimplyHTML
+    </p>
+    <p>
+      With <a href="../../topic16/topic140.htm">stage 8</a> of SimplyHTML, the 
+      application home page at <font face="'Courier New',Monospaced,Monospace">
+      http://www.lightdev.com/dev/sh.htm</font> holds a link to a <font face="'Courier New',Monospaced,Monospace">
+.jnlp</font> file which in turn specifies all details of application 
+      SimplyHTML (required files, descriptions, etc.). When the link is 
+      clicked, Java Web Start is invoked on the client and the application is 
+      loaded down to the client. Once loaded, SimplyHTML is launched and the 
+      application can be used immediately.
+    </p>
+    <p>
+      No manual installation, no copying of files, no command line scripting 
+      or desktop links, no compatibility checking, nothing.
+    </p>
+    <p>
+      Users can choose to always start SimplyHTML through the web or to 
+      download it to the client permanently and work with the application 
+      offline.
+    </p>
+    <p class="heading3">
+      How it is done
+    </p>
+    <p>
+      To achieve a Java Web Start for SimplyHTML a <font face="'Courier New',Monospaced,Monospace">
+.jnlp</font> file is created as follows (with <font face="'Courier New',Monospaced,Monospace">
+codebase</font> below having an example entry)
+    </p>
+    <p>
+      
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <?xml version="1.0" encoding="UTF-8"?>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <jnlp spec="1.0+" codebase="http://www.lightdev.com/dev/">
+
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:12pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <information>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <title>SimplyHTML</title>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <vendor>Light Development</vendor>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <homepage href="http://www.lightdev.com/dev/sh.htm" />
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <description>SimplyHTML text processor for HTML and CSS</description>
+
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <offline-allowed/>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:12pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      </information>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:12pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <security>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <all-permissions/>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:12pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      </security>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:12pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <resources>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <j2se version="1.4+" />
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <jar href="SimplyHTML.jar"/>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <extension name="Java Help" href="javahelp.jnlp">
+
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:24pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      </extension>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:12pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      </resources>
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:12pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <application-desc main-class="com.lightdev.app.shtm.App" />
+
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; margin-left:0pt; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      </jnlp>
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      A similar <font face="'Courier New',Monospaced,Monospace">.jnlp</font> 
+      file is created to deploy the <a href="../../topic22/topic6.htm">JavaHelp</a>
+ runtime extension (file <font face="'Courier New',Monospaced,Monospace">
+      jhall.jar</font>). The <font face="'Courier New',Monospaced,Monospace">
+      .jnlp</font> files are copied onto the web server along with the signed 
+      application <font face="'Courier New',Monospaced,Monospace">.jar</font> 
+      file. Once the application home page has the mentioned link to the <font face="'Courier New',Monospaced,Monospace">
+.jnlp</font> file, it is ready to be 'Web Started'.
+    </p>
+    <p class="heading2">
+      References
+    </p>
+    <p>
+      A very good article about how to 'Web Start' an application can be found 
+      at
+    </p>
+    <p>
+      <font color="#0033ff">
+      http://developer.java.sun.com/developer/technicalArticles/Programming/jnlp/ 
+</font>
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      A perfect explanation of how to obtain a certificate from a Certificate 
+      Authority and how to sign own code with such certificate can be found at
+    </p>
+    <p>
+      <font color="#0033ff">http://www.dallaway.com/acad/webstart/</font>
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      The official Java Web Start product page is at
+    </p>
+    <p>
+      <font color="#0033ff">http://java.sun.com/products/javawebstart/</font>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic34/topic33.htm b/src/com/lightdev/app/shtm/help/topic16/topic34/topic33.htm
new file mode 100644
index 0000000..35f0cc0
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic34/topic33.htm
@@ -0,0 +1,82 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Avoiding loss of data in the close process
+    </p>
+    <p>
+      The process of closing one or more documents technically is easy to 
+      achieve. However, making sure that changes to a document are not lost 
+      when it is closed is a more complex task.
+    </p>
+    <p class="heading2">
+      Step 1: Intercept all close actions
+    </p>
+    <p>
+      Because a close operation can be caused by different actions, it is 
+      important to take into account all occasions that would cause a document 
+      to close. So the first step to take is to ensure that each and every 
+      possible close action is intercepted by a check wheter or not it is ok 
+      to close that document or what requirements are bound to closing it.
+    </p>
+    <p>
+      In the design of SimplyHTML proper handling of close requests is ensured 
+      by having all methods to call the same action for closing a document: <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic20/topic27.htm">
+SHTMLFileCloseAction</a></font>. Having all related functionality in a central 
+      place and having all other related methods to call that central 
+      functionality makes it easier to implement exactly the correct 
+      functionality and makes sure it is implemented only once.
+    </p>
+    <p>
+      The close actions to intercept are
+    </p>
+    <ul>
+      <li>
+        closing the main frame (method <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic12/topic14.htm">
+processWindowEvent</a></font>)
+      </li>
+      <li>
+        selecting 'Exit' from menu 'File' (<font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic20/topic37.htm">
+SHTMLFileExitAction</a></font>)
+      </li>
+      <li>
+        selecting 'Close' from menu 'File' (<font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic20/topic27.htm">
+SHTMLFileCloseAction</a></font>)
+      </li>
+      <li>
+        selecting 'Close all' from menu 'File' (<font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic20/topic36.htm">
+SHTMLFileCloseAllAction</a></font>)
+      </li>
+    </ul>
+    <p class="heading2">
+      Step 2: Ensure documents are closed only when conditions allow it
+    </p>
+    <p>
+      The second step is to ensure that a document is only closed when 
+      conditions allow to close it. Before it closes a document, <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic20/topic27.htm">
+SHTMLFileCloseAction</a></font> tests in a central place, if changes are to be 
+      saved for that document first or if a save process currently is going on 
+      which finalization has to be waited for.
+    </p>
+    <p>
+      In this functionality the logic is placed to notify the user, that he is 
+      about to close a document which contains unsaved changes and to ask the 
+      user for a decision whether or not the changes should be saved before 
+      closing.
+    </p>
+    <p class="heading2">
+      Step 3: Testing the result of the close action
+    </p>
+    <p>
+      In cases where an action has to follow the close action, such as when 
+      the application shall be terminated, the exit action needs to test if a 
+      document has been actually closed after it requested to close it. 
+      Otherwise, an application would terminate even if the user opted to 
+      cancel the operation during the close action (e.g. when asked to save 
+      the document first).
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic34/topic50.htm b/src/com/lightdev/app/shtm/help/topic16/topic34/topic50.htm
new file mode 100644
index 0000000..c398def
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic34/topic50.htm
@@ -0,0 +1,57 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using layouts for proper alignment of visible components
+    </p>
+    <p>
+      The Java language holds a powerful mechanism to properly align and size 
+      GUI elements within a frame with the <font face="'Courier New',Monospaced,Monospace">
+Layout</font> concept. Other than by stating absolute coordinates at design 
+      time of GUI elements, layouts define a display model relative to certain 
+      rules.
+    </p>
+    <p class="heading2">
+      Examples in Class AboutBox
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic39/topic40.htm">
+AboutBox</a></font> of SimplyHTML is an example of how to apply the layout 
+      concept. GUI elements such as labels or images are placed onto panels. 
+      For each panel exactly one layout scheme is associated by which the 
+      panel controls positions and sizes of it's contents.
+    </p>
+    <p>
+      The panel <font face="'Courier New',Monospaced,Monospace">textPane</font>
+       for instance uses a <font face="'Courier New',Monospaced,Monospace">
+      GridLayout</font> with one column and six rows to arrange the labels 
+      contained in the panel one below the other with a gap of 5pt between 
+      each other. The <font face="'Courier New',Monospaced,Monospace">
+      contentPane</font> of AboutBox uses a <font face="'Courier New',Monospaced,Monospace">
+BorderLayout</font> to align all other panels with a border of the 
+      contentPane. <font face="'Courier New',Monospaced,Monospace">buttonPane</font>
+ sticks to the bottom edge of the <font face="'Courier New',Monospaced,Monospace">
+contentPane</font>, <font face="'Courier New',Monospaced,Monospace">northPane</font>
+ to the top edge and so on.
+    </p>
+    <p class="heading2">
+      Conclusion
+    </p>
+    <p>
+      By using layouts, the GUI elements are sized automatically to fit the 
+      resulting scheme. Most important, they all are resized according to the 
+      rules of respective layout when the container is resized. By defining 
+      layouts, the developer does not have to worry about how the components 
+      need to be sized and resized. Only their positions relative to each 
+      other and relative to their container need to be taken into account.
+    </p>
+    <p>
+      So the layout model rather follows the original intention of the 
+      developer rather than forcing him to transform the design intentions 
+      into coding models over and over again.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic34/topic71.htm b/src/com/lightdev/app/shtm/help/topic16/topic34/topic71.htm
new file mode 100644
index 0000000..8642691
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic34/topic71.htm
@@ -0,0 +1,62 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using interfaces
+    </p>
+    <p>
+      Interfaces are a good way to define rules by which objects interact. If 
+      one object likes to communicate with another it has to have a way to 
+      determine whether or not that other object 'understands'. If an object 
+      can determine from which class another object was instantiated, it can 
+      expect or not expect certain methods being present.
+    </p>
+    <p>
+      If an object is to implement an interface it has to implement all 
+      methods the particular interface defines. How the methods are 
+      implemented, i.e. which code they actually hold, is up to the 
+      implementing object. A single object can implement many interfaces.
+    </p>
+    <p class="heading2">
+      Example: SHTMLAction
+    </p>
+    <p>
+      In application SimplyHTML this is demonstrated by interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font>.
+    </p>
+    <p>
+      In the process of <a href="../../topic16/topic62/topic68.htm">dynamic 
+      menu creation</a> method createMenu adds an <font face="'Courier New',Monospaced,Monospace">
+SHTMLMenuListener</font> to each menu. <font face="'Courier New',Monospaced,Monospace">
+SHTMLMenuListener</font> is used to update all actions to reflect the up to 
+      date enabled state prior to selection of a menu. To be able to do this, <font face="'Courier New',Monospaced,Monospace">
+SHTMLMenuListener</font> must determine, whether or not an action that is to 
+      be updated, actually <i>has</i> a method to update its enabled state.
+    </p>
+    <p>
+      Interface <font face="'Courier New',Monospaced,Monospace">SHTMLAction</font>
+ is defined so that <font face="'Courier New',Monospaced,Monospace">
+      SHTMLMenuListener</font> can do that. <font face="'Courier New',Monospaced,Monospace">
+SHTMLMenuListener</font> checks if an action is of instance <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font> which it only would be if it implements interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font>. Only if an action is an instance of <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font>, its update method is called, because otherwise <font face="'Courier New',Monospaced,Monospace">
+SHTMLMenuListener</font> can not be sure if there is a method <font face="'Courier New',Monospaced,Monospace">
+update</font> in the particular action object.
+    </p>
+    <p>
+      Another advantage of the interface methodology is that objects of any 
+      class can implement interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font> so that an object instantiated from class <font face="'Courier New',Monospaced,Monospace">
+SHTMLUndoAction</font> can be an instance of <font face="'Courier New',Monospaced,Monospace">
+SHTMLUndoAction</font> and an instance of <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font> too even if <font face="'Courier New',Monospaced,Monospace">
+      SHTMLAction</font> is not a superclass according to the class hierarchy 
+      of <font face="'Courier New',Monospaced,Monospace">SHTMLUndoAction</font>
+       .
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic34/topic84.htm b/src/com/lightdev/app/shtm/help/topic16/topic34/topic84.htm
new file mode 100644
index 0000000..84dd13c
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic34/topic84.htm
@@ -0,0 +1,66 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using listeners
+    </p>
+    <p>
+      Listeners are referred in many places of this documentation probably 
+      already giving an idea about how and why they are used. Anyway the 
+      listener concept should be explained in more detail here.
+    </p>
+    <p class="heading2">
+      Example: Font manipulation
+    </p>
+    <p>
+      In stage 3 of SimplyHTML many classes dealing with font manipulation had 
+      been added. These classes mostly are GUI elements or are related to GUI 
+      elements in some way. The <a href="../../topic16/topic74.htm">
+      interaction between objects during font manipulation</a> demonstrates 
+      the importance of proper design in handling such a rather complex topic.
+    </p>
+    <p>
+      In class <font face="'Courier New',Monospaced,Monospace">FontPanel</font>
+       for instance several objects allow changes to font attributes while all 
+      attributes are reflected in another object, the sample view.
+    </p>
+    <p class="heading2">
+      Listener interface instead of hard coding object relations
+    </p>
+    <p>
+      Instead of hard coding a relationship between the font attribute 
+      selectors and the sample view component, each attribute selector <i>
+      defines</i> a listener interface. Whenever an attribute is changed, a 
+      change event is fired in the format that interface defines.
+    </p>
+    <p>
+      The sample view component in turn <i>implements</i> the interface by 
+      having a method <font face="'Courier New',Monospaced,Monospace">
+      valueChanged</font> which is defined in the listener interface of the 
+      font selectors. The sample view component is then registered as a 
+      listener with the component defining the interface.
+    </p>
+    <p>
+      Having functions to handle calls to method <font face="'Courier New',Monospaced,Monospace">
+valueChanged</font>, the functions need to be coded only once and only at the 
+      place they belong to - the sample view component in our case.
+    </p>
+    <p class="heading2">
+      Conclusion
+    </p>
+    <p>
+      The listnener concept is an elegant way of letting an arbitrary number 
+      of objects dynamically interact without having to hard code 
+      relationships between objects. By defining interfaces and listening to 
+      events a clear separation according to object boundaries is accomplished.
+    </p>
+    <p>
+      By implementing code reacting on events, redundancies are avoided and 
+      objects do not need to 'know' about how other objects have to be changed 
+      by own actions.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4.htm b/src/com/lightdev/app/shtm/help/topic16/topic4.htm
new file mode 100644
index 0000000..c5bddfc
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4.htm
@@ -0,0 +1,66 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 1: Documents and files, menus and actions
+    </p>
+    <p>
+      This stage builds the basis for application SimplyHTML. It produces a 
+      basic executable capable to create, open and save simple HTML documents. 
+      Stage 1 concentrates on how to build a basic application with a main 
+      application frame and menus. As well it shows some concepts on how to 
+      work with documents and files.
+    </p>
+    <p>
+      Following is a short description of classes making up this stage and 
+      what they do in general.
+    </p>
+    <p class="heading2">
+      
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../topic16/topic4/topic39/topic40.htm">AboutBox</a></b> - A 
+      dialog showing information about application SimplyHTML.
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../topic16/topic4/topic11.htm">App</a></b> - The class 
+      containing the main method. This class constructs application SimplyHTML.
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../topic16/topic4/topic12/topic17.htm">FrmMain</a></b> - The 
+      application's main frame containing all menus and the view of all 
+      documents in a tabbed pane.
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../topic16/topic4/topic25/topic38.htm">DocumentPane</a></b> 
+      - GUI representation of a document of SimplyHTML.
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>ExampleFileFilter</b> - a helper class from Sun Microsystems, Inc. 
+      for conveniently applying file filters to JFileChooser components
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>ElementTreePanel</b> - a panel to show the element tree of a document
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../topic16/topic4/topic25/topic45.htm">SHTMLEditorKit</a></b>
+       - the <a href="../topic16/topic4/topic25.htm">editor kit</a> used for 
+      controlling documents in SimplyHTML
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../topic16/topic4/topic25/topic48.htm">CSSWriter</a></b> - a 
+      class for writing style sheets to <a href="../topic16/topic4/topic25/topic42.htm">
+CSS</a> files
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../topic16/topic4/topic39/topic51.htm">LicensePane</a></b> - 
+      subclasses JPanel for displaying SimplyHTML's license
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>Util</b> - a class with static utility methods
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic11.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic11.htm
new file mode 100644
index 0000000..8b0d02a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic11.htm
@@ -0,0 +1,58 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a basic application
+    </p>
+    <p>
+      For creating a basic application, in Java we need a class having a 
+      method called <font face="'Courier New',Monospaced,Monospace">main</font>
+       which accepts possible parameters from the standard Java Runtime 
+      Environemt (JRE). This basically is done by the class described in <font face="'Courier New',Monospaced,Monospace">
+App.java</font>.
+    </p>
+    <p>
+      Besides providing the application's main method, <font face="'Courier New',Monospaced,Monospace">
+App.class</font> constructs an instance of the main frame of application 
+      SimplyHTML, an instance of the class defined by <font face="'Courier New',Monospaced,Monospace">
+FrmMain.java,</font><font face="Sans-Serif"> and initially displays it. </font>
+    </p>
+    <p>
+      When application SimplyHTML is started, the Java Runtime Environment 
+      opens the main thread for this aplication and executes method main of 
+      class <font face="'Courier New',Monospaced,Monospace">App</font>. Once 
+      all steps such as constructing the application's main frame, control is 
+      transferred to the event dispatching thread.
+    </p>
+    <p class="heading2">
+      Setting a look and feel
+    </p>
+    <p>
+      An important feature of Java is to support different system platforms 
+      making it necessary to design applications independent from any system 
+      specific behaviour. The author of a Java application can not predict, on 
+      which system the application actually will be used.
+    </p>
+    <p>
+      Java provides mechanisms to keep applications away from proprietary look 
+      and feels or behaviours with class <font face="'Courier New',Monospaced,Monospace">
+UIManager</font> of package <font face="'Courier New',Monospaced,Monospace">
+      javax.swing</font>. <font face="'Courier New',Monospaced,Monospace">
+      App.class</font> of SimplyHTML uses methods <font face="'Courier New',Monospaced,Monospace">
+setLookAndFeel</font> and <font face="'Courier New',Monospaced,Monospace">
+      getSystemLookAndFeelClassName</font> of class <font face="'Courier New',Monospaced,Monospace">
+UIManager</font> to initially set the look and feel to the one of the system, 
+      the application is started on.
+    </p>
+    <p>
+      By setting the L&F at runtime in the application's main method, an 
+      application can be kept independent from system specific behaviour. 
+      Class <font face="'Courier New',Monospaced,Monospace">UIManager</font> 
+      still allows to change L&F settings later in a session with the 
+      application if necessary.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic12.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12.htm
new file mode 100644
index 0000000..b830682
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12.htm
@@ -0,0 +1,36 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a main window and menus
+    </p>
+    <p>
+      As described in the previous chapter '<a href="../../topic16/topic4/topic11.htm">
+Creating a basic application</a>', <font face="'Courier New',Monospaced,Monospace">
+App.class</font> creates and displays the main window of application 
+      SimplyHTML. For doing so, it uses another class defining the actual 
+      elements and functionality of the main window, class <font face="'Courier New',Monospaced,Monospace">
+FrmMain.java</font>.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      mainly has two areas of functionality in stage 1:
+    </p>
+    <ul>
+      <li>
+        it is the window in which all documents are opened and presented to 
+        the user
+      </li>
+      <li>
+        it makes available all functions of the application through a menu bar
+      </li>
+    </ul>
+    <p>
+      This section explains class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> and its functions.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic13.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic13.htm
new file mode 100644
index 0000000..ff32f80
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic13.htm
@@ -0,0 +1,77 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Constructing the main window
+    </p>
+    <p>
+      In the constructor of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> mainly three steps are done
+    </p>
+    <ul>
+      <li>
+        preparing the window to watch for events that would close this window
+      </li>
+      <li>
+        adjusting the window to requirements special to application SimplyHTML
+      </li>
+      <li>
+        adding a menu bar and menus
+      </li>
+    </ul>
+    <p>
+      Once above steps are through as described below, application 
+      SimplyHTML's main window is shown. Once shown, the start process of the 
+      application has ended and control is transferred to the event 
+      dispatching thread which Java created for SimplyHTML automatically.
+    </p>
+    <p>
+      The event dispatching thread controls the program flow by invoking 
+      methods attached to certain events, which usually are fired by user 
+      actions.
+    </p>
+    <p class="heading2">
+      Preparing for window close events
+    </p>
+    <p>
+      Closing an ordinary window might or might not need special handling. In 
+      the simplest case, respective window just closes which would be done 
+      automatically. For an application's main window however, closing usually 
+      terminates the application which in turn mostly requires certain cleanup 
+      before an application actually can be terminated.
+    </p>
+    <p>
+      A window can be closed through various actions such as the user 
+      selecting 'Exit' from menu 'File' or the user likes to switch off the 
+      computer etc. Most of such actions are signaled to a <font face="'Courier New',Monospaced,Monospace">
+JFrame</font>, if it claims to receive respective event notifications.
+    </p>
+    <p>
+      In class <font face="'Courier New',Monospaced,Monospace">FrmMain</font>, 
+      method <font face="'Courier New',Monospaced,Monospace">enableEvents</font>
+ is called in the constructor of the class for this. Method <font face="'Courier New',Monospaced,Monospace">
+enableEvents</font> is inherited from class <font face="'Courier New',Monospaced,Monospace">
+Component</font> of package <font face="'Courier New',Monospaced,Monospace">
+      java.awt</font> and is called, when a subclass of <font face="'Courier New',Monospaced,Monospace">
+Component</font> likes to receive or handle events of a certain type even 
+      without a respective event listener in place.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      calls for events defined in AWTEvent.WINDOW_EVENT_MASK and causes events 
+      of this type being delivered to method <font face="'Courier New',Monospaced,Monospace">
+processWindowEvent</font> of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>. This method <a href="../../../topic16/topic4/topic12/topic14.htm">
+handles window closing events</a> for the main window of application 
+      SimplyHTML.
+    </p>
+    <p>
+      Especially see ' <a href="../../../topic16/topic34/topic33.htm">Avoiding 
+      loss of data in the close process</a>' partly dealing with this topic 
+      too.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic14.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic14.htm
new file mode 100644
index 0000000..1aa4ef8
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic14.htm
@@ -0,0 +1,41 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Handling window close events
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">processWindowEvent</font>
+ of class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      watches window closing events for application SimplyHTML. All other 
+      events are not handled and routed on to <font face="'Courier New',Monospaced,Monospace">
+FrmMain's</font> superclass for possible handling.
+    </p>
+    <p class="heading2">
+      Method processWindowEvent
+    </p>
+    <p>
+      For every <font face="'Courier New',Monospaced,Monospace">WINDOW_CLOSING</font>
+ event, method <font face="'Courier New',Monospaced,Monospace">
+      processWindowEvents</font> creates an instance of <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic20/topic37.htm">
+SHTMLFileExitAction</a></font> and calls its <font face="'Courier New',Monospaced,Monospace">
+actionPerformed</font> method, which actually processes the closing.
+    </p>
+    <p>
+      For handling window closing events however, it is important that <font face="'Courier New',Monospaced,Monospace">
+processWindowEvent</font> checks whether or not documents are left open upon 
+      return from <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic20/topic37.htm">
+SHTMLFileExitAction</a></font>. If, yes, this indicates one or more documents 
+      could not be closed resulting in refusing to close <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> thus keeping application SimplyHTML from terminating.
+    </p>
+    <p>
+      Especially see ' <a href="../../../topic16/topic34/topic33.htm">Avoiding 
+      loss of data in the close process</a>' partly dealing with this topic 
+      too.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic17.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic17.htm
new file mode 100644
index 0000000..d93b074
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic17.htm
@@ -0,0 +1,58 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      The class FrmMain
+    </p>
+    <p>
+      A window typically is represented by class <font face="'Courier New',Monospaced,Monospace">
+JFrame</font> of package<font face="'Courier New',Monospaced,Monospace"> 
+      javax.swing. </font>To create the specific main window of application 
+      SimplyHTML, <font face="'Courier New',Monospaced,Monospace">FrmMain</font>
+ extends <font face="'Courier New',Monospaced,Monospace">JFrame</font> by 
+      adding certain fields:
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">jtpDocs</font> - a <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> for displaying one or more documents
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">APP_NAME</font> - a 
+        string constant for representing the application's human readable name
+      </li>
+      <li>
+        Several fields for menus and menu items
+      </li>
+    </ul>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:0pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      The fields are declared private to class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> so that they can not be seen or manipulated outside class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>.
+    </p>
+    <p class="standard">
+      In addition, class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font> adds several methods with functionality for
+    </p>
+    <ul>
+      <li>
+        constructing the window
+      </li>
+      <li>
+        ensure window closings do not cause loss of data
+      </li>
+      <li>
+        adjusting the windows appearance
+      </li>
+      <li>
+        adding a menu bar and menu items
+      </li>
+    </ul>
+    <p class="standard">
+      Above functions are described in more detail in the following chapters.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic18.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic18.htm
new file mode 100644
index 0000000..5f8c8c5
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic18.htm
@@ -0,0 +1,48 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Customizing the main window
+    </p>
+    <p>
+      As mentioned in chapter '<a href="../../../topic16/topic4/topic12/topic17.htm">
+The class FrmMain</a>', this class is extending class <font face="'Courier New',Monospaced,Monospace">
+JPanel</font> by adding some extra fields and methods. To construct these 
+      extras as well as to set up the way the window initially is displayed, 
+      method <font face="'Courier New',Monospaced,Monospace">customizeFrame</font>
+ is used.
+    </p>
+    <p>
+      After setting the window title and size, method <font face="'Courier New',Monospaced,Monospace">
+customizeFrame</font> gets a reference to the windows content pane, and adds a 
+      newly created instance of <font face="'Courier New',Monospaced,Monospace">
+BorderLayout</font> to it. Finally it creates a new <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> and adds it to the center of the content pane. As the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> is the only component of the application's main window, it 
+      covers all of its visible region except for the menu and title bar.
+    </p>
+    <p class="heading2">
+      JTabbedPane jtpDocs
+    </p>
+    <p>
+      A reference to <font face="'Courier New',Monospaced,Monospace">FrmMain's</font>
+ tabbed pane is kept in field <font face="'Courier New',Monospaced,Monospace">
+      jtpDocs</font> as a central place for pointing to all documents open in 
+      the main window. Whenever a document is created or opened, it is added 
+      to <font face="'Courier New',Monospaced,Monospace">jtpDocs</font> for 
+      display.
+    </p>
+    <p>
+      Thus, <font face="'Courier New',Monospaced,Monospace">jtpDocs</font> is 
+      a good place to look for a certain document. If the currently active 
+      document shall be adressed for instance, <font face="'Courier New',Monospaced,Monospace">
+jtpDocs.getSelectedIndex</font> points to the currently selected tab in the <font face="'Courier New',Monospaced,Monospace">
+JTabbedPane</font> and <font face="'Courier New',Monospaced,Monospace">
+      jtpDocs.getComponentAt</font> fetches the component contained in this 
+      tab, which in turn would be the currently active document.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic19.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic19.htm
new file mode 100644
index 0000000..4182ad9
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic12/topic19.htm
@@ -0,0 +1,63 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Adding a menu bar and menu items
+    </p>
+    <p>
+      As class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      defines the main window of application SimplyHTML it should present the 
+      application's functions to the user. One way of doing this is to 
+      maintain a menu bar and menu items. In class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> this is done mainly in method <font face="'Courier New',Monospaced,Monospace">
+constructMenu</font> which is called in <font face="'Courier New',Monospaced,Monospace">
+FrmMain's</font> constructor.
+    </p>
+    <p class="heading2">
+      Fields referring to menus and menu items
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      holds a field for each menu and menu item in its menu bar. These fields 
+      are visible to all methods within class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>. By keeping fields referring to the menu structure it is 
+      possible to influence appearance and behaviour of the menu structure 
+      later on during the flow of the program.
+    </p>
+    <p>
+      To build a menu bar using the menu fields of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>, the fields have to be initialized first. This is done at the 
+      same time the fields are declared upon construction of a <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> object.
+    </p>
+    <p>
+      Initialization is done by creating a new instance of <font face="'Courier New',Monospaced,Monospace">
+JMenu</font> and <font face="'Courier New',Monospaced,Monospace">JMenuItem</font>
+ respectively on the line of code where that field is declared. Each menu item 
+      gets associated with an instance of the <a href="../../../topic16/topic4/topic20.htm">
+action class</a> which is meant for handling selctions of the particular menu 
+      item.
+    </p>
+    <p class="heading2">
+      Method constructMenu
+    </p>
+    <p>
+      The previously initialized menu fields of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> are put together on a menu bar by method <font face="'Courier New',Monospaced,Monospace">
+constructMenu</font>. The method first creates a new <font face="'Courier New',Monospaced,Monospace">
+JMenuBar</font> object and then adds all previously initialized menus and menu 
+      items to it.
+    </p>
+    <p>
+      It then adds a new <font face="'Courier New',Monospaced,Monospace">
+      MenuListener</font> to the file menu object which takes care of 
+      adjusting appearance of the file menu whenever it is selected. Finally 
+      the new menu bar is associated with the main window by calling method 
+      setJMenuBar, which was inherited from <font face="'Courier New',Monospaced,Monospace">
+JFrame</font>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic20.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20.htm
new file mode 100644
index 0000000..4da58af
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20.htm
@@ -0,0 +1,84 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Connecting GUI and functionality
+    </p>
+    <p>
+      Functionality of an application - more or less the application kernel - 
+      usually is separated from the graphical user interface (GUI) in separate 
+      classes. In some cases it makes sense, to combine both in one class or 
+      to create inner classes within another class too.
+    </p>
+    <p>
+      Still there must be a connection between the two, application kernel and 
+      GUI, which can be built by using actions.
+    </p>
+    <p>
+      Actions are explained in general below. In the follwoing chapters some 
+      of the actions of FrmMain are explained in greater detail. Additional 
+      comments about the actions can be found in the source code.
+    </p>
+    <p class="heading2">
+      Actions
+    </p>
+    <p>
+      Action classes are a design approach to make a central connection 
+      between GUI and functionality. With functions being coded as actions, 
+      respective functionality is kept in a central place and can be centrally 
+      combined with code dealing with availability and behaviour of the 
+      respective functions during certain states of the application.
+    </p>
+    <p class="heading3">
+      Why actions make sense
+    </p>
+    <p>
+      Coding certain functionality as actions makes code easier to maintain, 
+      because code is stored at exactly one location while the resulting 
+      action and its appearance can be connected to several GUI elements such 
+      as a menu item and a tool bar button for instance.
+    </p>
+    <p class="heading3">
+      What actions do
+    </p>
+    <p>
+      An action can be constructed with a certain name and icon. Components 
+      such as menu items or buttons automatically display an action's name and 
+      icon when it is associated with them. As well the action's state 
+      (enabled or not enabled) automatically is reflected in the component's 
+      display (dimmed or normally shown).
+    </p>
+    <p>
+      When selecting a component that has an action associated to it, this 
+      component automatically fires an action event that calls method 
+      actionPerformed of that action. An <font face="'Courier New',Monospaced,Monospace">
+ActionEvent</font> object is created automatically describing the event that 
+      led to calling the action.
+    </p>
+    <p>
+      In essence a big advantage of using actions aside of their easier 
+      maintenance is that no additional coding is required to support the 
+      mentioned interactions and dependencies.
+    </p>
+    <p class="heading3">
+      How actions are designed in class FrmMain
+    </p>
+    <p>
+      In class <font face="'Courier New',Monospaced,Monospace">FrmMain</font>, 
+      the actions are designed as inner classes. With that the actions have 
+      access to <font face="'Courier New',Monospaced,Monospace">FrmMain's</font>
+ fields and methods without <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font> having to pass references to the actions explicitly. The 
+      actions defined so far have a lot to do with the documents shown in<font face="'Courier New',Monospaced,Monospace">
+ FrmMain</font> so that access to <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic12/topic18.htm">
+jtpDocs</a></font> is quite helpful.
+    </p>
+    <p>
+      In the following chapters we look into some of the <a href="../../topic16/topic4/topic20/topic28.htm">
+actions of FrmMain</a> in detail.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic27.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic27.htm
new file mode 100644
index 0000000..14312da
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic27.htm
@@ -0,0 +1,126 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      SHTMLFileCloseAction
+    </p>
+    <p>
+      All actions implement method <font face="'Courier New',Monospaced,Monospace">
+actionPerformed</font> which gets called automatically by components bound to 
+      that action. Usually all functionality to be performed by an action goes 
+      here.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">SHTMLFileCloseAction</font>
+ adds some flexibility to that approach by having an additional method <font face="'Courier New',Monospaced,Monospace">
+closeDocument</font>. This method is called by the action's <font face="'Courier New',Monospaced,Monospace">
+actionPerformed</font> method on the currently active document so that 
+      whenever the action is fired, the currently active document is safely 
+      closed.
+    </p>
+    <p class="heading2">
+      Method closeDocument
+    </p>
+    <p>
+      With method <font face="'Courier New',Monospaced,Monospace">closeDocument</font>
+ an arbitrary document shown in the main window can be closed even if it is 
+      not the currently active one. The method is declared public so that it 
+      can be called and reused from other places simply by instantiating class <font face="'Courier New',Monospaced,Monospace">
+SHTMLFileCloseAction</font>.
+    </p>
+    <p>
+      The method's main task is to ensure that a document is only closed, when 
+      all of its contents are properly saved. It does this by
+    </p>
+    <ol>
+      <li>
+        check, whether or not the particular document needs to be saved (if it 
+        was newly created and/or contains unsaved changes, that is)
+      </li>
+      <li>
+        if not, the document is closed
+      </li>
+      <li>
+        if yes, the user is asked if the document shall be saved
+      </li>
+      <li>
+        if the document shall be saved, it is saved by calling the appropriate 
+        action class (perform a 'save' or 'save as')
+      </li>
+      <li>
+        if the save was successful or if the user chose not to save changes, 
+        the document is closed
+      </li>
+      <li>
+        if the save was not successful or the user wanted to cancel, the 
+        document is not closed
+      </li>
+    </ol>
+    <p>
+      In all cases, closing the document is done simply by removing the 
+      respective DocumentPane from <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic12/topic17.htm">
+FrmMain's</a></font> <a href="../../../topic16/topic4/topic12/topic18.htm">
+      jtpDocs</a>.
+    </p>
+    <p class="heading3">
+      Special case: save thread in progress
+    </p>
+    <p>
+      As outlined in '<a href="../../../topic16/topic4/topic20/topic49.htm"> 
+      Using threads for lengthy operations</a>', saving a document among other 
+      functions is set forth in an own thread. Any close operation has to 
+      consider, that a save operation on a particular document could be in 
+      progress at the time the user selects to close a document. Method <font face="'Courier New',Monospaced,Monospace">
+closeDocument</font> takes this into account by calling Method <font face="'Courier New',Monospaced,Monospace">
+scheduleClose</font> (see below) in cases where it detects a save operation 
+      being in progress or where it caused a save operation itself while 
+      attempting to close a document.
+    </p>
+    <p class="heading3">
+      Method scheduleClose
+    </p>
+    <p>
+      When a save operation is in progress on a document that is to be closed, 
+      SimplyHTML has to wait for the save operation to finish because a 
+      document may only be closed when it was saved successful. Whether or not 
+      the save operation was successful can only be determined, once it 
+      completely finishes, so in this case, the application has to wait with 
+      closing until then.
+    </p>
+    <p>
+      To block the application from other activities, method <font face="'Courier New',Monospaced,Monospace">
+scheduleClose</font> creates a <font face="'Courier New',Monospaced,Monospace">
+      Timer</font> thread and schedules a <font face="'Courier New',Monospaced,Monospace">
+TimerTask</font> with the <font face="'Courier New',Monospaced,Monospace">Timer</font>
+ . The <font face="'Courier New',Monospaced,Monospace">TimerTask</font> 
+      periodically checks whether or not the save operation of the particular 
+      document has finished with the help of field <font face="'Courier New',Monospaced,Monospace">
+saveInProgress</font> of class <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font>. If it has finished, the document is closed and the <font face="'Courier New',Monospaced,Monospace">
+Timer</font> and <font face="'Courier New',Monospaced,Monospace">TimerTask</font>
+ are disposed. If there was an error during the save operation, the document 
+      remains open.
+    </p>
+    <p class="heading2">
+      Design advantage
+    </p>
+    <p>
+      The advantage of this design is that closing a document safely is 
+      implemented only once. Still it can be reused either as action or as 
+      method from anywhere in the application as done in <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic20/topic36.htm">
+SHTMLFileCloseAllAction</a></font> or <font face="'Courier New',Monospaced,Monospace">
+SHTMLFileExitAction</font> for instance.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Especially see '<a href="../../../topic16/topic34/topic33.htm">Avoiding 
+      loss of data in the close process</a>' partly dealing with this topic 
+      too.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic28.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic28.htm
new file mode 100644
index 0000000..658b95d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic28.htm
@@ -0,0 +1,101 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Actions of FrmMain
+    </p>
+    <p>
+      The actions in <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic12/topic17.htm">
+FrmMain</a></font> take use much of class <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic38.htm">
+DocumentPane</a></font>. They call some of the functions for files and 
+      documents available in this class. Also other functions are wrapped into 
+      actions.
+    </p>
+    <p>
+      In this section it is explained, how to make existing functions 
+      available to the user. The functions of stage 1 themselves are explained 
+      in '<a href="../../../topic16/topic4/topic25.htm">Creating and storing 
+      documents</a>' and in '<a href="../../../topic16/topic4/topic39.htm"> 
+      Documenting the application</a>'.
+    </p>
+    <p class="heading2">
+      Actions for the file menu
+    </p>
+    <p>
+      In the file menu, the basic actions on documents and files are 
+      selectable. Create new documents, open documents from file, save changes 
+      to documents, save new documents or save exisiting documents under a new 
+      name and finally exiting the application can be done by the user through 
+      this menu.
+    </p>
+    <p class="heading2">
+      Actions for the help menu
+    </p>
+    <p>
+      The help menu makes all kinds of documentation available to the user. 
+      With stage 1 of application SimplyHTML the help menu has links to the 
+      help file (this tutorial), the API documentation and an <a href="../../../topic16/topic4/topic39/topic40.htm">
+'About this application' dialog</a>.
+    </p>
+    <p class="heading2">
+      Action list and short description
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>SHTMLFileNewAction</b> - <a href="../../../topic16/topic4/topic25/topic29.htm">
+create</a> a new document and show it
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>SHTMLFileOpenAction</b> - <a href="../../../topic16/topic4/topic25/topic31.htm">
+open</a> an existing document and show it
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../../../topic16/topic4/topic20/topic27.htm">
+      SHTMLFileCloseAction</a></b> - close a currently open document and take 
+      care of <a href="../../../topic16/topic4/topic25/topic32.htm">saving</a> 
+      the document before closing if necessary
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../../../topic16/topic4/topic20/topic36.htm">
+      SHTMLFileCloseAllAction</a></b> - close all currently open documents and 
+      take care of <a href="../../../topic16/topic4/topic25/topic32.htm">saving</a>
+ the documents before closing if necessary
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b><a href="../../../topic16/topic4/topic20/topic37.htm">
+      SHTMLFileExitAction</a></b> - exit the application and take care of <a href="../../../topic16/topic4/topic25/topic32.htm">
+saving</a> open documents before closing if necessary
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>SHTMLFileSaveAction</b> - <a href="../../../topic16/topic4/topic25/topic32.htm">
+save</a> a document
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>SHTMLFileSaveAsAction</b>- <a href="../../../topic16/topic4/topic25/topic32.htm">
+save</a> a document under a new name
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>SHTMLHelpAppInfoAction</b> - shows SimplyHTML's <a href="../../../topic16/topic4/topic39/topic40.htm">
+about dialog </a>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>SHTMLHelpShowContentsAction</b> - brings up online help
+    </p>
+    <p class="heading2">
+      Dynamic interaction
+    </p>
+    <p>
+      There is a certain dependability between some of the actions which 
+      requires to aviod redundancy of code in the design therefore. Using 
+      actions bears an advantage for this because it allows to build a more 
+      complex process by combining actions individually.
+    </p>
+    <p>
+      Especially see '<a href="../../../topic16/topic34/topic33.htm">Avoiding 
+      loss of data in the close process</a>' in the Spotlights section partly 
+      dealing with this issue too.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic36.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic36.htm
new file mode 100644
index 0000000..b945b96
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic36.htm
@@ -0,0 +1,27 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      SHTMLFileCloseAllAction
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">SHTMLFileCloseAllAction</font>
+ uses <font face="'Courier New',Monospaced,Monospace">SHTMLFileCloseAction</font>
+ to close all currently open documents. It declares a field for an own private 
+      instance of <font face="'Courier New',Monospaced,Monospace">
+      SHTMLFileCloseAction</font>. This field gets initialized it with an <font face="'Courier New',Monospaced,Monospace">
+SHTMLFileCloseAction</font> object upon construction of the <font face="'Courier New',Monospaced,Monospace">
+SHTMLFileCloseAllAction</font> object.
+    </p>
+    <p>
+      In it's <font face="'Courier New',Monospaced,Monospace">actionPerformed</font>
+ method <font face="'Courier New',Monospaced,Monospace">SHTMLFileCloseAllAction</font>
+ then simply loops through all open documents and calls method <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic20/topic27.htm">
+closeDocument</a></font> of <font face="'Courier New',Monospaced,Monospace">
+      SHTMLFileCloseAction</font>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic37.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic37.htm
new file mode 100644
index 0000000..0267e09
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic37.htm
@@ -0,0 +1,29 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      SHTMLFileExitAction
+    </p>
+    <p>
+      This action will terminate the application and takes care of saving 
+      possibly existing unsaved changes before. The application will only be 
+      terminated, if all possibly open documents could successfully and safely 
+      be closed.
+    </p>
+    <p>
+      To ensure a safe termination of SimplyHTML, <font face="'Courier New',Monospaced,Monospace">
+SHTMLFileExitAction</font> fires an <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic20/topic36.htm">
+SHTMLFileCloseAll</a></font> action to safely close all possibly open 
+      documents. It then checks whether or not documents are left open. If 
+      yes, one or more documents could not be closed safely and the 
+      application will not be terminated.
+    </p>
+    <p>
+      To properly handle window close events, this action is used in method <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic12/topic14.htm">
+processWindowEvent</a></font> of FrmMain too.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic49.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic49.htm
new file mode 100644
index 0000000..51f2435
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic20/topic49.htm
@@ -0,0 +1,69 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using threads for lengthy operations
+    </p>
+    <p>
+      Most of the operations we encountered so far are not considerably time 
+      consuming. Especially loading or saving documents however, can be a 
+      lengthy task depending on the amount of data to be processed. Without 
+      any special handling of these tasks, application SimplyHTML could block 
+      for the time a particular save or load process would take. Java provides 
+      a mechanism to overcome this potential problem with class <font face="'Courier New',Monospaced,Monospace">
+Thread</font>.
+    </p>
+    <p class="heading2">
+      Threads
+    </p>
+    <p>
+      Usually all activities of an application are done within the event 
+      dispatching thread. All lines of code contained in a method called by 
+      the event dispatching thread are executed sequentially in the order they 
+      are coded. In Java however, this must not be the case always. By opening 
+      a new <font face="'Courier New',Monospaced,Monospace">Thread</font> 
+      object and starting the code placed in its <font face="'Courier New',Monospaced,Monospace">
+run</font> method, this piece of code is executed in parallel or at least 
+      asynchonous from the event dispatching thread.
+    </p>
+    <p class="heading2">
+      How SimplyHTML uses threads
+    </p>
+    <p>
+      In SimplyHTML three operations are executed in separate threads so far: 
+      saving a document to a file, loading a document from a file and closing 
+      one or more documents. All operations are embedded in an inner class of 
+      the respectice Actions <font face="'Courier New',Monospaced,Monospace">
+      SHTMLFileSaveAction,</font> <font face="'Courier New',Monospaced,Monospace">
+SHTMLFileOpenAction,</font> <font face="'Courier New',Monospaced,Monospace">
+      SHTMLFileSaveAsAction</font> and <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic20/topic27.htm">
+SHTMLFileCloseAction</a></font>.
+    </p>
+    <p>
+      The inner classes <font face="'Courier New',Monospaced,Monospace">
+      FileSaver</font>, <font face="'Courier New',Monospaced,Monospace">
+      NewFileSaver,</font> <font face="'Courier New',Monospaced,Monospace">
+      FileLoader</font> are subclasses of class <font face="'Courier New',Monospaced,Monospace">
+Thread</font> and simply wrap the call to <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic32.htm">
+saveDocument</a></font> or <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic31.htm">
+loadDocument</a></font> respectively in the <font face="'Courier New',Monospaced,Monospace">
+run</font> method inherited from the <font face="'Courier New',Monospaced,Monospace">
+Thread</font> class. Once an action is fired, its <font face="'Courier New',Monospaced,Monospace">
+actionPerformed</font> method creates an instance of <font face="'Courier New',Monospaced,Monospace">
+FileSaver</font>, <font face="'Courier New',Monospaced,Monospace">NewFileSaver</font>
+ or <font face="'Courier New',Monospaced,Monospace">FileLoader</font> and 
+      calls its <font face="'Courier New',Monospaced,Monospace">start</font> 
+      method.
+    </p>
+    <p>
+      In addition, method <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic20/topic27.htm">
+scheduleClose</a></font> in <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic20/topic27.htm">
+SHTMLFileCloseAction</a></font> creates a <font face="'Courier New',Monospaced,Monospace">
+Timer</font> thread for each close operation waiting for a save operation to 
+      complete.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25.htm
new file mode 100644
index 0000000..75a1f11
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25.htm
@@ -0,0 +1,74 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating and storing documents
+    </p>
+    <p>
+      From the perspective of application SimplyHTML there is a distinction 
+      between documents as represented in package <font face="'Courier New',Monospaced,Monospace">
+javax.swing</font> and documents of application SimplyHTML. Package <font face="'Courier New',Monospaced,Monospace">
+javax.swing</font> provides a very powerful set of classes for working with 
+      documents, which relieves applications from having to completely 
+      implement their own editor, document model, etc.
+    </p>
+    <p>
+      How this set of classes is implemented in an application is left to the 
+      application developer however, allowing a maximum of flexibility while 
+      reducing effort and still retaining a common basis for the particular 
+      functionality.
+    </p>
+    <p class="heading2">
+      Documents in Java
+    </p>
+    <p>
+      The package <font face="'Courier New',Monospaced,Monospace">javax.swing</font>
+ implements a model-view-controller (MVC) approach to work with documents as 
+      shown below:
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>Document</b> - the model for swing text components
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>EditorKit</b> - the controller for text components
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:10pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <b>JTextComponent</b> - the view component
+    </p>
+    <p>
+      The interface <font face="'Courier New',Monospaced,Monospace">Document</font>
+ is a container for text that serves as the model for swing text components. 
+      The goal for this interface is to scale from very simple needs (a plain 
+      text textfield) to complex needs (an HTML or XML document, for example).
+    </p>
+    <p>
+      The abstract class <font face="'Courier New',Monospaced,Monospace">
+      EditorKit</font> serves as the controller for text components 
+      establishing the set of things needed by a text component to be a 
+      reasonably functioning editor for some type of text content.
+    </p>
+    <p>
+      Abstract class <font face="'Courier New',Monospaced,Monospace">
+      JTextComponent</font> finally is the view component in the MVC context 
+      serving as the base class for swing text components such as <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font>.
+    </p>
+    <p class="heading2">
+      Documents in SimplyHTML
+    </p>
+    <p>
+      SimplyHTML defines an own class for dealing with the documents used in 
+      the application. Class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic25/topic38.htm">
+DocumentPane</a></font> is used to create new documents, load documents from 
+      file, save documents, view and edit documents and to define a SimplyHTML 
+      document in general.
+    </p>
+    <p>
+      With DocumentPane there is only one interface to deal with for both GUI 
+      and functionality when working with documents.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic29.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic29.htm
new file mode 100644
index 0000000..080d916
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic29.htm
@@ -0,0 +1,117 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating new documents
+    </p>
+    <p>
+      To create a new document basically two steps are necessary
+    </p>
+    <ol>
+      <li>
+        create a new <font face="'Courier New',Monospaced,Monospace">
+        DocumentPane</font> for viewing and editing a new document
+      </li>
+      <li>
+        create a new <font face="'Courier New',Monospaced,Monospace">
+        HTMLDocument</font>, initialize it properly and attach it to the 
+        editor pane of the <font face="'Courier New',Monospaced,Monospace">
+        DocumentPane</font>
+      </li>
+    </ol>
+    <p>
+      With method <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane(URL url)</font> class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> has a constructor especially for that purpose. When a <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> is created by calling this constructor with <font face="'Courier New',Monospaced,Monospace">
+null</font> as the url parameter, the <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> is told to create a new <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> after <a href="../../../topic16/topic4/topic25/topic41.htm">
+creating the basic DocumentPane</a>. The constructor calls <font face="'Courier New',Monospaced,Monospace">
+this()</font> to create a basic <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> and then it calls method <font face="'Courier New',Monospaced,Monospace">
+createNewDocument</font> for creating the new document.
+    </p>
+    <p class="heading2">
+      Method createNewDocument
+    </p>
+    <p>
+      As with <a href="../../../topic16/topic4/topic25/topic41.htm">creating a 
+      new editor pane</a>, it is not enough to simply create a new <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> object and send it to the editor pane. We need additional 
+      steps inorder to adjust the <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> to the needs of application SimplyHTML which is why it 
+      makes sense to put these steps into an own method.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">createNewDocument</font> 
+      first gets the <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic45.htm">
+SHTMLEditorKit</a></font> which was attached to the editor pane upon 
+      construction of the <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font>. A new <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> is created by calling method <font face="'Courier New',Monospaced,Monospace">
+createDefaultDocument</font> of the editor kit. <font face="'Courier New',Monospaced,Monospace">
+createDefaultDocument</font> ensures that we get a new <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> properly initialized and with our default style sheet 
+      attached to it.
+    </p>
+    <p>
+      The <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font> 
+      then gets inserted a link reference to the style sheet file. Because we 
+      create a new <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font>
+ , this link refers to the name of SimplyHTML's default style sheet. The link 
+      reference is necessary because once we save the <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>, it can be used with other applications too. For an 
+      application other than SimplyHTML, the only way to determine which style 
+      sheet to use when the <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font> is loaded is this particular style sheet reference 
+      (see '<a href="../../../topic16/topic4/topic25/topic42.htm">Style sheets 
+      and HTML documents</a>'). To insert the style sheet reference to the 
+      document, method <font face="'Courier New',Monospaced,Monospace">
+      insertStyleRef</font> is used (see below).
+    </p>
+    <p>
+      The <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      is registered as <font face="'Courier New',Monospaced,Monospace">
+      DocumentListener</font> with the new document, causing the document to 
+      notify its <font face="'Courier New',Monospaced,Monospace">DocumentPane</font>
+ about all changes. Finally the new <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> is assigned to the editor pane.
+    </p>
+    <p class="heading2">
+      Method insertStyleRef
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">insertStyleRef</font>
+ inserts a reference link to the style sheet file to be associated with the 
+      HTML document having this reference link. The reference link has a 
+      syntax such as <font face="'Courier New',Monospaced,Monospace"><link 
+      rel=stylesheet type="text/css" href="style.css"></font>
+ and is to be placed in the <font face="'Courier New',Monospaced,Monospace">
+      <head></font> tag of a HTML document (see '<a href="../../../topic16/topic4/topic25/topic42.htm">
+Style sheets and HTML documents</a>').
+    </p>
+    <p>
+      To insert the reference, method <font face="'Courier New',Monospaced,Monospace">
+insertStyleRef</font> 'walks' through the element structure of a <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> and looks for its <font face="'Courier New',Monospaced,Monospace">
+<head></font> and <font face="'Courier New',Monospaced,Monospace"><body></font>
+ tags. If a <font face="'Courier New',Monospaced,Monospace"><head></font>
+       tag is found, it is assumed that it already has the appropriate 
+      reference and the method does nothing.
+    </p>
+    <p>
+      Otherwise, it uses method <font face="'Courier New',Monospaced,Monospace">
+insertBeforeStart</font> of class <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> to insert a new <font face="'Courier New',Monospaced,Monospace">
+<head></font> tag before the start of the <font face="'Courier New',Monospaced,Monospace">
+<body></font> tag. The <font face="'Courier New',Monospaced,Monospace">
+      <head></font> tag is inserted along with the reference link to the 
+      style sheet by passing a respective HTML string to method <font face="'Courier New',Monospaced,Monospace">
+insertBeforeStart</font>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic31.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic31.htm
new file mode 100644
index 0000000..46b43d6
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic31.htm
@@ -0,0 +1,66 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Loading documents from file
+    </p>
+    <p>
+      When a document is loaded into a <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font>, the <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font> and its components need to be initialized properly. 
+      This is done in method <font face="'Courier New',Monospaced,Monospace">
+      loadDocument</font>.
+    </p>
+    <p class="heading2">
+      Method loadDocument
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">loadDocument</font>
+ , first the editor kit object is taken from the editor pane of this <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> object. With method <font face="'Courier New',Monospaced,Monospace">
+createDefaultDocument</font> of the editor kit a properly initialized empty 
+      document object is created with the appropriate style sheet attached. 
+      The document base is set from the URL the document is to be loaded from. 
+      The document base is necessary so that all relative URLs probably 
+      contained in the document are correctly resolved.
+    </p>
+    <p>
+      The contents of the HTML file are then loaded into the new document 
+      object by opening an <font face="'Courier New',Monospaced,Monospace">
+      InputStream</font> from the URL and using method <font face="'Courier New',Monospaced,Monospace">
+read</font> of the editor kit. The DocumentPane registers itself as <font face="'Courier New',Monospaced,Monospace">
+DocumentListener</font> with the new document, causing the document to notify 
+      its <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      about all changes.
+    </p>
+    <p>
+      Finally the new <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font> is assigned to the editor pane and the URL, the 
+      document was loaded from is stored in field <font face="'Courier New',Monospaced,Monospace">
+sourceUrl</font> of the <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font>.
+    </p>
+    <p class="heading2">
+      How the style sheet is associated
+    </p>
+    <p>
+      Application SimplyHTML assumes that every HTML document is associated 
+      with a style sheet in a separate <a href="../../../topic16/topic4/topic25/topic42.htm">
+CSS</a> file. This style sheet must be referenced by a link in the <font face="'Courier New',Monospaced,Monospace">
+<head></font> tag of the HTML document as it is generated by method <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic29.htm">
+insertStyleRef</a></font>.
+    </p>
+    <p>
+      If such a reference link is contained in the <font face="'Courier New',Monospaced,Monospace">
+<head></font> tag of an <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font> and the style sheet file can be found at the 
+      referenced location, the <font face="'Courier New',Monospaced,Monospace">
+      read</font> method of the editor kit handles the style sheet reference 
+      correctly and the editor pane renders the HTML document with the 
+      associated styles.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic32.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic32.htm
new file mode 100644
index 0000000..2fb825d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic32.htm
@@ -0,0 +1,57 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Saving documents
+    </p>
+    <p>
+      To persistently store a newly created document or to save changes to an 
+      existing one, application SimplyHTML uses an object of class <font face="'Courier New',Monospaced,Monospace">
+HTMLWriter</font> which package <font face="'Courier New',Monospaced,Monospace">
+javax.swing</font> holds especially for <font face="'Courier New',Monospaced,Monospace">
+HTMLDocuments</font>. Again, to simply call <font face="'Courier New',Monospaced,Monospace">
+HTMLWriter's</font> <font face="'Courier New',Monospaced,Monospace">write</font>
+ method is not enough to meet saving requirements of SimplyHTML. Class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> uses methods <font face="'Courier New',Monospaced,Monospace">
+saveDocument</font> and <font face="'Courier New',Monospaced,Monospace">
+      saveDefaultStyleSheet</font> to put together its own save routine.
+    </p>
+    <p class="heading2">
+      Method saveDocument
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">saveDocument</font>
+ class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      uses its field <font face="'Courier New',Monospaced,Monospace">sourceUrl</font>
+ to tell <font face="'Courier New',Monospaced,Monospace">HTMLWriter</font> 
+      where to save a document. Field <font face="'Courier New',Monospaced,Monospace">
+sourceUrl</font> usually has been set previously either by method <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic31.htm">
+loadDocument</a></font> or <font face="'Courier New',Monospaced,Monospace">
+      saveDocumentAs</font>. If no <font face="'Courier New',Monospaced,Monospace">
+soureUrl</font> is set for any reason, <font face="'Courier New',Monospaced,Monospace">
+saveDocument</font> does nothing.
+    </p>
+    <p>
+      When field <font face="'Courier New',Monospaced,Monospace">sourceUrl</font>
+ is properly set, <font face="'Courier New',Monospaced,Monospace">saveDocument</font>
+ creates a <font face="'Courier New',Monospaced,Monospace">FileOutputStream</font>
+ for respective URL, attaches it to a new <font face="'Courier New',Monospaced,Monospace">
+OutputStreamWriter</font> and creates an instance of <font face="'Courier New',Monospaced,Monospace">
+HTMLWriter</font> with these parameters. <font face="'Courier New',Monospaced,Monospace">
+HTMLWriter</font> completely takes care of transforming the model of object <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> to an HTML file when its method <font face="'Courier New',Monospaced,Monospace">
+write</font> is called.
+    </p>
+    <p>
+      Once the HTML file is saved, its associated style sheet is saved by 
+      calling method <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic47.htm">
+saveStyleSheet</a></font>. Finally field <font face="'Courier New',Monospaced,Monospace">
+textChanged</font> is set to <font face="'Courier New',Monospaced,Monospace">
+      false</font> to indicate that the document of this <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> does not contain changes which need to be saved.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic38.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic38.htm
new file mode 100644
index 0000000..ff9e2a6
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic38.htm
@@ -0,0 +1,95 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      The class DocumentPane
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      implements an application centric approach of a document, wrapping the 
+      classes of <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25.htm">
+javax.swing</a></font> together with application and GUI functionality into 
+      one class.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      follows the idea of having a single interface between an application and 
+      its documents. It serves as the single point for displaying, editing, 
+      opening, saving etc. For this, it combines GUI elements and <a href="../../../topic16/topic4/topic25.htm">
+'MVC' elements</a> to form one consistent and compact class to work with in 
+      applications.
+    </p>
+    <p class="heading2">
+      Elements of DocumentPane
+    </p>
+    <p>
+      The major element of <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font> is a <font face="'Courier New',Monospaced,Monospace">
+      JEditorPane</font>. <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font> extends <font face="'Courier New',Monospaced,Monospace">
+JPanel</font> and combines a <font face="'Courier New',Monospaced,Monospace">
+      JScrollPane</font> and the J<font face="'Courier New',Monospaced,Monospace">
+EditorPane</font> as the only visible components.
+    </p>
+    <p>
+      In addition it has fields for storing the name of the document, the 
+      source where it has been loaded from and a field indicating whether or 
+      not the document has changed. Finally constants for a default document 
+      name as well as two cursor definitions are contained as fields in the <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font>.
+    </p>
+    <p>
+      There are two fields reflecting save operations as well: <font face="'Courier New',Monospaced,Monospace">
+saveInProgress</font> is set to true while a save operation runs and <font face="'Courier New',Monospaced,Monospace">
+saveSuccessful</font> is set by a save operation before (false) and after a 
+      save (true, if and only if all went fine) to indicate any errors while 
+      saving.
+    </p>
+    <p>
+      Last but not least, <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font> implements interface <font face="'Courier New',Monospaced,Monospace">
+DocumentListener</font> to recognize changes.
+    </p>
+    <p class="heading3">
+      Interface DocumentListener
+    </p>
+    <p>
+      In field <font face="'Courier New',Monospaced,Monospace">textChanged</font>
+ class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      'remembers' if there have been changes to it's document since its 
+      creation or since the last save to file operation. But the <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> needs to be notified about changes for being able to 
+      'remember' them. It implements interface <font face="'Courier New',Monospaced,Monospace">
+DocumentListener</font> for that purpose.
+    </p>
+    <p>
+      Interface <font face="'Courier New',Monospaced,Monospace">
+      DocumentListener</font> defines what a class would have to do to listen 
+      to <font face="'Courier New',Monospaced,Monospace">DocumentEvents</font> 
+      . <font face="'Courier New',Monospaced,Monospace">DocumentEvents</font> 
+      are fired to registered listeners whenever a document is changed in any 
+      way for instance.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">DocumentPane</font>
+       defines methods <font face="'Courier New',Monospaced,Monospace">
+      insertUpdate</font>, <font face="'Courier New',Monospaced,Monospace">
+      changedUpdate</font> and <font face="'Courier New',Monospaced,Monospace">
+      removeUpdate</font> to implement the <font face="'Courier New',Monospaced,Monospace">
+DocumentListener</font> interface. By doing that, class <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font> is a <font face="'Courier New',Monospaced,Monospace">
+      DocumentListener</font> and can register itself with any document to 
+      listen for changes.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> sets 
+      field <font face="'Courier New',Monospaced,Monospace">textChanged</font> 
+      to <font face="'Courier New',Monospaced,Monospace">true</font> whenever 
+      it is notified of a <font face="'Courier New',Monospaced,Monospace">
+      DocumentEvent</font>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic41.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic41.htm
new file mode 100644
index 0000000..8454875
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic41.htm
@@ -0,0 +1,86 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Constructing a DocumentPane
+    </p>
+    <p>
+      Simply creating a new instance of an editor pane and throwing it onto a <font face="'Courier New',Monospaced,Monospace">
+JPanel</font> is not enough to display and use a <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font>. Due to the <a href="../../../topic16/topic4/topic25.htm">
+      relationship</a> of <font face="'Courier New',Monospaced,Monospace">
+      Document</font>, <font face="'Courier New',Monospaced,Monospace">
+      EditorKit</font>, <font face="'Courier New',Monospaced,Monospace">
+      JEditorPane</font> and <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet</font> it is necessary to initialize all elements properly.
+    </p>
+    <p>
+      In <font face="'Courier New',Monospaced,Monospace">DocumentPane's</font> 
+      basic constructor <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane()</font> a new J<font face="'Courier New',Monospaced,Monospace">
+EditorPane</font> is created and assigned to field <font face="'Courier New',Monospaced,Monospace">
+editor</font>. The caret color for the editor pane is set and the typical text 
+      cursor is assigned by calling method <font face="'Courier New',Monospaced,Monospace">
+setEditCursor</font> (see below).
+    </p>
+    <p>
+      Then a new <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic45.htm">
+SHTMLEditorKit</a></font> is created and assigned to our editor pane. This 
+      procedure ensures that a document gets correctly initialized with the 
+      style sheet properly attached.
+    </p>
+    <p>
+      Finally a new <font face="'Courier New',Monospaced,Monospace">JScrollPane</font>
+ is created, the editor pane is added to the scroll pane and both are added to 
+      the <font face="'Courier New',Monospaced,Monospace">DocumentPane</font> 
+      after defining an appropriate layout.
+    </p>
+    <p>
+      The editor pane has to reside inside a <font face="'Courier New',Monospaced,Monospace">
+JScrollPane</font> for a vertical scroll bar automatically being shown as 
+      needed. The editor pane automatically wraps words at the right end of 
+      the pane so that a horizontal scroll bar is not shown or needed.
+    </p>
+    <p class="heading2">
+      Method setEditCursor
+    </p>
+    <p>
+      Although <font face="'Courier New',Monospaced,Monospace">JEditorPane</font>
+ has a method <font face="'Courier New',Monospaced,Monospace">setCursor</font> 
+      inherited from <font face="'Courier New',Monospaced,Monospace">
+      java.awt.Component</font>, setting the cursor with that method does not 
+      cause respective cursor to be displayed (probably someone can let me 
+      know why sometime). Method <font face="'Courier New',Monospaced,Monospace">
+setEditCursor</font> therefore adds a <font face="'Courier New',Monospaced,Monospace">
+MenuListener</font> to our editor, that reacts on <font face="'Courier New',Monospaced,Monospace">
+mouseEntered</font> and <font face="'Courier New',Monospaced,Monospace">
+      mouseExited</font> events.
+    </p>
+    <p>
+      When the mouse enters the editor pane, the cursor is set to the text 
+      cursor, when the mouse exits the editor pane the cursor is reset to a 
+      default cursor.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">setEditCursor</font>
+ achieves this by getting the <font face="'Courier New',Monospaced,Monospace">
+      glassPane</font> of the <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane's</font> <font face="'Courier New',Monospaced,Monospace">
+      JRootPane</font>, assigning respective cursor and setting the <font face="'Courier New',Monospaced,Monospace">
+glassPane</font> to visible.
+    </p>
+    <p class="heading2">
+      
+    </p>
+    <p>
+      Constructing a <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font> with above steps sets up the basic contents of a <font face="'Courier New',Monospaced,Monospace">
+DocumentPane</font>. Read on to learn how to <a href="../../../topic16/topic4/topic25/topic29.htm">
+create a new document</a> for editing or to <a href="../../../topic16/topic4/topic25/topic31.htm">
+open an existing one</a>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic42.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic42.htm
new file mode 100644
index 0000000..4b94e33
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic42.htm
@@ -0,0 +1,55 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Style sheets and HTML documents
+    </p>
+    <p>
+      Before we start looking into how SimplyHTML implements the use of 
+      Documents, we should spend some time on reviewing how HTML documents and 
+      Cascading Style Sheets (CSS) are related.
+    </p>
+    <p class="heading2">
+      What are CSS styles
+    </p>
+    <p>
+      Styles in CSS syntax are an extension to 'plain' HTML that allow to 
+      define attributes describing how HTML content should look. With styles 
+      one can define that paragraphs should always have a 6pt margin at the 
+      top for instance or that headlines always should be shown in red letters 
+      of 18pt size using font Helvetica.
+    </p>
+    <p class="heading2">
+      How styles can be used
+    </p>
+    <p>
+      HTML allows to combine content and styles all in one HTML file, for 
+      example by means of adding <font face="'Courier New',Monospaced,Monospace">
+style</font> attributes to HTML tags. Another way is to store a <font face="'Courier New',Monospaced,Monospace">
+<style></font> tag in the <font face="'Courier New',Monospaced,Monospace">
+<head></font> tag of the document.
+    </p>
+    <p>
+      In addition it is possible to store styles in files separated from an 
+      HTML file. Storing styles in Cascading Style Sheets (CSS) has the 
+      advantage that a set of common styles can be defined at a central 
+      location serving as the basis for an arbitrary number of HTML files.
+    </p>
+    <p class="heading2">
+      How SimplyHTML uses styles
+    </p>
+    <p>
+      In SimplyHTML a combination of styles defined separately in style sheets 
+      and styles defined as attributes within HTML tags is implemented. 
+      Whenever possible SimplyHTML avoids HTML tags such as <font face="'Courier New',Monospaced,Monospace">
+<font></font> in favour of styles.
+    </p>
+    <p>
+      See '<a href="../../../topic16/topic4/topic25/topic46.htm">Style 
+      handling design in SimplyHTML</a>' for additional details.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic45.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic45.htm
new file mode 100644
index 0000000..210be8b
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic45.htm
@@ -0,0 +1,64 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      The class SHTMLEditorKit
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">HTMLEditorKit</font>
+ in package <font face="'Courier New',Monospaced,Monospace">
+      javax.swing.text.html</font> automatically associates a <a href="../../../topic16/topic4/topic25/topic42.htm">
+style sheet</a> with any newly created <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>. The style sheet used is taken from the Java Runtime 
+      Environment and holds default styles for all possible HTML tags.
+    </p>
+    <p>
+      To use a different set of styles, we can either load another style sheet 
+      afterwards and delegate it to the <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> or we have to override this behaviour at its original 
+      location.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">SHTMLEditorKit</font>
+ overrides all methods in <font face="'Courier New',Monospaced,Monospace">
+      HTMLEditorKit</font> dealing with the default style sheet and uses our 
+      own set of styles.
+    </p>
+    <p class="heading2">
+      Method getStyleSheet
+    </p>
+    <p>
+      This method returns the style sheet found in field <font face="'Courier New',Monospaced,Monospace">
+defaultStyles</font> of <font face="'Courier New',Monospaced,Monospace">
+      SHTMLEditorKit</font>. If this field points to a <font face="'Courier New',Monospaced,Monospace">
+StyleSheet</font> object, this <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet</font> is returned.
+    </p>
+    <p>
+      If <font face="'Courier New',Monospaced,Monospace">defaultStyles</font> 
+      is not initialized so far, a new <font face="'Courier New',Monospaced,Monospace">
+StyleSheet</font> object is created. Then the default style sheet, identified 
+      by constant <font face="'Courier New',Monospaced,Monospace">DEFAULT_CSS</font>
+ , is located by calling method <font face="'Courier New',Monospaced,Monospace">
+getResourceAsStream</font> inherited from class <font face="'Courier New',Monospaced,Monospace">
+Class</font>. <font face="'Courier New',Monospaced,Monospace">
+      getResourceAsStream</font> looks for the style sheet file in the class 
+      path and returns an <font face="'Courier New',Monospaced,Monospace">
+      InputStream</font> for it if found.
+    </p>
+    <p>
+      A <a href="../../../topic16/topic4/topic25/topic42.htm">CSS</a> file '<font face="'Courier New',Monospaced,Monospace">
+default.css</font>' is distributed with the classes of application SimplyHTML 
+      so that it can be loaded as default in this way. A new <font face="'Courier New',Monospaced,Monospace">
+BufferedReader</font> is created which reads from a new <font face="'Courier New',Monospaced,Monospace">
+InputStreamReader</font> used on the <font face="'Courier New',Monospaced,Monospace">
+InputStream</font>. Method <font face="'Courier New',Monospaced,Monospace">
+      loadRules</font> of class <font face="'Courier New',Monospaced,Monospace">
+StyleSheet</font> then reads all styles from the <font face="'Courier New',Monospaced,Monospace">
+BufferedReader</font>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic46.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic46.htm
new file mode 100644
index 0000000..03201e6
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic46.htm
@@ -0,0 +1,67 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Style handling design in SimplyHTML
+    </p>
+    <p>
+      Java implements class <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet</font> to define central styles in <a href="../../../topic16/topic4/topic25/topic42.htm">
+CSS</a> notation for an <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font>. In addition styles in <a href="../../../topic16/topic4/topic25/topic42.htm">
+CSS</a> syntax can be included directly in <font face="'Courier New',Monospaced,Monospace">
+HTMLDocuments</font> by storing them as an attribute to a HTML tag.
+    </p>
+    <p>
+      In all Java versions up to J2SE 1.4 there is no way however, to store 
+      styles persistently although working with <font face="'Courier New',Monospaced,Monospace">
+HTMLDocuments</font> in Java would hardly work without styles. Applications 
+      creating <font face="'Courier New',Monospaced,Monospace">HTMLDocuments</font>
+ have to find a way to save styles on their own. SimplyHTML defines and uses 
+      an own class <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic48.htm">
+CSSWriter</a></font> for this matter.
+    </p>
+    <p class="heading2">
+      When are styles saved?
+    </p>
+    <p>
+      In stage 1 of application SimplyHTML styles can not be changed, so a 
+      style sheet is only <a href="../../../topic16/topic4/topic25/topic47.htm">
+saved</a>, when a newly created document is saved (i.e. the document was not 
+      loaded from a file and a style sheet with the same name does not exist 
+      at the target location for the document).
+    </p>
+    <p>
+      This leaves one conflict open:
+    </p>
+    <ul>
+      <li>
+        a style sheet exists at the location where a new document is to be 
+        saved and
+      </li>
+      <li>
+        the exisiting style sheet has the same name as the style sheet 
+        associated with the new document to be saved and
+      </li>
+      <li>
+        the exisiting style sheet is different from the style sheet associated 
+        with the new document
+      </li>
+    </ul>
+    <p>
+      In this case, the style sheet is not saved and the existing style sheet 
+      is used. A solution for this case is not implemented in SimplyHTML yet. 
+      A workaround for the time being is to save newly created documents in a 
+      directory which holds only documents sharing the default style sheet of 
+      SimplyHTML.
+    </p>
+    <p>
+      In later stages of SimplyHTML it will be possible to change styles. Then 
+      the association of style sheets and documents as well as the handling of 
+      saving style sheets will be refined.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic47.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic47.htm
new file mode 100644
index 0000000..2748b69
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic47.htm
@@ -0,0 +1,124 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Saving CSS style information
+    </p>
+    <p>
+      A style sheet is saved by application SimplyHTML with method <font face="'Courier New',Monospaced,Monospace">
+saveStyleSheet</font> in class <font face="'Courier New',Monospaced,Monospace">
+      DocumentPane</font>. This method is called by method <font face="'Courier New',Monospaced,Monospace">
+saveDocument</font> whenever a document is saved. To read more about HTML and 
+      style sheets in general and about how SimplyHTML uses style sheets, see 
+      chapters '<a href="../../../topic16/topic4/topic25/topic42.htm">Style 
+      sheets and HTML documents</a>' and '<a href="../../../topic16/topic4/topic25/topic46.htm">
+Style handling design in SimplyHTML</a>'.
+    </p>
+    <p class="heading2">
+      Method saveStyleSheet
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">saveStyleSheet</font>
+ first determines the file name of the style sheet associated with the 
+      document to be saved by calling mehtod <font face="'Courier New',Monospaced,Monospace">
+getStyleSheetName</font> (see below).
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">getStyleSheetName</font> 
+      returns the file name as a URL string. A <font face="'Courier New',Monospaced,Monospace">
+URL</font> object is created with that string and method <font face="'Courier New',Monospaced,Monospace">
+getFile</font> is called on that <font face="'Courier New',Monospaced,Monospace">
+URL</font> object to transform the URL string to a file string. This file 
+      string is taken to create a new <font face="'Courier New',Monospaced,Monospace">
+File</font> object for the style sheet to be saved.
+    </p>
+    <p>
+      With the <font face="'Courier New',Monospaced,Monospace">File</font> 
+      object it is first ensured that the file does not already exist with the 
+      help of method <font face="'Courier New',Monospaced,Monospace">
+      File.exists</font>. If it exists, the style sheet is not saved (see '<a href="../../../topic16/topic4/topic25/topic46.htm">
+Style handling design in SimlpyHTML</a>').
+    </p>
+    <p>
+      If the file does not exist, it is created by calling method <font face="'Courier New',Monospaced,Monospace">
+createNewFile</font> on the <font face="'Courier New',Monospaced,Monospace">
+      File</font> object. An <font face="'Courier New',Monospaced,Monospace">
+      OutputStream</font> object is opened on the newly created file and an <font face="'Courier New',Monospaced,Monospace">
+OutputStreamWriter</font> is created for that <font face="'Courier New',Monospaced,Monospace">
+OutputStream</font>.
+    </p>
+    <p>
+      If the document to be saved has been newly created, the <font face="'Courier New',Monospaced,Monospace">
+StyleSheet</font> object of <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic45.htm">
+SHTMLEditorKit</a></font> is taken to be written to file. If the document was 
+      loaded from file, the style sheet of the document is taken instead (the 
+      second case will not happen in stage 1 of SimplyHTML).
+    </p>
+    <p>
+      A new <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic48.htm">
+CSSWriter</a></font> object is created with that style sheet and the 
+      previously created <font face="'Courier New',Monospaced,Monospace">
+      Writer.</font> The style sheet is written to file by calling <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic25/topic48.htm">
+CSSWriter's</a></font> <font face="'Courier New',Monospaced,Monospace">write</font>
+ method. Once done, <font face="'Courier New',Monospaced,Monospace">
+      OutputStreamWriter</font> and <font face="'Courier New',Monospaced,Monospace">
+OutputStream</font> are closed.
+    </p>
+    <p class="heading2">
+      Method getStyleSheetName
+    </p>
+    <p>
+      A style sheet is saved at the location pointed to by the style sheet 
+      link reference of its associated document. The style sheet link 
+      reference usually is a relative expression containing the file name of 
+      the style sheet and an optional path which usually is a relative path.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">getStyleName</font>
+ returns the path and name of the style sheet by combining the document base 
+      (the path the document actually is stored at) and the (possibly 
+      relative) path and name of the style sheet reference.
+    </p>
+    <p>
+      First path and name of the style sheet as contained in the document's 
+      style sheet reference link is taken by calling method <font face="'Courier New',Monospaced,Monospace">
+getStyleRef</font> (see below). Then the document base is read with method <font face="'Courier New',Monospaced,Monospace">
+getBase</font> of class <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font>.
+    </p>
+    <p>
+      If a style sheet reference link is not found in the document, the 
+      default style sheet name is taken from class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorKit</font>. Finally a relative path possibly contained in the style 
+      sheet reference is resolved by method <font face="'Courier New',Monospaced,Monospace">
+resolveRelativePath</font> and the resulting name is returned.
+    </p>
+    <p class="heading2">
+      Method getStyleRef
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">getStyleRef</font>
+ , the first occurrence of a <font face="'Courier New',Monospaced,Monospace">
+      <link></font> tag is searched in the element tree of the document 
+      with the help of method <font face="'Courier New',Monospaced,Monospace">
+      findElement</font>. If a <font face="'Courier New',Monospaced,Monospace">
+      <link></font> tag is found, the <font face="'Courier New',Monospaced,Monospace">
+value</font> object of its <font face="'Courier New',Monospaced,Monospace">href</font>
+ attribute is copied to the local string variable <font face="'Courier New',Monospaced,Monospace">
+linkName</font>.
+    </p>
+    <p>
+      If no <font face="'Courier New',Monospaced,Monospace"><link></font>
+       tag is found or it does not contain a <font face="'Courier New',Monospaced,Monospace">
+href</font> attribute, <font face="'Courier New',Monospaced,Monospace">null</font>
+ is returned.
+    </p>
+    <p>
+      There is no implementation for the case that there is more than one link 
+      reference to style sheets.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic48.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic48.htm
new file mode 100644
index 0000000..f6c1ad9
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic25/topic48.htm
@@ -0,0 +1,122 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      The class CSSWriter
+    </p>
+    <p>
+      As mentioned <a href="../../../topic16/topic4/topic25/topic46.htm">
+      previously</a>, Java does not provide a class to save information in a <font face="'Courier New',Monospaced,Monospace">
+StyleSheet</font> to a file. To be able to save <a href="../../../topic16/topic4/topic25/topic42.htm">
+CSS</a> information, SimplyHTML defines and uses class <font face="'Courier New',Monospaced,Monospace">
+CSSWriter</font>. <font face="'Courier New',Monospaced,Monospace">CSSWriter</font>
+ is passed a <font face="'Courier New',Monospaced,Monospace">Writer</font> 
+      object and a <font face="'Courier New',Monospaced,Monospace">StyleSheet</font>
+ object upon construction. The <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet</font> object contains the <a href="../../../topic16/topic4/topic25/topic42.htm">
+CSS</a> information to be saved and the <font face="'Courier New',Monospaced,Monospace">
+Writer</font> object identifies the destination to store the <a href="../../../topic16/topic4/topic25/topic42.htm">
+CSS</a> information at.
+    </p>
+    <p>
+      In the constructor of <font face="'Courier New',Monospaced,Monospace">
+      CSSWriter</font>, the two parameters <font face="'Courier New',Monospaced,Monospace">
+Writer</font> and <font face="'Courier New',Monospaced,Monospace">StyleSheet</font>
+ are stored in respective fields <font face="'Courier New',Monospaced,Monospace">
+w</font> and <font face="'Courier New',Monospaced,Monospace">s</font> of class <font face="'Courier New',Monospaced,Monospace">
+CSSWriter</font> for later use. To actually write out the styles found in the <font face="'Courier New',Monospaced,Monospace">
+StyleSheet</font> <font face="'Courier New',Monospaced,Monospace">s</font>, 
+      method <font face="'Courier New',Monospaced,Monospace">write</font> is 
+      used.
+    </p>
+    <p class="heading2">
+      Method write
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">write</font> 
+      an <font face="'Courier New',Monospaced,Monospace">Enumeration</font> of 
+      all rules in the <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet</font> is created. An <font face="'Courier New',Monospaced,Monospace">
+Enumeration</font> is a good way to iterate over a collection of elements. It 
+      provides two convenience methods <font face="'Courier New',Monospaced,Monospace">
+hasMoreElements</font> and <font face="'Courier New',Monospaced,Monospace">
+      nextElement for </font><font face="Sans-Serif">this purpose</font>. 
+      While there are more Elements in the Enumeration of styles, method <font face="'Courier New',Monospaced,Monospace">
+write</font> gets the next element in the <font face="'Courier New',Monospaced,Monospace">
+Enumeration</font> being the name of the next <font face="'Courier New',Monospaced,Monospace">
+Style</font> object.
+    </p>
+    <p>
+      It then gets the <font face="'Courier New',Monospaced,Monospace">Style</font>
+ object identified by that name. <font face="'Courier New',Monospaced,Monospace">
+Style</font> objects are <font face="'Courier New',Monospaced,Monospace">
+      AttributeSet</font> objects that can contain attribute objects or other <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> objects. The length of the style name is taken to find out 
+      how far from the left side the style attributes have to be written to 
+      file. This indentation length is stored in field <font face="'Courier New',Monospaced,Monospace">
+indentLen</font> of class <font face="'Courier New',Monospaced,Monospace">
+      CSSWriter</font>.
+    </p>
+    <p>
+      First the style name is written to file followed by the character 
+      opening a collection of attributes for a CSS style ( '{' ). Every style 
+      except the one identified by <font face="'Courier New',Monospaced,Monospace">
+StyleContext.DEFAULT_STYLE</font> then is written to file by calling method <font face="'Courier New',Monospaced,Monospace">
+writeStyle</font> on respective <font face="'Courier New',Monospaced,Monospace">
+Style</font> object.
+    </p>
+    <p class="heading2">
+      Method writeStyle
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">writeStyle</font>
+ again an <font face="'Courier New',Monospaced,Monospace">Enumeration</font> 
+      is used to go through all attributes found in the style <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font>. An <font face="'Courier New',Monospaced,Monospace">
+      AttributeSet</font> is a pair of objects for the key and the value of a 
+      style attribute. For every element in the <font face="'Courier New',Monospaced,Monospace">
+Enumeration</font> the key and value objects are read.
+    </p>
+    <p>
+      Attribute <font face="'Courier New',Monospaced,Monospace">
+      StyleConstants.NameAttribute</font> can be left out from writing because 
+      it contains the name of the style, this <font face="'Courier New',Monospaced,Monospace">
+Style</font> object is describing. As well the attribute <font face="'Courier New',Monospaced,Monospace">
+StyleConstants.ResolveAttribute</font> is not written to file itself, because 
+      it contains another <font face="'Courier New',Monospaced,Monospace">
+      AttributeSet</font> in its value object. For attributes of type <font face="'Courier New',Monospaced,Monospace">
+StyleConstants.ResolveAttribute</font> method <font face="'Courier New',Monospaced,Monospace">
+writeStyle</font> is called recursively to write out all attributes found in 
+      this attribute.
+    </p>
+    <p>
+      All other attributes are written to file by first writing the key object 
+      having the name of the attribute (such as font-size, left-margin, etc.) 
+      followed by a colon, the attribute value (such as '12pt' or '20%', etc.) 
+      and a semicolon. Every attribute except the first is preceded by a new 
+      line and the indentation needed to make the collection of attributes 
+      more legible.
+    </p>
+    <p>
+      Finally the closing character for a CSS style ( '}' ) and a new line is 
+      written.
+    </p>
+    <p class="heading3">
+      Using the appropriate line separator
+    </p>
+    <p>
+      At design time it can not be predicted on which operating system 
+      application SimplyHTML might be used. As different operating systems use 
+      different line separators with their file system, this has to be taken 
+      into account for our save routine. <font face="'Courier New',Monospaced,Monospace">
+CSSWriter</font> gets the correct line separator from a global constant 
+      defined in Java with command <font face="'Courier New',Monospaced,Monospace">
+System.getProperty("line.separator")</font>. The value returned by 
+      this call is appended to every line written to the target style sheet 
+      file.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic39.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39.htm
new file mode 100644
index 0000000..8c6160d
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39.htm
@@ -0,0 +1,26 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Documenting the application
+    </p>
+    <p>
+      Designing and developing an application can be hard work already. But 
+      the resulting solution is nothing without proper documentation.
+    </p>
+    <p>
+      Documentation starts at providing information about the name of the 
+      application or license and copyright notices and goes all the way 
+      through installation guidelines to a user manual, tutorial and 
+      information for developers.
+    </p>
+    <p>
+      Most of the time, documenting an application is at least as much the 
+      work as developing it. This section shall give some hints about how a 
+      proper documentation can be accomplished.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic40.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic40.htm
new file mode 100644
index 0000000..28917af
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic40.htm
@@ -0,0 +1,80 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating an 'About dialog'
+    </p>
+    <p>
+      An elementary part of an application is its 'about' dialog. An 'about 
+      dialog' usually is shown when the user likes to know which application 
+      is currently running, by whom it was created, which version the user 
+      operates, which terms and conditions are connected to usage, etc.
+    </p>
+    <p>
+      It is common practice to have an item in the help menu of an application 
+      such as 'About SimplyHTML' for this purpose. This menu item in 
+      application SimplyHTML creates an instance of its <font face="'Courier New',Monospaced,Monospace">
+AboutBox</font> class.
+    </p>
+    <p class="heading2">
+      Class AboutBox
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">AboutBox</font> 
+      descends from class <font face="'Courier New',Monospaced,Monospace">
+      JDialog</font> and hosts a number of information panels. In the upper 
+      left part, an image associated with the application is shown (see 
+      below). Next to the image on the right a number of <font face="'Courier New',Monospaced,Monospace">
+JLabels</font> have the application name, current release, the author (wow, 
+      that's me!) and the application's home page. The name of the application 
+      is taken from the constant <font face="'Courier New',Monospaced,Monospace">
+APP_NAME</font> of class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font>.
+    </p>
+    <p>
+      Below these components, a <a href="../../../topic16/topic4/topic39/topic51.htm">
+license panel</a> shows the full text of the <a href="../../../topic1/topic5.htm">
+GNU General Public License</a> SimplyHTML is distributed under. Finally a 
+      close button is displayed at the bottom of the dialog.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">AboutBox</font> does not 
+      have any other function than to construct itself and to be shown for 
+      information. Once the close button is pressed, it is disposed properly. 
+      This is ensured by overriding method <font face="'Courier New',Monospaced,Monospace">
+processWindowEvent</font> and calling <font face="'Courier New',Monospaced,Monospace">
+enableEvents</font> in the constructor of <font face="'Courier New',Monospaced,Monospace">
+AboutBox</font>.
+    </p>
+    <p class="heading3">
+      Reading an image from the class path
+    </p>
+    <p>
+      A common way to display an image is to place a JLabel somewhere onto a 
+      visible component and associate an image to it. <font face="'Courier New',Monospaced,Monospace">
+JLabel</font> has a constructor especially for that, which accepts an <font face="'Courier New',Monospaced,Monospace">
+ImageIcon</font> object as a parameter. The image is taken from the class path 
+      of application SimplyHTML, where file '<font face="'Courier New',Monospaced,Monospace">
+App.jpg</font>' is distributed together with the applciation's classes in 
+      subdirectory '<font face="'Courier New',Monospaced,Monospace">image</font>
+ '.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">getResource</font>
+       in the <font face="'Courier New',Monospaced,Monospace">Class</font> 
+      object of respective <font face="'Courier New',Monospaced,Monospace">
+      JLabel</font> is used to create an <font face="'Courier New',Monospaced,Monospace">
+ImageIcon</font> object for file '<font face="'Courier New',Monospaced,Monospace">
+App.jpg</font>'. Using the command <font face="'Courier New',Monospaced,Monospace">
+this.getClass.getResource("image/App.jpg")</font> gets the class 
+      object of this <font face="'Courier New',Monospaced,Monospace">JLabel</font>
+ object and finds out from where it was loaded. Calling <font face="'Courier New',Monospaced,Monospace">
+getResource</font> on this <font face="'Courier New',Monospaced,Monospace">
+      Class</font> object resolves the name given as a parameter to <font face="'Courier New',Monospaced,Monospace">
+getResource</font> as a relative path to the path where the class was found.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic43.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic43.htm
new file mode 100644
index 0000000..04e98d1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic43.htm
@@ -0,0 +1,104 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Adding online help
+    </p>
+    <p>
+      Once an application is started by the user it is most convenient to 
+      provide information and help directly out of that application. With 
+      JavaHelp technology the Java language has an extension for online help 
+      which any application can use to seamlessly incorporate documentation.
+    </p>
+    <p class="heading2">
+      JavaHelp extension
+    </p>
+    <p>
+      JavaHelp extends the Java Runtime Environment in the way that it 
+      provides a specification and platform to display any kind of 
+      documentation. All Information presented in JavaHelp is stored in HTML 
+      files. Table of contents, index and map are XML files all wrapped 
+      together with the HTML topic files into a framework of classes to view 
+      and query the information through a common user interface.
+    </p>
+    <p>
+      Unfortunately the JavaHelp extension is not a part of the core Java 
+      Runtime Environment (JRE) so the extension has to be applied manually by 
+      coping the extension file for JavaHelp into the extensions directory of 
+      the JRE.
+    </p>
+    <p class="heading3">
+      How to use JavaHelp in an application
+    </p>
+    <p>
+      Once a JavaHelp documentation is set up by creating HTML documents, 
+      table of contents, index and map files and the JavaHelp extension is 
+      available to the JRE, displaying JavaHelp documentation simply is done 
+      by creating a <font face="'Courier New',Monospaced,Monospace">HelpSet</font>
+ object for the corresponding help set and display it with an instance of <font face="'Courier New',Monospaced,Monospace">
+HelpBroker</font>.
+    </p>
+    <p>
+      More about the JavaHelp specification and technology is available at
+    </p>
+    <p>
+      <font color="#3366ff">http://java.sun.com/products/javahelp</font>
+    </p>
+    <p class="heading2">
+      How help is created for SimplyHTML
+    </p>
+    <p>
+      All documentation is stored in a single JavaHelp help set in directory <font face="'Courier New',Monospaced,Monospace">
+help</font> of the SimplyHTML class path (<font face="'Courier New',Monospaced,Monospace">
+source/com/lightdev/app/shtm/help</font>). The help set is the one you are 
+      currently reading. It was produced entirely with the Java application 
+      HelpExpert. HelpExpert is created by the author of SimplyHTML (hey, 
+      that's me again!) and is available at
+    </p>
+    <p>
+      <font color="#3366ff">http://www.calcom.de/eng/product/hlpex.htm</font>
+    </p>
+    <p class="heading2">
+      How help is implemented in SimplyHTML
+    </p>
+    <p>
+      A common practice is to deliver documentation through menu 'Help'. 
+      Consequently SimplyHTML has an item 'Help Topics' in the 'Help' menu 
+      linking to this help set. In stage 1 the link was performed by <font face="'Courier New',Monospaced,Monospace">
+SHTMLHelpShowContentsAction</font>. This has been refined to now being handled 
+      in method <font face="'Courier New',Monospaced,Monospace">initJavaHelp</font>
+ of class <font face="'Courier New',Monospaced,Monospace">FrmMain</font>.
+    </p>
+    <p class="heading3">
+      Method initJavaHelp
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">initJavaHelp</font>
+ an instance of a <font face="'Courier New',Monospaced,Monospace">HelpBroker</font>
+ is created pointing to the JavaHelp version of this tutorial (included in the 
+      Java archive (JAR) file of SimplyHTML). A reference to this <font face="'Courier New',Monospaced,Monospace">
+HelpBroker</font> is kept for later use. Then class <font face="'Courier New',Monospaced,Monospace">
+FrmMain's</font> instance of class <font face="'Courier New',Monospaced,Monospace">
+DynamicResource</font> is used to get the menu item meant for displaying the 
+      application's online help topics overview.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">CSH</font> (for 
+      context sensitive help) of the JavaHelp API is used to create an <font face="'Courier New',Monospaced,Monospace">
+ActionListener</font> responsible to display context sensitive help on 
+      occurrence of a given action (selecting the 'Help contents' menu item in 
+      this case). This <font face="'Courier New',Monospaced,Monospace">
+      ActionListener</font> is registered with the menu item.
+    </p>
+    <p>
+      <b>Important</b>: A 'readme' document should always be distributed with 
+      an application as <i>plain text file</i>. The readme file should contain 
+      essential information to properly set up and run the application. If all 
+      other tools fail, at least the user can be referred to this file to 
+      start with.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic44.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic44.htm
new file mode 100644
index 0000000..1ec3cde
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic44.htm
@@ -0,0 +1,36 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating source code documentation
+    </p>
+    <p>
+      Source codes usually are documented by comments inserted at positions in 
+      the code where the author thought an explanation of what is done there 
+      might be needed or otherwise helpful.
+    </p>
+    <p>
+      If such comments are created following a certain syntax, they can be 
+      translated to a set of API documentation files in HTML with the Javadoc 
+      tool of the Java Software Development Kit. For details about Javadoc 
+      please refer to page 'Javadoc 1.4 Tool' at <font color="#3333ff">
+      http://java.sun.com/j2se/1.4/docs/tooldocs/javadoc/index.html</font>
+    </p>
+    <p>
+      Generally it is a good idea and common practice to comment Java source 
+      codes following Javadoc syntax as almost automatically there will be a 
+      very transparent and thorough documentation of the sources openly 
+      viewable with nothing more than a browser.
+    </p>
+    <p>
+      With application SimplyHTML this has been done too, so there is a set of 
+      API documentation files in directory <font face="'Courier New',Monospaced,Monospace">
+doc</font> of the <a href="../../../topic1/topic24.htm">SimplyHTML 
+      distribution package</a>. By opening file <font face="'Courier New',Monospaced,Monospace">
+index.html</font> the documentation can be viewed with any browser.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic51.htm b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic51.htm
new file mode 100644
index 0000000..e6920b7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic4/topic39/topic51.htm
@@ -0,0 +1,65 @@
+<html>
+  <head>
+    <link href="../../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      The class LicensePane
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">LicensePane</font> 
+      extens class <font face="'Courier New',Monospaced,Monospace">JPanel</font>
+ by adding a <font face="'Courier New',Monospaced,Monospace">JTextArea</font> 
+      and a <font face="'Courier New',Monospaced,Monospace">JScrollPane</font> 
+      to it. The <font face="'Courier New',Monospaced,Monospace">JTextArea</font>
+ is used to display the full text of the <a href="../../../topic1/topic5.htm">
+      GNU General Public License</a>. By wrapping this functionality into a 
+      separate class it is easier for other classes such as <font face="'Courier New',Monospaced,Monospace"><a href="../../../topic16/topic4/topic39/topic40.htm">
+AboutBox</a></font> to show that info text.
+    </p>
+    <p class="heading2">
+      Constructing a LicensePane
+    </p>
+    <p>
+      The constructor takes a <font face="'Courier New',Monospaced,Monospace">
+      Dimension</font> object to determine the preferred size of the panel to 
+      be constructed. In the constructor a new non-editable <font face="'Courier New',Monospaced,Monospace">
+JTextArea</font> is created with the license text to be displayed as a 
+      parameter. The license text is delivered by method <font face="'Courier New',Monospaced,Monospace">
+getLicenseText</font> (see below). A new <font face="'Courier New',Monospaced,Monospace">
+JScrollPane</font> is created and the <font face="'Courier New',Monospaced,Monospace">
+JTextArea</font> is associated with it. The vertical and horizontal scroll bar 
+      are set to be displayed as needed.
+    </p>
+    <p>
+      Finally the <font face="'Courier New',Monospaced,Monospace">JScrollPane</font>
+ containing the <font face="'Courier New',Monospaced,Monospace">JTextArea</font>
+ is added to the <font face="'Courier New',Monospaced,Monospace">LicensePane</font>
+ and the license text is scrolled to the top with method <font face="'Courier New',Monospaced,Monospace">
+setCaretPosition</font>.
+    </p>
+    <p class="heading2">
+      Method getLicenseText
+    </p>
+    <p>
+      The license text is taken from file '<font face="'Courier New',Monospaced,Monospace">
+gpl.txt</font>' delivered in the class path of the <a href="../../../topic1/topic24.htm">
+distribution</a> of SimplyHTML. Method <font face="'Courier New',Monospaced,Monospace">
+getResourceAsStream</font> is used to locate the file and to open an <font face="'Courier New',Monospaced,Monospace">
+InputStream</font> object to it. An <font face="'Courier New',Monospaced,Monospace">
+InputStreamReader</font> is created on that <font face="'Courier New',Monospaced,Monospace">
+InputStream</font> and the <font face="'Courier New',Monospaced,Monospace">
+      InputStreamReader</font> is used to create a <font face="'Courier New',Monospaced,Monospace">
+BufferedReader</font>.
+    </p>
+    <p>
+      As long as lines are found in '<font face="'Courier New',Monospaced,Monospace">
+gpl.txt</font>' they are read and appended to a <font face="'Courier New',Monospaced,Monospace">
+StringBuffer</font>. Finally the readers are closed properly and the contents 
+      of the <font face="'Courier New',Monospaced,Monospace">StringBuffer</font>
+ are returned as a <font face="'Courier New',Monospaced,Monospace">String</font>
+ .
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62.htm b/src/com/lightdev/app/shtm/help/topic16/topic62.htm
new file mode 100644
index 0000000..f9c3ed1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62.htm
@@ -0,0 +1,28 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 2: Resource bundles and common edit functions
+    </p>
+    <p>
+      While <a href="../topic16/topic4.htm">stage 1</a> has been a comparably 
+      big step, stage 2 will be more concise. Here we have a look on how to 
+      add resource bundles to a Java application and how they can be used. As 
+      well we will add edit functions common to most applications:
+    </p>
+    <ul>
+      <li>
+        cascading undo and redo,
+      </li>
+      <li>
+        cut and paste and
+      </li>
+      <li>
+        drag and drop
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic63.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic63.htm
new file mode 100644
index 0000000..289bf6e
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic63.htm
@@ -0,0 +1,49 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Typical undo/redo parts
+    </p>
+    <p>
+      In the Java language undo/redo support is made availabe to all text 
+      components through a common set of parts, which can be used almost 
+      simliarly between different applications dealing with text processing.
+    </p>
+    <p class="heading2">
+      UndoManager
+    </p>
+    <p>
+      An <font face="'Courier New',Monospaced,Monospace">UndoManager</font> 
+      'remembers' undoable edit acionst. It is the central place to store such 
+      edit actions for later use in a possible undo/redo action.
+    </p>
+    <p class="heading2">
+      UndoableEditListener
+    </p>
+    <p>
+      For being able to store undoable edit actions a class has to implement 
+      the <font face="'Courier New',Monospaced,Monospace">UndoableEditListener</font>
+ interface. By implementing this interface, an object can register itself with 
+      any <font face="'Courier New',Monospaced,Monospace">Document</font> 
+      whose undoable edit events it likes to handle.
+    </p>
+    <p>
+      By listening to undoable edit events, a class acting as an <font face="'Courier New',Monospaced,Monospace">
+UndoableEditListener</font> can as well update GUI elements according to the 
+      undoable edit events received.
+    </p>
+    <p class="heading2">
+      Undo and redo actions
+    </p>
+    <p>
+      To actually undo or redo an undoable edit, actions are used as a common 
+      way to make an undo or redo command available on the GUI. These actions 
+      call <font face="'Courier New',Monospaced,Monospace">UndoManager</font> 
+      methods to undo or redo an undoable edit. As well the actions can be 
+      used to adapt the GUI according to the current undo/redo state.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic64.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic64.htm
new file mode 100644
index 0000000..cd3ad53
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic64.htm
@@ -0,0 +1,79 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      How undo and redo work in SimplyHTML
+    </p>
+    <p>
+      Currently, only the<font face="'Courier New',Monospaced,Monospace"> 
+      Document</font> class offers undo and redo support to text components. 
+      For any edit action that can be cancelled and reinstated again in a 
+      particular <font face="'Courier New',Monospaced,Monospace">Document</font>
+ , the <font face="'Courier New',Monospaced,Monospace">Document</font> sends 
+      undoable edit events to all <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic62/topic63.htm">
+UndoableEditListeners</a></font> registered with that <font face="'Courier New',Monospaced,Monospace">
+Document</font>.
+    </p>
+    <p class="heading2">
+      Creating an UndoManager
+    </p>
+    <p>
+      To store undoable edit actions for later use in a possible undo or redo 
+      action, class <font face="'Courier New',Monospaced,Monospace">FrmMain</font>
+ creates an instance of class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic62/topic63.htm">
+UndoManager</a></font>. The object is stored in private field <font face="'Courier New',Monospaced,Monospace">
+undo</font> of class <font face="'Courier New',Monospaced,Monospace">FrmMain</font>
+ for later use in the undo/redo implementation.
+    </p>
+    <p class="heading2">
+      Defining and registering an UndoableEditListener
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      also defines an inner class <font face="'Courier New',Monospaced,Monospace">
+UndoHandler</font> that implements the <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic62/topic63.htm">
+UndoableEditListener</a></font> interface. In its method <font face="'Courier New',Monospaced,Monospace">
+undoableEditHappened</font> it stores undoable edit actions in the previously 
+      created <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic62/topic63.htm">
+UndoManager</a></font>. As well, <font face="'Courier New',Monospaced,Monospace">
+UndoHandler</font> updates the GUI whenever an undoable edit event is received.
+    </p>
+    <p>
+      The <font face="'Courier New',Monospaced,Monospace">UndoHandler</font> 
+      of <font face="'Courier New',Monospaced,Monospace">FrmMain</font> is 
+      registered with any<font face="'Courier New',Monospaced,Monospace"> 
+      Document</font> created or opened by SimplyHTML in the respective 
+      actions <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic20/topic28.htm">
+SHTMLFileOpenAction</a></font> and <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic4/topic20/topic28.htm">
+SHTMLFileNewAction</a></font>. Consequently <font face="'Courier New',Monospaced,Monospace">
+UndoHandler</font> is properly removed from any open <font face="'Courier New',Monospaced,Monospace">
+Document</font> before it is closed to ensure proper cleanup of the disposed <font face="'Courier New',Monospaced,Monospace">
+Document</font> in the garbage collection.
+    </p>
+    <p class="heading2">
+      Defining actions for undo and redo
+    </p>
+    <p>
+      To finally being able to perform an undo or redo command, either through 
+      the menu or from other places such as a tool bar, class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> defines two actions <font face="'Courier New',Monospaced,Monospace">
+UndoAction</font> and <font face="'Courier New',Monospaced,Monospace">
+      RedoAction</font>.
+    </p>
+    <p>
+      In their <font face="'Courier New',Monospaced,Monospace">actionPerformed</font>
+ methods <font face="'Courier New',Monospaced,Monospace">UndoAction</font> and <font face="'Courier New',Monospaced,Monospace">
+RedoAction</font> call methods<font face="'Courier New',Monospaced,Monospace"> 
+      undo</font> and <font face="'Courier New',Monospaced,Monospace">redo</font>
+ of <font face="'Courier New',Monospaced,Monospace">FrmMain's</font> <font face="'Courier New',Monospaced,Monospace">
+UndoManager</font> accordingly. In addition they both have a method <font face="'Courier New',Monospaced,Monospace">
+update</font> to bring their GUI representation in line with the current undo 
+      state (being enabled or not depending on whether or not undoable edits 
+      are present in the<font face="'Courier New',Monospaced,Monospace"> 
+      UndoManager</font>, that is).
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic65.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic65.htm
new file mode 100644
index 0000000..58d7119
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic65.htm
@@ -0,0 +1,65 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Cut and paste mechanism in Java
+    </p>
+    <p>
+      Cut and paste uses the clipboard to copy a certain part of a document. 
+      Data is transferred from one part of a document to the clipboard and 
+      later it is transferred from the clipboard to another place of this or 
+      another cocument.
+    </p>
+    <p class="heading2">
+      Cut, copy and paste actions and methods
+    </p>
+    <p>
+      In the <font face="'Courier New',Monospaced,Monospace">javax.swing 
+      packages</font> there are predefined actions one can use to add cut and 
+      paste to an application in an 'Edit' menu for instance. <font face="'Courier New',Monospaced,Monospace">
+DefaultEditorKit.CutAction</font>, <font face="'Courier New',Monospaced,Monospace">
+DefaultEditorKit.CopyAction</font> and <font face="'Courier New',Monospaced,Monospace">
+DefaultEditorKit.PasteAction</font> already deliver functionality by calling a 
+      target object's <font face="'Courier New',Monospaced,Monospace">cut</font>
+ , <font face="'Courier New',Monospaced,Monospace">copy</font> and <font face="'Courier New',Monospaced,Monospace">
+paste</font> methods.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">JTextComponent</font>
+ , which is a superclass to <font face="'Courier New',Monospaced,Monospace">
+      JEditorPane</font>, in turn implements these methods to perform the 
+      actual cut and paste on a <font face="'Courier New',Monospaced,Monospace">
+Document</font> connected to that <font face="'Courier New',Monospaced,Monospace">
+JTextComponent</font>.
+    </p>
+    <p class="heading2">
+      How data is transported
+    </p>
+    <p>
+      To be able to transport data regardless of its type, the Java language 
+      has an object <font face="'Courier New',Monospaced,Monospace">
+      Transferable</font> which one has to use or design to certain needs. <font face="'Courier New',Monospaced,Monospace">
+Transferables</font> make use of <font face="'Courier New',Monospaced,Monospace">
+DataFlavors</font> to inform about the data types they support. Transport of <font face="'Courier New',Monospaced,Monospace">
+Transferables</font> in cut and paste operations is done through <font face="'Courier New',Monospaced,Monospace">
+Clipboard</font> objects.
+    </p>
+    <p class="heading2">
+      Extending the mechanism
+    </p>
+    <p>
+      Unfortunately this mechanism is not extended by class <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font> for the transport of HTML during cut and paste operations. <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font> is limited to plain text in cut and paste operations even 
+      when its content type is set to <font face="'Courier New',Monospaced,Monospace">
+text/html</font>. SimplyHTML therefore extends <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font> with class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic62/topic69.htm">
+SHTMLEditorPane</a></font> overriding its cut, copy and paste methods so that 
+      cut and paste <i>including</i> styles and HTML specific parts is 
+      possible.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic66.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic66.htm
new file mode 100644
index 0000000..13141f7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic66.htm
@@ -0,0 +1,66 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Adding an edit menu
+    </p>
+    <p>
+      With the functions describing <a href="../../topic16/topic62/topic69.htm">
+cut and paste</a> and <a href="../../topic16/topic62/topic64.htm">undo/redo</a>
+       in previous chapters we finally have what we need to add common edit 
+      functionality to SimplyHTML and to make it available on the GUI.
+    </p>
+    <p>
+      The edit menu is easily built by adding a new menu definition to our 
+      resource bundles: Just a few lines of text describing the new menu and 
+      its menu items. The entries in the resource bundle look as follows
+    </p>
+    <p>
+      
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace"># edit menu definition </font>
+
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace">edit=undo redo - cut 
+      copy paste </font>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace">editLabel=Edit </font>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace"># edit menu items </font>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace">undoLabel=Undo </font>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace">redoLabel=Redo </font>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace">cutLabel=Cut </font>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace">copyLabel=Copy </font>
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace">pasteLabel=Paste</font>
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Once above text is added to file SimplyHTML.propertiers, construction of 
+      the menu as well as proper connection to actions and functionality to 
+      enable/disable the menu items is created automatically by the <a href="../../topic16/topic62/topic68.htm">
+dynamic menu functionality</a> of SimplyHTML.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic67.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic67.htm
new file mode 100644
index 0000000..6298043
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic67.htm
@@ -0,0 +1,50 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using resource bundles
+    </p>
+    <p>
+      Resources are simply text files that are accessible to an application. 
+      The text files contain information in the format
+    </p>
+    <p style=" font-family:Arial,Sans-Serif; margin-left:20pt; font-size:12pt; color:#000000; margin-top:6pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;">
+      <font face="'Courier New',Monospaced,Monospace">key=value</font>
+    </p>
+    <p>
+      and usually are distributed in the path the application classes are 
+      located. Class <font face="'Courier New',Monospaced,Monospace">
+      java.util.ResourceBundle</font> makes available the data to an 
+      application. Applications read constants or parameters at runtime 
+      through methods of class <font face="'Courier New',Monospaced,Monospace">
+      ResourceBundle</font>.
+    </p>
+    <p class="heading2">
+      Why using resources?
+    </p>
+    <p>
+      Using resources has the following advantages
+    </p>
+    <p>
+      <b>Maintenance</b>: text constants and parameters can be maintained 
+      outside the source code. Changing a text constant or parameter does not 
+      require code changes. Information is stored in a central place. If a 
+      change is necessary, respective part has not to be searched in the whole 
+      source code. Constants have to be changed in only one place regardless 
+      of whether they are used in multiple places in the source code.
+    </p>
+    <p>
+      <b><a href="../../topic16/topic62/topic70.htm">Internationalization</a></b>
+ : Resources can be replaced in one step without code changes making it easy 
+      to switch an application to another language.
+    </p>
+    <p>
+      <b><a href="../../topic16/topic62/topic68.htm">Control</a></b>: Parts of 
+      the application can be controlled dynamically through parameters in a 
+      resource file rather than having to 'hard wire' them.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic68.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic68.htm
new file mode 100644
index 0000000..183d285
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic68.htm
@@ -0,0 +1,126 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a dynamic menu
+    </p>
+    <p>
+      In <a href="../../topic16/topic4.htm">stage 1</a> of SimplyHTML the menu 
+      consisting of menu bar, menus and menu items had been hard coded in 
+      method constructMenu. This part would always have to be changed when the 
+      menu changes or is extended by additional functions. In stage 2 of the 
+      application we therefore add functionality to build a menu dynamically 
+      controlled by parameters from a resource file.
+    </p>
+    <p class="heading3">
+      Connect actions dynamically
+    </p>
+    <p>
+      Certainly actions triggered by menu selections still have to be coded 
+      also because they contain the actual functionality in most cases. But 
+      how actions are connected to menu items or other GUI elements does not 
+      have to be hard coded and therefore actions are included in the change 
+      towards a dynamic menu.
+    </p>
+    <p class="heading3">
+      Advantage
+    </p>
+    <p>
+      By having functions to dynamically construct and control a menu, the 
+      code does not have to be changed again once a new menu is to be added or 
+      changes in the menu structure occur.
+    </p>
+    <p>
+      Menus and menu items can be added simply by making an entry in the 
+      resource file.
+    </p>
+    <p class="heading2">
+      How to automate the menu construction
+    </p>
+    <p>
+      Each action has a name which we use as unique key, such as <font face="'Courier New',Monospaced,Monospace">
+new</font>, <font face="'Courier New',Monospaced,Monospace">open</font>, <font face="'Courier New',Monospaced,Monospace">
+save</font>, etc. In class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain's</font> constructor a <font face="'Courier New',Monospaced,Monospace">
+commands</font> <font face="'Courier New',Monospaced,Monospace">Hashtable</font>
+ is created with all actions of SimplyHTML and their action commands (<font face="'Courier New',Monospaced,Monospace">
+new</font>, <font face="'Courier New',Monospaced,Monospace">save</font>, 
+      etc.). With method <font face="'Courier New',Monospaced,Monospace">
+      getAction</font>, an action can be fetched by its command name.
+    </p>
+    <p class="heading3">
+      Method createMenuBar
+    </p>
+    <p>
+      To create the menu bar a menu bar definition string from the resource 
+      file is read having the key for each menu delimited by blanks (e.g. file 
+      edit help). The keys are in the order as menus shall appear in the menu 
+      bar.
+    </p>
+    <p class="heading3">
+      Method createMenu
+    </p>
+    <p>
+      To create menus a menu definition string from the resource file is read 
+      having the action key for each menu item delimited by blanks. The keys 
+      are in the order as items shall appear in respective menu.
+    </p>
+    <p class="heading3">
+      Method createMenuItem
+    </p>
+    <p>
+      Menu items are created with the key to 'their' action (new, save, etc.) 
+      as the action command<font face="'Courier New',Monospaced,Monospace">.</font><font face="Sans-Serif">
+ The key also serves to get the label for the menu item: In the resource file 
+      all menu labels are named </font><font face="'Courier New',Monospaced,Monospace">
+fileLabel</font><font face="Sans-Serif">, </font><font face="'Courier New',Monospaced,Monospace">
+newLabel</font><font face="Sans-Serif">, </font><font face="'Courier New',Monospaced,Monospace">
+saveLabel</font><font face="Sans-Serif">, etc. so they can be read 
+      automatically and stored with the menu item. </font>
+    </p>
+    <p class="heading2">
+      <font face="Sans-Serif">Consistent state handling over components </font>
+    </p>
+    <p>
+      <font face="Sans-Serif">Menu items always should reflect if their action 
+      is available at a certain point in time during execution of an 
+      application. Actions in turn should only be available if it makes sense 
+      at that point in time. Action close for instance should only be enabled, 
+      if there are documents open, that can be closed. </font>
+    </p>
+    <p class="heading3">
+      Listeners for interaction between menus, menu items and actions
+    </p>
+    <p>
+      <font face="Sans-Serif">A reference between menus, menu items and 
+      actions is created in several ways to ensure this behaviour: </font>
+    </p>
+    <ul>
+      <li>
+        <font face="Sans-Serif">The menu item is connected to a </font><font face="'Courier New',Monospaced,Monospace">
+PropertyChangeListener</font><font face="Sans-Serif"> and registered with the 
+        action belonging to that menu item to automatically update the state 
+        of the menu item according to the state of the action.</font>
+      </li>
+      <li>
+        <font face="Sans-Serif">The action in turn is registered with the menu 
+        item as an </font><font face="'Courier New',Monospaced,Monospace">
+        ActionListener</font><font face="Sans-Serif"> so that the action can 
+        execute its </font><font face="'Courier New',Monospaced,Monospace">
+        actionPerformed</font><font face="Sans-Serif"> method whenever the 
+        menu item fires the action command.</font>
+      </li>
+      <li>
+        <font face="Sans-Serif">Finally with each menu a </font><font face="'Courier New',Monospaced,Monospace">
+MenuListener</font><font face="Sans-Serif"> is registered that updates the 
+        action state of each item in respective menu whenever it is about to 
+        be displayed. This ensures that always the actions are in the correct 
+        state. (In later stages, this has to be refined by updating controls 
+        other than menus if such are connected to actions in addition.)</font>
+      </li>
+    </ul>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic69.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic69.htm
new file mode 100644
index 0000000..f4fef93
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic69.htm
@@ -0,0 +1,96 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      How cut and paste work in SimplyHTML
+    </p>
+    <p>
+      To allow cut and paste for content <i>including</i> styles and all HTML 
+      specific parts SimplyHTML extends the <a href="../../topic16/topic62/topic65.htm">
+cut and paste mechanis of Java</a>. It defines two classes to enable the 
+      transport of HTML data and extends <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font> to use SimplyHTML's classes instead of the standard ones.
+    </p>
+    <p class="heading2">
+      Class HTMLText
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">HTMLText</font> 
+      represents a portion of HTML content. It has field <font face="'Courier New',Monospaced,Monospace">
+htmlText</font> for the HTML code representing the content and field <font face="'Courier New',Monospaced,Monospace">
+plainText</font> to represent the content as plain text. With methods <font face="'Courier New',Monospaced,Monospace">
+copyHTML</font> and <font face="'Courier New',Monospaced,Monospace">pasteHTML</font>
+ it enables transport of HTML data into and out of <font face="'Courier New',Monospaced,Monospace">
+HTMLText</font> objects.
+    </p>
+    <p class="heading3">
+      Transport mechanism
+    </p>
+    <p>
+      To transport HTML text methods <font face="'Courier New',Monospaced,Monospace">
+copyHTML</font> and <font face="'Courier New',Monospaced,Monospace">pasteHTML</font>
+ use <font face="'Courier New',Monospaced,Monospace">HTMLEditorKit's</font> <font face="'Courier New',Monospaced,Monospace">
+read</font> and <font face="'Courier New',Monospaced,Monospace">write</font> 
+      methods, which allow to read or write a portion of a <font face="'Courier New',Monospaced,Monospace">
+Document's</font> content as HTML code using a <font face="'Courier New',Monospaced,Monospace">
+Writer</font>. By taking a <font face="'Courier New',Monospaced,Monospace">
+      StringWriter</font>, data can be transferred into a <font face="'Courier New',Monospaced,Monospace">
+String</font> for temporary storage inside a <font face="'Courier New',Monospaced,Monospace">
+HTMLText</font> object.
+    </p>
+    <p class="heading3">
+      Different mechanism within one paragraph
+    </p>
+    <p>
+      When copying and pasting text within one paragraph, i.e. without 
+      paragraph breaks, method HTMLEditorKit.read makes an own paragraph of 
+      the pasted text. HTMLText avoids this behaviour by implementing an 
+      alternate copy and paste mechanism.
+    </p>
+    <p>
+      When not copying multiple paragraphs the selection is split into text 
+      chunks. For each chunk of text it's attributes. Each chunk of text is 
+      inserted togehter with its attributes when it is pasted to another place 
+      in a document.
+    </p>
+    <p class="heading2">
+      Class HTMLTextSelection
+    </p>
+    <p>
+      To transfer data in cut and paste operation a <font face="'Courier New',Monospaced,Monospace">
+Transferable</font> object is needed. A <font face="'Courier New',Monospaced,Monospace">
+Transferable</font> object wraps a data object into a common format describing 
+      the contained data to transfer operations. Class <font face="'Courier New',Monospaced,Monospace">
+HTMLTextSelection</font> is a <font face="'Courier New',Monospaced,Monospace">
+      Transferable</font> for <font face="'Courier New',Monospaced,Monospace">
+      HTMLText</font> objects. Whenever <font face="'Courier New',Monospaced,Monospace">
+HTMLText</font> is to be transported it is wrapped into an <font face="'Courier New',Monospaced,Monospace">
+HTMLTextSelection</font> object and passed to any transfer operation such as 
+      copy or paste.
+    </p>
+    <p class="heading2">
+      Extending JEditorPane
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">JEditorPane</font> is a 
+      subclass of <font face="'Courier New',Monospaced,Monospace">
+      JTextComponent</font>. <font face="'Courier New',Monospaced,Monospace">
+      JTextComponent</font> has methods <font face="'Courier New',Monospaced,Monospace">
+cut</font>, <font face="'Courier New',Monospaced,Monospace">copy</font> and <font face="'Courier New',Monospaced,Monospace">
+paste</font> to implement cut and paste operations which are inherited by <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font>. To actually use <font face="'Courier New',Monospaced,Monospace">
+HTMLText</font> and <font face="'Courier New',Monospaced,Monospace">
+      HTMLTextSelection</font> in an editor, <font face="'Courier New',Monospaced,Monospace">
+JEditorPane</font> has to be extended by an own class named <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> in SimplyHTML. <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> overrides methods <font face="'Courier New',Monospaced,Monospace">
+cut</font>, <font face="'Courier New',Monospaced,Monospace">copy</font> and <font face="'Courier New',Monospaced,Monospace">
+paste</font> and uses <font face="'Courier New',Monospaced,Monospace">HTMLText</font>
+ and <font face="'Courier New',Monospaced,Monospace">HTMLTextSelection</font> 
+      accordingly.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic70.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic70.htm
new file mode 100644
index 0000000..ed94322
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic70.htm
@@ -0,0 +1,54 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Presenting SimplyHTML in multiple languages
+    </p>
+    <p>
+      By using class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic62/topic67.htm">
+ResourceBundle</a></font> for all string constants in SimplyHTML the source 
+      code does not contain string constants except for internal ones not 
+      appearing on the GUI.
+    </p>
+    <p>
+      In the place of the former string constants in the source code a call to 
+      method <font face="'Courier New',Monospaced,Monospace">
+      getResourceString()</font> is put. The actual strings are centrally 
+      stored in and retrieved from a resource file instead.
+    </p>
+    <p>
+      By providing resource files for any language, the application shall be 
+      presented in, the application can be switched to those languages simply 
+      by switching to the particular resource file.
+    </p>
+    <p class="heading2">
+      How a language is picked
+    </p>
+    <p>
+      In Java class <font face="'Courier New',Monospaced,Monospace">Locale</font>
+ is used to represent a specific geographical, political, or cultural region. 
+      The Locale of the system an application is running on can be determined 
+      by <font face="'Courier New',Monospaced,Monospace">Locale.getDefault()</font>
+ .
+    </p>
+    <p>
+      Class FrmMain has a public and static field <font face="'Courier New',Monospaced,Monospace">
+resources</font> referencing the <font face="'Courier New',Monospaced,Monospace">
+ResourceBundle </font>from which all string constants shall be taken. The <font face="'Courier New',Monospaced,Monospace">
+ResourceBundle</font> is initialized to the <font face="'Courier New',Monospaced,Monospace">
+Locale</font> the System is running on. If a resource file for the Locale can 
+      not be found, the default candidate is taken, which would be <font face="'Courier New',Monospaced,Monospace">
+SimplyHTML.properties</font>.
+    </p>
+    <p>
+      If for instance SimplyHTML is running on a German system and a resource 
+      file ending with the appropriate language ("_de") is distributed with 
+      the application, this resource file will be taken. If <font face="'Courier New',Monospaced,Monospace">
+SimplyHTML_de.properties</font> can not be found, <font face="'Courier New',Monospaced,Monospace">
+SimplyHTML.properties</font> will be taken as the resource file instead.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic62/topic72.htm b/src/com/lightdev/app/shtm/help/topic16/topic62/topic72.htm
new file mode 100644
index 0000000..1acf27f
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic62/topic72.htm
@@ -0,0 +1,132 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Implementing drag and drop
+    </p>
+    <p>
+      Drag and drop more or less is cut and paste without having to use the 
+      menu. As SimplyHTML has implemented <a href="../../topic16/topic62/topic69.htm">
+cut and paste for styled text and HTML text</a> in stage 2, it has the basis 
+      for drag and drop too.
+    </p>
+    <p class="heading3">
+      Typical drag an drop
+    </p>
+    <p>
+      A typical drag and drop operation in the editor would act as follows: By 
+      selecting text in the editor and by dragging the selection with the 
+      mouse, a copy operation is initiated. Once the selection is dropped 
+      anywhere else in the editor, the selection is removed from the original 
+      location and pasted at the new location.
+    </p>
+    <p>
+      To implement drag and drop a mechanism has to be implemented to 
+      recognize drag and drop activities and to react in the described way.
+    </p>
+    <p class="heading3">
+      The Java Tutorial
+    </p>
+    <p>
+      There is a good example about how to implement drag and drop in The Java 
+      Tutorial. The drag and drop example is well explained there already. At 
+      this point therefore only some more general aspects are discussed only.
+    </p>
+    <p>
+      The Java Tutorial is available online at <font color="#3333ff">
+      http://java.sun.com/docs/books/tutorial/</font>
+    </p>
+    <p>
+      <b>Note</b>: In J2SE 1.4 the original drag and drop is simplyfied by 
+      wrapping the 'old' implementation into class TransferHandler partly but 
+      as SimplyHTML shall be available to users of the 1.3 Runtime, the 'old' 
+      mechanism is implemented which in fact does the same as the 'new' one.
+    </p>
+    <p class="heading2">
+      Drag and drop in SimplyHTML
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">SHTMLEditorPane</font>
+ has been created in this stage to allow for own cut and paste handling. For 
+      drag and drop support it has an additional section in the source code. 
+      The main parts of the drag and drop implementation are methods
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">initDnd</font>
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">dragGestureRecognized</font>
+
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">drop</font> and
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">doDrop</font>
+      </li>
+    </ul>
+    <p class="heading3">
+      Method initDnd
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">initDnd</font> 
+      instantiates the objects necessary to control our drag and drop 
+      implementation: <font face="'Courier New',Monospaced,Monospace">
+      DragSource</font> and <font face="'Courier New',Monospaced,Monospace">
+      DropTarget</font>. The <font face="'Courier New',Monospaced,Monospace">
+      SHTMLEditorPane</font> registers itself as a <font face="'Courier New',Monospaced,Monospace">
+DropTarget</font> and as a <font face="'Courier New',Monospaced,Monospace">
+      DropTargetListener</font>. In <font face="'Courier New',Monospaced,Monospace">
+DragSource</font> <font face="'Courier New',Monospaced,Monospace">SHTMLEditPane</font>
+ registers itself as a <font face="'Courier New',Monospaced,Monospace">
+      DragGestureRecognizer</font>. As well it registers as a <font face="'Courier New',Monospaced,Monospace">
+MouseListener</font> to keep track of the selection during drag and drop 
+      operations.
+    </p>
+    <p class="heading3">
+      Method dragGestureRecognized
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">dragGestureRecognized</font>
+ is the method <font face="'Courier New',Monospaced,Monospace">SHTMLEditorPane</font>
+ has to implement to be a <font face="'Courier New',Monospaced,Monospace">
+      DragGestureRecognizer</font>. The method is invoked by all drag 
+      initiating gestures on <font face="'Courier New',Monospaced,Monospace">
+      SHTMLEditorPane</font>.
+    </p>
+    <p>
+      In method <font face="'Courier New',Monospaced,Monospace">
+      dragGestureRecognized</font> an <font face="'Courier New',Monospaced,Monospace">
+HTMLText</font> object is created on the currently selected text and an <font face="'Courier New',Monospaced,Monospace">
+HTMLTextSelection</font> <a href="../../topic16/topic62/topic65.htm">
+      transferable</a> is created wrapping the <font face="'Courier New',Monospaced,Monospace">
+HTMLText</font> object. Finally the drag operation is initiated by invoking 
+      method <font face="'Courier New',Monospaced,Monospace">
+      DragSource.startDrag</font> with the newly created transferable.
+    </p>
+    <p class="heading3">
+      Method drop
+    </p>
+    <p>
+      Once a drop event is recognized, method drop is invoked. In SimplyHTML 
+      it calls method <font face="'Courier New',Monospaced,Monospace">doDrop</font>
+ if a suitable <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic62/topic65.htm">
+DataFlavor</a></font> (<font face="'Courier New',Monospaced,Monospace">HTMLText</font>
+ or <font face="'Courier New',Monospaced,Monospace">String</font>) is found in 
+      the dragged element. Otherwise the drop is rejected.
+    </p>
+    <p class="heading3">
+      Method doDrop
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">doDrop</font> 
+      does the actual cut and paste resulting from the drag and drop operation 
+      consisting of adding the dragged element and necessarily removing the 
+      dragged element from the original position.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74.htm b/src/com/lightdev/app/shtm/help/topic16/topic74.htm
new file mode 100644
index 0000000..9ded83b
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74.htm
@@ -0,0 +1,27 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 3: Font manipulation and tool bars
+    </p>
+    <p>
+      Most text processors have one essential functionality in common. They 
+      allow to manipulate fonts in various ways.
+    </p>
+    <p>
+      Typically fonts can be set through a menu allowing to change all font 
+      related settings for a certain portion of text at once. In addition, 
+      there mostly is a tool bar to quickly change single font attributes such 
+      as size or style.
+    </p>
+    <p>
+      Stage 3 of SimplyHTML is about adding font manipulation features. It 
+      builds a font dialog to change a whole set of font related attributes 
+      and it creates tool bars to access most functions of SimplyHTML 
+      including new font formatting.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic75.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic75.htm
new file mode 100644
index 0000000..324ec7f
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic75.htm
@@ -0,0 +1,201 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a GUI for font manipulation
+    </p>
+    <p class="standard">
+      To use the functionality described in the previous chapters, application 
+      SimplyHTML needs additional GUI components the first of which is class <font face="'Courier New',Monospaced,Monospace">
+FontPanel</font>. Class <font face="'Courier New',Monospaced,Monospace">
+      FontPanel</font> allows to display and change most relevant font and 
+      font style attributes at once. By wrapping all related components into a 
+      panel, it is easier to use it in different places such as dialogs later.
+    </p>
+    <p class="heading2">
+      Setting and getting attributes
+    </p>
+    <p class="standard">
+      <font face="'Courier New',Monospaced,Monospace">FontPanel</font> uses 
+      methods <font face="'Courier New',Monospaced,Monospace">getAttributes</font>
+ and <font face="'Courier New',Monospaced,Monospace">setAttributes</font> to 
+      exchange font settings with other objects through an <a href="../../topic16/topic74/topic78.htm">
+AttributeSet</a>.
+    </p>
+    <p class="standard">
+      In the constructor of <font face="'Courier New',Monospaced,Monospace">
+      FontPanel</font> all components implementing the <font face="'Courier New',Monospaced,Monospace">
+FontComponent</font> interface (see below) are added to <font face="'Courier New',Monospaced,Monospace">
+Vector</font> <font face="'Courier New',Monospaced,Monospace">fontComponents</font>
+ . This makes it easy for methods <font face="'Courier New',Monospaced,Monospace">
+getAttributes</font> and <font face="'Courier New',Monospaced,Monospace">
+      setAttributes</font> to distribute or collect the attributes to and from 
+      the various font manipulation components through an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font>.
+    </p>
+    <p class="standard">
+      <font face="Sans-Serif">Methods </font><font face="'Courier New',Monospaced,Monospace">
+getAttributes</font> and <font face="'Courier New',Monospaced,Monospace">
+      setAttributes</font> simply go through all objects in <font face="'Courier New',Monospaced,Monospace">
+Vector</font> <font face="'Courier New',Monospaced,Monospace">fontComponents</font>
+ and call methods <font face="'Courier New',Monospaced,Monospace">getValue</font>
+ and <font face="'Courier New',Monospaced,Monospace">setValue</font> 
+      respectively passing the <font face="'Courier New',Monospaced,Monospace">
+      AttributeSet</font> containing the actual font settings.
+    </p>
+    <p class="heading2">
+      Components of class FontPanel
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">FontPanel</font> uses 
+      GUI components defined in different classes to set the various font 
+      attributes:
+    </p>
+    <ul>
+      <li>
+        font family - <font face="'Courier New',Monospaced,Monospace">
+        FamilyPickList</font>
+      </li>
+      <li>
+        font size - <font face="'Courier New',Monospaced,Monospace">
+        SizePickList</font>
+      </li>
+      <li>
+        font style - <font face="'Courier New',Monospaced,Monospace">
+        StylePickList</font>
+      </li>
+      <li>
+        line effects - <font face="'Courier New',Monospaced,Monospace">
+        EffectPanel</font>
+      </li>
+      <li>
+        colors - <font face="'Courier New',Monospaced,Monospace">ColorPanel</font>
+
+      </li>
+    </ul>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">FamilyPickList</font>, <font face="'Courier New',Monospaced,Monospace">
+SizePickList</font> and <font face="'Courier New',Monospaced,Monospace">
+      StylePickList</font> are inner classes of class <font face="'Courier New',Monospaced,Monospace">
+FontPanel</font> and variations of a separate class <font face="'Courier New',Monospaced,Monospace">
+TitledPickList</font> which defines the general behaviour of a pick list 
+      typical for font dialogs having a list, a text field and a title label. 
+      All mentioned classes are described below shortly. Please consult the 
+      sources and API documents for further details.
+    </p>
+    <p class="heading2">
+      TitledPickList
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">TitledPickList</font>
+ defines a pick list typically being used in font dialogs, consisting of a 
+      list title, a text field for the currently selected value and the actual 
+      pick list containing all possible values. It implements listeners for 
+      the various events produced by user settings inside its controls to 
+      synchronize selections in the text field and the pick list at all times. 
+      Then it has some getter/setter methods to programmatically get and set a 
+      selection.
+    </p>
+    <p>
+      It also defines a an <font face="'Courier New',Monospaced,Monospace">
+      EventListener</font> and <font face="'Courier New',Monospaced,Monospace">
+      Event</font> so that external components can be notified of changes in 
+      the <font face="'Courier New',Monospaced,Monospace">TitledPickList</font>
+       . This mainly is meant to allow <font face="'Courier New',Monospaced,Monospace">
+FontPanel</font> to update the sample text display whenever a selection 
+      changes.
+    </p>
+    <p class="heading2">
+      FamilyPickList, SizePickList and StylePickList
+    </p>
+    <p>
+      Classes <font face="'Courier New',Monospaced,Monospace">FamilyPickList</font>
+ , <font face="'Courier New',Monospaced,Monospace">SizePickList</font> and <font face="'Courier New',Monospaced,Monospace">
+StylePickList</font> all are subclasses of <font face="'Courier New',Monospaced,Monospace">
+TitledPickList</font>. They extend <font face="'Courier New',Monospaced,Monospace">
+TitledPickList</font> by implementing interface <font face="'Courier New',Monospaced,Monospace">
+FontComponent</font>.
+    </p>
+    <p class="heading2">
+      Interface FontComponent
+    </p>
+    <p>
+      Interface <font face="'Courier New',Monospaced,Monospace">FontComponent</font>
+ is used to standardize the way attributes are set and retrieved. It defines 
+      two generic methods <font face="'Courier New',Monospaced,Monospace">
+      getValue</font> and <font face="'Courier New',Monospaced,Monospace">
+      setValue</font>. <font face="'Courier New',Monospaced,Monospace">setValue</font>
+ is meant for setting a component from an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font>, <font face="'Courier New',Monospaced,Monospace">getValue</font>
+ should return the setting of a font component in the form of an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font>.
+    </p>
+    <p class="heading3">
+      Implementing the FontComponent Interface
+    </p>
+    <p>
+      Each component implementing the <font face="'Courier New',Monospaced,Monospace">
+FontComponent</font> interface can do the implementation special to the 
+      attribute or set of attributes it is meant to manipulate. <font face="'Courier New',Monospaced,Monospace">
+FamilyPickList</font> for instance simply reads <font face="'Courier New',Monospaced,Monospace">
+CSS.Attribute.FONT_FAMILY</font>, <font face="'Courier New',Monospaced,Monospace">
+StylePickList</font> acts on a combination of <font face="'Courier New',Monospaced,Monospace">
+CSS.Attribute.FONT_WEIGHT</font> and <font face="'Courier New',Monospaced,Monospace">
+CSS.Attribute.FONT_STYLE</font> and <font face="'Courier New',Monospaced,Monospace">
+SizePickList</font> uses <font face="'Courier New',Monospaced,Monospace">
+      CSS.Attribute.FONT_SIZE</font> and adds certain handling for the 'pt' 
+      identifier.
+    </p>
+    <p class="heading2">
+      EffectPanel
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">EffectPanel</font> 
+      is a <font face="'Courier New',Monospaced,Monospace">JPanel</font> with 
+      a <font face="'Courier New',Monospaced,Monospace">ButtonGroup</font> of <font face="'Courier New',Monospaced,Monospace">
+JRadioButtons</font> allowing to select, whether or not a text portion should 
+      be underlined or striked out. With <font face="'Courier New',Monospaced,Monospace">
+CSS.Attribute.TEXT_DECORATION</font>, attributes <font face="'Courier New',Monospaced,Monospace">
+underline</font> and <font face="'Courier New',Monospaced,Monospace">
+      line-through</font> can not be combined which is why <font face="'Courier New',Monospaced,Monospace">
+JRadioButtons</font> are used allowing only one of the possible selections at 
+      a time.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">EffectPanel</font> 
+      implements interface <font face="'Courier New',Monospaced,Monospace">
+      FontComponent</font> to set and return the component's value in form of 
+      an <font face="'Courier New',Monospaced,Monospace">AttributeSet</font>.
+    </p>
+    <p class="heading2">
+      ColorPanel
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">ColorPanel</font> 
+      adds a <font face="'Courier New',Monospaced,Monospace">JLabel</font>, a <font face="'Courier New',Monospaced,Monospace">
+JTextField</font> and a <font face="'Courier New',Monospaced,Monospace">JButton</font>
+ to a <font face="'Courier New',Monospaced,Monospace">JPanel</font> and shows 
+      a <font face="'Courier New',Monospaced,Monospace">JColorChooser</font> 
+      dialog when the <font face="'Courier New',Monospaced,Monospace">JButton</font>
+ is pressed. Colors selected from the <font face="'Courier New',Monospaced,Monospace">
+JColorChooser</font> are set as the background color of the <font face="'Courier New',Monospaced,Monospace">
+JTextField</font>. The <font face="'Courier New',Monospaced,Monospace">
+      JTextField</font> is not editable, it is only used to show the currently 
+      selected color as its background color.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">ColorPanel</font> 
+      implements interface <font face="'Courier New',Monospaced,Monospace">
+      FontComponent</font> to set and return the component's value in form of 
+      an <font face="'Courier New',Monospaced,Monospace">AttributeSet</font>. 
+      In addition it defines a an <font face="'Courier New',Monospaced,Monospace">
+EventListener</font> and <font face="'Courier New',Monospaced,Monospace">Event</font>
+ so that external components can be notified of changes in the <font face="'Courier New',Monospaced,Monospace">
+ColorPanel</font>. This mainly is meant to allow <font face="'Courier New',Monospaced,Monospace">
+FontPanel</font> to update the sample text display when a color is changed.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic76.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic76.htm
new file mode 100644
index 0000000..3196716
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic76.htm
@@ -0,0 +1,65 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+
+    <p class="heading1">
+      Customizing Java for CSS
+    </p>
+    <p>
+      Before we can look at how to build GUI and functionality for font 
+      manipulation, we need to understand the way, HTML documents are handled 
+      in Java a little more.
+    </p>
+    <p>
+      As shown previously, text and HTML are used in a <a href="../../topic16/topic4/topic25.htm">
+model-view-controller environment</a> consisting of EditorKit, Document and 
+      EditorPane. However, up to Java 2 Standard Edition version 1.4 this 
+      environment supports HTML 3.2 only. Especially it does not totally 
+      support <a href="../../topic16/topic4/topic25/topic42.htm">CSS</a> 
+      elements although attributes are stored partly in CSS format already.
+    </p>
+    <p>
+      SimplyHTML is based on CSS for dealing with styles and font settings 
+      belong to styles so consequently, font settings are implemented using 
+      CSS as well.
+    </p>
+    <p class="heading2">
+      Design approach
+    </p>
+    <p>
+      In stage 3 of SimplyHTML font manipulation is enabled for a contiguous 
+      run of characters. HTML has tag <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> to set font attributes for a contiguous run of characters using 
+      CSS . In addition there are tags <font face="'Courier New',Monospaced,Monospace">
+FONT</font>, <font face="'Courier New',Monospaced,Monospace">B</font>, <font face="'Courier New',Monospaced,Monospace">
+I</font> etc. allowign the same without using CSS.
+    </p>
+    <p>
+      In SimplyHTML universal usage of CSS has been chosen because almost any 
+      part of a HTML structure can be formatted with CSS regardless of its 
+      type.
+    </p>
+    <p class="heading2">
+      Solution approach
+    </p>
+    <p>
+      To show and manipulate font information for documents with SimplyHTML 
+      using CSS on character level, support for the <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tag has to be built into the <a href="../../topic16/topic4/topic25.htm">
+MVC environment</a> for HTML documents in Java.
+    </p>
+    <p>
+      SimplyHTML does this by extending classes <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>, <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument.HTMLReader</font>, <font face="'Courier New',Monospaced,Monospace">
+HTMLEditorKit</font> and <font face="'Courier New',Monospaced,Monospace">
+      HTMLWriter</font> accordingly, as described in the next chapters.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic77.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic77.htm
new file mode 100644
index 0000000..3acd7bd
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic77.htm
@@ -0,0 +1,143 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Extending classes for tag SPAN
+    </p>
+    <p>
+      SimplyHTML extends classes <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>, <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument.HTMLReader</font>, <font face="'Courier New',Monospaced,Monospace">
+HTMLEditorKit</font> and <font face="'Courier New',Monospaced,Monospace">
+      HTMLWriter</font> to support the <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tag of HTML. In this chapter the overall approach of how this is 
+      done is described. Please consult the source code and API documents of 
+      the mentioned classes for additional details.
+    </p>
+    <p class="heading2">
+      Why extending the mentioned classes?
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font>
+       has an inner class <font face="'Courier New',Monospaced,Monospace">
+      HTMLReader</font> which is used by <font face="'Courier New',Monospaced,Monospace">
+HTMLEditorKit</font> to read HTML files. <font face="'Courier New',Monospaced,Monospace">
+HTMLReader</font> does not support <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tags so it is extended by SHTMLReader accordingly. To use <font face="'Courier New',Monospaced,Monospace">
+SHTMLReader</font> in favor of <font face="'Courier New',Monospaced,Monospace">
+      HTMLReader</font>, class <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font> has to be extended too.
+    </p>
+    <p>
+      When a HTML document is edited in SimplyHTML, all attributes are stored 
+      as CSS attributes which is why it is also necessary to extend class <font face="'Courier New',Monospaced,Monospace">
+HTMLWriter</font> to write out those CSS styles inside <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tags. To use both our own reader and our own writer, <font face="'Courier New',Monospaced,Monospace">
+HTMLEditorKit</font> needs to be extended as well.
+    </p>
+    <p class="heading2">
+      SHTMLWriter
+    </p>
+    <p>
+      Usually a class is extended simply by overriding one or more of its 
+      public methods. Unfortunately class <font face="'Courier New',Monospaced,Monospace">
+HTMLWriter</font> only has one public method <font face="'Courier New',Monospaced,Monospace">
+write</font> which calls other private methods making up the actual write 
+      process.
+    </p>
+    <p>
+      If not a completely new writer is to be created, the only way to extend <font face="'Courier New',Monospaced,Monospace">
+HTMLWriter</font> is to copy its source code completely into a new subclass <font face="'Courier New',Monospaced,Monospace">
+SHTMLWriter</font> and change some of the code to our needs (please do let me 
+      know if you can provide a more elegant way to do this...).
+    </p>
+    <p>
+      To allow to write <font face="'Courier New',Monospaced,Monospace">SPAN</font>
+ tags for style attributes, new class <font face="'Courier New',Monospaced,Monospace">
+SHTMLWriter</font> changes method <font face="'Courier New',Monospaced,Monospace">
+convertToHTML32</font>. Whenever a <font face="'Courier New',Monospaced,Monospace">
+CONTENT</font> tag is encountered during write, any CSS attributes are 
+      converted to a syntax used in <font face="'Courier New',Monospaced,Monospace">
+STYLE</font> attributes. The resulting style string then is added to a new <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tag and the <font face="'Courier New',Monospaced,Monospace">SPAN</font>
+ tag including the found styles is added to the <font face="'Courier New',Monospaced,Monospace">
+CONTENT</font> tag.
+    </p>
+    <p class="heading2">
+      SHTMLDocument
+    </p>
+    <p>
+      Whenever data is read into an instance of <font face="'Courier New',Monospaced,Monospace">
+SHTMLDocument</font>, method <font face="'Courier New',Monospaced,Monospace">
+      getReader</font> returns an instance of the reader special to this type 
+      of document, so this method is overridden to provide an instance of <font face="'Courier New',Monospaced,Monospace">
+SHTMLReader</font> (see below).
+    </p>
+    <p class="heading2">
+      SHTMLDocument.SHTMLReader
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font>
+       contains an inner class <font face="'Courier New',Monospaced,Monospace">
+      HTMLReader</font> to read HTML data into an instance of <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>. To support <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tags <font face="'Courier New',Monospaced,Monospace">SHTMLDocument</font>
+ creates a new inner class <font face="'Courier New',Monospaced,Monospace">
+      SHTMLReader</font>.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">SHTMLReader</font> 
+      overrides methods <font face="'Courier New',Monospaced,Monospace">
+      handleStartTag</font>, <font face="'Courier New',Monospaced,Monospace">
+      handleSimpleTag</font> and <font face="'Courier New',Monospaced,Monospace">
+handleEndTag</font> which are called by the parser for every tag found. <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tags are delivered to the reader through method <font face="'Courier New',Monospaced,Monospace">
+handleSimpleTag</font>. <font face="'Courier New',Monospaced,Monospace">
+      SHTMLReader</font> deviates this tag to be handled by <font face="'Courier New',Monospaced,Monospace">
+handleStartTag</font> instead.
+    </p>
+    <p>
+      In method handleStartTag, for any <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tag found an instance of <font face="'Courier New',Monospaced,Monospace">
+SHTMLCharacterAction</font> is invoked. <font face="'Courier New',Monospaced,Monospace">
+SHTMLCharacterAction</font> is an inner class of <font face="'Courier New',Monospaced,Monospace">
+SHTMLReader</font> and extends class <font face="'Courier New',Monospaced,Monospace">
+CharacterAction</font> of class <font face="'Courier New',Monospaced,Monospace">
+HTMLReader</font>. It does the actual handling of the <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tag by removing the <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tag and by adding its style attributes to the <font face="'Courier New',Monospaced,Monospace">
+CONTENT</font> tag the <font face="'Courier New',Monospaced,Monospace">SPAN</font>
+ tag belongs to.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">handleEndTag</font>
+ properly terminates <font face="'Courier New',Monospaced,Monospace">
+      SHTMLCharacterActions</font> for any <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tag in process.
+    </p>
+    <p class="heading2">
+      SHTMLEditorKit
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">HTMLEditorKit</font>
+ provides methods to read and write data stored inside an instance of <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>. It uses method <font face="'Courier New',Monospaced,Monospace">
+getReader</font> of <font face="'Courier New',Monospaced,Monospace">
+      HTMLDocument</font> in its read an write methods. To support our own set 
+      of classes as described above, class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorKit</font> overrides methods <font face="'Courier New',Monospaced,Monospace">
+read</font> and <font face="'Courier New',Monospaced,Monospace">write</font> 
+      accordingly.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">SHTMLEditorKit</font> 
+      also ensures that a <font face="'Courier New',Monospaced,Monospace">
+      SHTMLDocument</font> is created instead of a <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> by overriding method <font face="'Courier New',Monospaced,Monospace">
+createDefaultDocument</font>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic78.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic78.htm
new file mode 100644
index 0000000..141f02c
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic78.htm
@@ -0,0 +1,92 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Manipulating fonts and font styles
+    </p>
+    <p>
+      Documents are modeled by <font face="'Courier New',Monospaced,Monospace">
+      Elements</font> which are hierarchically linked according to the content 
+      structure in the document. HTML documents for instance define - with 
+      certain exceptions - an <font face="'Courier New',Monospaced,Monospace">
+      Element</font> object for every HTML tag. As with HTML tags, each <font face="'Courier New',Monospaced,Monospace">
+Element</font> can have one or more attributes (bold, italic, etc.) which are 
+      assigned to an <font face="'Courier New',Monospaced,Monospace">Element</font>
+ through class <font face="'Courier New',Monospaced,Monospace">AttributeSet</font>
+ .
+    </p>
+    <p class="heading3">
+      Applicable ranges for AttributeSets
+    </p>
+    <p>
+      How <font face="'Courier New',Monospaced,Monospace">AttributeSets</font> 
+      influence the rendering of a document depends on the context they are 
+      found in. Attributes for a paragraph for instance can be valid for a 
+      whole range of subseuqent <font face="'Courier New',Monospaced,Monospace">
+Elements</font>. In addition, a HTML document has an associated style sheet 
+      which defines <font face="'Courier New',Monospaced,Monospace">
+      AttributeSets</font> too. If a paragraph element or an element for a 
+      range of characters has no attributes in the document itself, attributes 
+      from the style sheet might still be relevant for rendering respective 
+      content.
+    </p>
+    <p class="heading3">
+      Limitation to attributes on character level
+    </p>
+    <p>
+      In stage 3 of application SimplyHTML only manipulation of fonts and font 
+      styles on character level is implemented. There are two methods in 
+      SimplyHTML for dealing with attribute changes, one for reading 
+      attributes for a given position in a document and one for applying 
+      attributes to a given part of a document.
+    </p>
+    <p class="heading2">
+      Method getMaxAttributes
+    </p>
+    <p>
+      All methods in stage 3 of SimplyHTML dealing with fonts and font styles 
+      use static method <font face="'Courier New',Monospaced,Monospace">
+      getMaxAttributes</font> of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> to determine which attributes are assigned to a certain point 
+      inisde a document. Method <font face="'Courier New',Monospaced,Monospace">
+getMaxAttributes</font> combines attributes from the style sheet associated to 
+      the document with attributes assigend directly to to a character element 
+      inside the document (in later stages this has to be refined to deal with 
+      style sheet styles other than <font face="'Courier New',Monospaced,Monospace">
+<p></font>, paragraph styles, etc.).
+    </p>
+    <p>
+      The attribute sets from the style sheet and from the character element 
+      are added to a new attribute set which is returned to the calling method.
+    </p>
+    <p class="heading2">
+      Method applyAttributes
+    </p>
+    <p>
+      As described in the follwing chapters all components manipulating fonts 
+      and font styles do their changes entirely on the basis of <font face="'Courier New',Monospaced,Monospace">
+AttributeSets</font>. An <font face="'Courier New',Monospaced,Monospace">
+      AttributeSet</font> is applied to a document by method <font face="'Courier New',Monospaced,Monospace">
+applyAttributes</font> in class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>.
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">applyAttributes</font>
+ determines whether or not a range of characters is selected in the given 
+      editor pane. If a selection is present, the given <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> is applied to that range of text. If no selection is 
+      present, the given <font face="'Courier New',Monospaced,Monospace">
+      AttributeSet</font> is applied as attributes for subsequent inputs.
+    </p>
+    <p>
+      To define attributes for subsequent inputs, class <font face="'Courier New',Monospaced,Monospace">
+EditorKit</font> defines a method <font face="'Courier New',Monospaced,Monospace">
+getInputAttributes</font>. When attributes are stored in the AttributeSet 
+      returned by this method, these attributes are applied for inputs 
+      thereafter.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic79.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic79.htm
new file mode 100644
index 0000000..1c13365
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic79.htm
@@ -0,0 +1,82 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a font formatting tool bar
+    </p>
+    <p>
+      As we have created functionality to manipulate font settings as 
+      described in the previous chapters, now it would be handy to have 
+      certain font formatting functions availabe in a tool bar as it is done 
+      in other text processors too.
+    </p>
+    <p>
+      Creating a font formatting tool bar for that purpose is easily done 
+      though a mechanism we already know from SimplyHTML's <a href="../../topic16/topic62/topic68.htm">
+dynamic menu creation function</a>. Method <font face="'Courier New',Monospaced,Monospace">
+createToolBar</font> uses the same technique by reading a tool bar definition 
+      string and turning it into a tool bar.
+    </p>
+    <p class="heading2">
+      Method createToolBar
+    </p>
+    <p>
+      To create a tool bar a tool bar definition string from the resource file 
+      is read having the key for each element in the tool bar delimited by 
+      blanks (e.g. fontFamily fontBold fontItalic). The keys are in the order 
+      as elements shall appear in the tool bar.
+    </p>
+    <p class="heading3">
+      Standard tool bar buttons
+    </p>
+    <p>
+      The typical case is to add a button on the tool bar for an action 
+      defined in the <font face="'Courier New',Monospaced,Monospace">commands</font>
+ <font face="'Courier New',Monospaced,Monospace">Hashtable</font> of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>. Class <font face="'Courier New',Monospaced,Monospace">JToolBar</font>
+ has a constructor returning a newly created button by passing an action to 
+      the constructor. The constructor will do all the connections between the 
+      tool bar button and the action automatically.
+    </p>
+    <p class="heading3">
+      Combo box elements
+    </p>
+    <p>
+      Some of the elements in the tool bar however require special handling. <font face="'Courier New',Monospaced,Monospace">
+FontFamilyPicker</font> and <font face="'Courier New',Monospaced,Monospace">
+      FontSizePicker</font> for instance are subclasses of <font face="'Courier New',Monospaced,Monospace">
+JComboBox</font>. In their case, <font face="'Courier New',Monospaced,Monospace">
+createToolbar</font> creates an instance of the component and uses method add 
+      of <font face="'Courier New',Monospaced,Monospace">JToolBar</font>.
+    </p>
+    <p class="heading3">
+      Toggle buttons
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">FontComponents</font> 
+      other than <font face="'Courier New',Monospaced,Monospace">
+      FontFamilyPicker</font> and <font face="'Courier New',Monospaced,Monospace">
+FontSizePicker</font> are instances of <font face="'Courier New',Monospaced,Monospace">
+ToggleFontAction</font>. For <font face="'Courier New',Monospaced,Monospace">
+      ToggleFontActions</font> we need a <font face="'Courier New',Monospaced,Monospace">
+JToggleButton</font> instead of a <font face="'Courier New',Monospaced,Monospace">
+JButton</font> in the tool bar and we have to make sure, the <font face="'Courier New',Monospaced,Monospace">
+JToggleButton</font> is property connected to its <font face="'Courier New',Monospaced,Monospace">
+ToggleFontAction</font>.
+    </p>
+    <p>
+      For each <font face="'Courier New',Monospaced,Monospace">JToggleButton</font>
+ in the tool bar a <font face="'Courier New',Monospaced,Monospace">
+      ToggleActionChangedListener</font> associated with the corresponding <font face="'Courier New',Monospaced,Monospace">
+ToggleFontAction</font> is created. <font face="'Courier New',Monospaced,Monospace">
+ToggleActionChangedListener</font> implements interface <font face="'Courier New',Monospaced,Monospace">
+PropertyChangeListener</font> and will always adjust the <font face="'Courier New',Monospaced,Monospace">
+JToggleButton</font> according to the action's current state. An <font face="'Courier New',Monospaced,Monospace">
+ActionListener</font> in turn is registered for the <font face="'Courier New',Monospaced,Monospace">
+JToggleButton</font> invoking the action when the button is pressed.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic80.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic80.htm
new file mode 100644
index 0000000..8c776ab
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic80.htm
@@ -0,0 +1,65 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Using the new font formatting GUI
+    </p>
+    <p>
+      <a href="../../topic16/topic74/topic75.htm">Previous chapter</a> 
+      described <font face="'Courier New',Monospaced,Monospace">FontPanel</font>
+ as SimplyHTML's GUI to set most relevant font and font style settings at 
+      once. To actually use class <font face="'Courier New',Monospaced,Monospace">
+FontPanel</font> two additional classes are required. First of all, a dialog 
+      is needed to present a <font face="'Courier New',Monospaced,Monospace">
+      FontPanel</font> to the user. As well an action to invoke respective 
+      dialog must be created.
+    </p>
+    <p class="heading2">
+      Class FontDialog
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">FontDialog</font> 
+      simply wraps class <font face="'Courier New',Monospaced,Monospace">
+      FontPanel</font> into a <font face="'Courier New',Monospaced,Monospace">
+      JDialog</font> and creates all methods necessary to control the dialog 
+      such as closing the dialog with 'OK', cancelling the dialog etc.
+    </p>
+    <p>
+      In its constructor <font face="'Courier New',Monospaced,Monospace">
+      FontDialog</font> expects an <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic74/topic78.htm">
+AttributeSet</a></font> which is routed on to <font face="'Courier New',Monospaced,Monospace">
+FontPanel</font> for display and manipulation. Once the dialog is closed by 
+      pressing the 'OK' button, method <font face="'Courier New',Monospaced,Monospace">
+getAttributes</font> returns the <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> from method <font face="'Courier New',Monospaced,Monospace">
+getAttributes</font> of class <font face="'Courier New',Monospaced,Monospace">
+      FontPanel</font>. Method <font face="'Courier New',Monospaced,Monospace">
+      getResult</font> returns the information whether the dialog was closed 
+      with the 'OK' or the 'Cancel' button.
+    </p>
+    <p class="heading2">
+      Action FontAction
+    </p>
+    <p>
+      With class <font face="'Courier New',Monospaced,Monospace">FontAction</font>
+ all prevously descibed font functionality is 'plugged' into SimplyHTML's 
+      mechanism to make functions avaliable on the GUI. Its method <font face="'Courier New',Monospaced,Monospace">
+actionPerformed</font> creates an instance of class <font face="'Courier New',Monospaced,Monospace">
+FontDialog</font> and applies font changes from <font face="'Courier New',Monospaced,Monospace">
+FontDialog</font> to a document. <font face="'Courier New',Monospaced,Monospace">
+FontAction</font> is added to the commands Hashtable of FrmMain through method <font face="'Courier New',Monospaced,Monospace">
+initActions</font> and its name is reflected in the action name constants of 
+      FrmMain ensuring proper usage during <a href="../../topic16/topic62/topic68.htm">
+dynamic menu creation</a>.
+    </p>
+    <p>
+      To always reflect proper state to components bound to <font face="'Courier New',Monospaced,Monospace">
+FontAction</font>, it implements interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font> with method <font face="'Courier New',Monospaced,Monospace">
+      update</font>.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic81.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic81.htm
new file mode 100644
index 0000000..da2827a
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic81.htm
@@ -0,0 +1,149 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Actions and components to switch single font attributes
+    </p>
+    <p>
+      On top of being able to change most relevant font settings at once using 
+      class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic74/topic75.htm">
+FontPanel</a></font>, a couple of actions and components are needed to allow 
+      users to toggle or switch single font attributes quickly. In stage 3 of 
+      SimplyHTML this is done by adding some inner classes to <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> implementing respective parts:
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">FontFamilyPicker</font>
+         - a JComboBox dedicated to font family changes
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">FontSizePicker</font> 
+        - a JComboBox dedicated to font size changes
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">FontFamilyAction</font>
+         - an action to change the font family
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">FontSizeAction</font> 
+        - an action to change the font size
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">ToggleFontAction</font>
+         - an action to toggle a single font setting on or off
+      </li>
+    </ul>
+    <p class="heading2">
+      FontFamilyPicker and FontSizePicker
+    </p>
+    <p>
+      The easiest way to act on a certain font setting probably would be an 
+      action bound to a <font face="'Courier New',Monospaced,Monospace">JButton</font>
+ . For font properties family and size however, a possible setting is not just 
+      'on' or 'off', for both attributes there a is a certain list of possible 
+      selections instead. For this type of setting a <font face="'Courier New',Monospaced,Monospace">
+JComboBox</font> is the GUI component of choice.
+    </p>
+    <p class="heading3">
+      Extending JComboBox
+    </p>
+    <p>
+      To make such <font face="'Courier New',Monospaced,Monospace">JComboBoxes</font>
+ easier to handle, two inner classes <font face="'Courier New',Monospaced,Monospace">
+FontFamilyPicker</font> and <font face="'Courier New',Monospaced,Monospace">
+      FontSizePicker</font> extend class <font face="'Courier New',Monospaced,Monospace">
+JComboBox</font> with functions special to the purpose of changing respective 
+      font settings.
+    </p>
+    <p class="heading3">
+      Customized content and common interface
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">FontFamilyPicker</font> 
+      adds all font family names found on the particular system to its combo 
+      box using method <font face="'Courier New',Monospaced,Monospace">
+      getAvailableFontFamilyNames</font> of class <font face="'Courier New',Monospaced,Monospace">
+GraphicsEnvironment</font> in its constructor. <font face="'Courier New',Monospaced,Monospace">
+FontSizePicker</font> adds a fixed list of point sizes instead. Both classes 
+      implement interface <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic74/topic75.htm">
+FontComponent</a></font> for standardized access to their selected value.
+    </p>
+    <p class="heading2">
+      FontFamilyAction and FontSizeAction
+    </p>
+    <p>
+      Both actions implement interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font> so that common handling of setting action properties from 
+      our resource bundle and common updating can be used. In their 
+      actionPerformed method they apply the attribute represented by their 
+      associated picker component (family or size) to the editor.
+    </p>
+    <p class="heading2">
+      ToggleFontAction
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">ToggleFontAction</font> 
+      allows to switch a single font setting on or off in a generic way. It 
+      extends <font face="'Courier New',Monospaced,Monospace">AbstractAction</font>
+ by defining some private fields reflecting the font attribute this instance 
+      of <font face="'Courier New',Monospaced,Monospace">ToggleFontAction</font>
+ represents as well as the value for 'on' and 'off' for that particular font 
+      attribute. In the constructor, those fields are initialized from 
+      respective arguments passed to the constructor.
+    </p>
+    <p class="heading3">
+      Shifting state
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">actionPerformed</font>
+ applies the font attribute resulting from the current state (on or off) and 
+      then toggles the action's state using method <font face="'Courier New',Monospaced,Monospace">
+putValue</font>. By passing either value <font face="'Courier New',Monospaced,Monospace">
+FrmMain.ACTION_SELECTED</font> or <font face="'Courier New',Monospaced,Monospace">
+FrmMain.ACTION_UNSELECTED</font> with key <font face="'Courier New',Monospaced,Monospace">
+FrmMain.ACTION_SELECTED_KEY</font> to method <font face="'Courier New',Monospaced,Monospace">
+putValue</font>, respective value is stored in the action's poperties table 
+      causing a <font face="'Courier New',Monospaced,Monospace">
+      PropertyChangeEvent</font> being fired. Any listener to such events can 
+      then update its state accordingly.
+    </p>
+    <p class="heading3">
+      Interfaces
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">ToggleFontAction</font> 
+      implements interface <font face="'Courier New',Monospaced,Monospace">
+      FontComponent</font> so that its value can be changed in a standard way 
+      from other objects through methods <font face="'Courier New',Monospaced,Monospace">
+getValue</font> and <font face="'Courier New',Monospaced,Monospace">setValue</font>
+ . To always reflect proper state to components bound to <font face="'Courier New',Monospaced,Monospace">
+FontAction</font>, it implements interface <font face="'Courier New',Monospaced,Monospace">
+SHTMLAction</font> with method <font face="'Courier New',Monospaced,Monospace">
+      update</font>.
+    </p>
+    <p class="heading3">
+      Integration to FrmMain
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">initActions</font>
+       of class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      initializes three instances of <font face="'Courier New',Monospaced,Monospace">
+ToggleFontAction</font> to the central <font face="'Courier New',Monospaced,Monospace">
+commands</font> <font face="'Courier New',Monospaced,Monospace">Hashtable</font>
+ , one for <font face="'Courier New',Monospaced,Monospace">
+      CSS.Attribute.FONT_WEIGHT</font>, one for <font face="'Courier New',Monospaced,Monospace">
+CSS.Attribute.FONT_STYLE</font> and one for switching <font face="'Courier New',Monospaced,Monospace">
+CSS.Attribute.TEXT_DECORATION</font> between <font face="'Courier New',Monospaced,Monospace">
+normal</font> and <font face="'Courier New',Monospaced,Monospace">underline</font>
+ . For each of the three instances a separate action command is created in the 
+      constants list of class <font face="'Courier New',Monospaced,Monospace">
+      FrmMain</font> for proper handling in <a href="../../topic16/topic62/topic68.htm">
+dynamic menu</a> and <a href="../../topic16/topic74/topic79.htm">tool bar</a> 
+      creation.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic82.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic82.htm
new file mode 100644
index 0000000..351b1b1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic82.htm
@@ -0,0 +1,47 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Synchronizing tool bar and document
+    </p>
+    <p>
+      Font formatting controls in the tool bar not only allow to act on 
+      certain font settings in a document, they should also be used to reflect 
+      the settings at the current caret position. Class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> implements interface <font face="'Courier New',Monospaced,Monospace">
+CaretListener</font> for doing this.
+    </p>
+    <p class="heading2">
+      Method caretUpdate
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">caretUpdate</font>
+       in class <font face="'Courier New',Monospaced,Monospace">FrmMain</font> 
+      calls method <font face="'Courier New',Monospaced,Monospace">
+      updateFormatControls</font> (see below) whenever the caret changes in 
+      the curently active document. <font face="'Courier New',Monospaced,Monospace">
+updateFormatControls</font> is called by <font face="'Courier New',Monospaced,Monospace">
+FontAction</font> too because this action also changes font attributes but the 
+      caret position does not change in this case.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">caretUpdate</font> is 
+      registered with every newly opened or created document through method <font face="'Courier New',Monospaced,Monospace">
+registerDocument</font>. Method <font face="'Courier New',Monospaced,Monospace">
+unregisterDocument</font> takes care of removing any listener when a document 
+      is closed.
+    </p>
+    <p class="heading2">
+      Method updateFormatControls
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">updateFormatControls</font>
+ gets the attributes for the current caret position and calls method <font face="'Courier New',Monospaced,Monospace">
+setValue</font> of any <font face="'Courier New',Monospaced,Monospace">
+      FontComponents</font> found in the format tool bar.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic74/topic83.htm b/src/com/lightdev/app/shtm/help/topic16/topic74/topic83.htm
new file mode 100644
index 0000000..23cb1e7
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic74/topic83.htm
@@ -0,0 +1,29 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Adding a standard tool bar
+    </p>
+    <p>
+      Already having all functions of SimplyHTML as actions connected to the 
+      menu bar and having a method createToolBar with stage 3 of SimplyHTML as 
+      described previously, creating additional tool bars is done with almost 
+      no additional effort.
+    </p>
+    <p>
+      To create an additional tool bar for standard actions such as create a 
+      new document, open or save a document, for instance an additional tool 
+      bar definition in the resource bundle has been prepared.
+    </p>
+    <p>
+      The additional tool bar definition is read by calling <font face="'Courier New',Monospaced,Monospace">
+createToolBar</font> in method <font face="'Courier New',Monospaced,Monospace">
+      customizeFrame</font> of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>. The new standard tool bar then is added to the panel on top of 
+      the main frame where our font formatting tool bar is located too.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86.htm b/src/com/lightdev/app/shtm/help/topic16/topic86.htm
new file mode 100644
index 0000000..e2e83f9
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86.htm
@@ -0,0 +1,69 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Stage 4: Tables
+    </p>
+    <p>
+      Implementing support for tables is a comparably complex task because 
+      there are no special objects for a table, table row or table column 
+      inside a HTML document. Each table part is represented by elements 
+      hierarchically linked, each element having many attributes. Iterating 
+      through all cells of a table column for instance needs a special way of 
+      handling for this reason.
+    </p>
+    <p>
+      To complicate things a little, there are only comparably limited ways to 
+      manipulate table elements in a document in Java. An additional challenge 
+      is to support table borders in Java because up to J2SE 1.4, table cell 
+      rendering is not appropriate compared to existing text processors when 
+      it comes to borders.
+    </p>
+    <p>
+      This stage of SimplyHTML implements support for tables trying to solve 
+      these limitations. In the follwing chapters is described how this is 
+      done in more detail.
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic89.htm">Table manipulation parts to 
+      implement</a>
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic92.htm">Table structure in documents</a>
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic95.htm">Creating a new table</a>
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic96.htm">Enabling element and attribute 
+      changes</a>
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic100.htm">CSS shorthand properties</a>
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic91.htm">Manipulating the table structure</a>
+
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic99.htm">Enhancing cell border rendering</a>
+
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic93.htm">Changing table and cell 
+      attributes</a>
+    </p>
+    <p>
+      <a href="../topic16/topic86/topic94.htm">Caret movement in tables</a>
+    </p>
+    <p>
+      Due to the complexity of the topic the documentation does not cover all 
+      details of the resulting source code completely. The source code itself 
+      should be taken in addition to understand how the implementation is 
+      accomplished.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic100.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic100.htm
new file mode 100644
index 0000000..bf59cca
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic100.htm
@@ -0,0 +1,100 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      CSS shorthand properties
+    </p>
+    <p>
+      CSS 'shorthand properties' allow to store a group of properties in one 
+      single property which shortens the way the properties are stored. If for 
+      instance a margin should be specified for an object that margin usually 
+      applies to a certain side such as top, or left. To store individual 
+      margins for all four sides of an object one can specifiy four CSS 
+      attributes for each of the four sides or the individual properties of 
+      all four sides can be stored in one shorthand property.
+    </p>
+    <p>
+      To store values in a shorthand property, they have to follow the order 
+      top, right, bottom, left. Individual values can be omitted, if some or 
+      all values are equal. E.g. if the margin of all sides is the same, only 
+      one value needs to be stored in the shorthand property which will be 
+      taken for all four sides.
+    </p>
+    <p>
+      <i><b>Example with four equal values</b>:</i> <font face="'Courier New',Monospaced,Monospace">
+margin:0pt;</font>
+    </p>
+    <p>
+      <i><b>Example with four different values</b>:</i> <font face="'Courier New',Monospaced,Monospace">
+margin:0pt 1pt 2pt 3pt;</font>
+    </p>
+    <p class="heading3">
+      Shorthand properties used with HTML tables
+    </p>
+    <p>
+      For elements of HTML tables modeled by application SimplyHTML the 
+      following shorthand properties can be used to shorten attribute 
+      expressions inside individual tags:
+    </p>
+    <ul>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">margin</font>
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">padding</font>
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">border-width</font>
+      </li>
+      <li>
+        <font face="'Courier New',Monospaced,Monospace">border-color</font>
+      </li>
+    </ul>
+    <p class="heading2">
+      Class CombinedAttribute
+    </p>
+    <p>
+      To enable usage of shorthand properties, application SimplyHTML provides 
+      class <font face="'Courier New',Monospaced,Monospace">CombinedAttribute</font>
+ . <font face="'Courier New',Monospaced,Monospace">CombinedAttribute</font> 
+      models a CSS shorthand property by providing methods to manipulate and 
+      store four individual CSS properties in one CSS shorthand property.
+    </p>
+    <p>
+      It is used in classes <font face="'Courier New',Monospaced,Monospace">
+      SHTMLBoxPainter</font> to render table cells, <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> to manipulate tables and in <font face="'Courier New',Monospaced,Monospace">
+SHTMLWriter</font> for writing CSS shorthand properties.
+    </p>
+    <p class="heading2">
+      Transforming CSS properties to CSS shorthand properties
+    </p>
+    <p>
+      In the Java languages all CSS shorthand properties are transformed to 
+      'normal' CSS properties when HTML and CSS is modeled (in an <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> for instance). So for any CSS shorthand property four 
+      individual CSS attributes are created for an element.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">CombinedAtrribute</font> 
+      is constructed from an <font face="'Courier New',Monospaced,Monospace">
+      AttributeSet</font> which may have CSS attributes belonging to a CSS 
+      shorthand property or not, so it does not matter whether or not the 
+      model uses CSS shorthand properties. When HTML code is to be generated 
+      for HTML file creation however, 'normal' CSS properties belonging to a 
+      CSS shorthand property need to be transformed from the model to the file 
+      accordingly.
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">SHTMLWriter</font> 
+      does that by initializing a table of CSS properties for which CSS 
+      shorthand properties are to be generated. When creating HTML code, 
+      method <font face="'Courier New',Monospaced,Monospace">writeAttributes</font>
+ filters out those single CSS atributes, creates CSS shorthand properties for 
+      them, and writes out these instead.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic89.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic89.htm
new file mode 100644
index 0000000..d0f4e20
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic89.htm
@@ -0,0 +1,269 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Table manipulation parts to implement
+    </p>
+    <p>
+      Table manipulation is divided into several parts
+    </p>
+    <ul>
+      <li>
+        Table creation
+      </li>
+      <li>
+        Table content changes and caret movement
+      </li>
+      <li>
+        Table and cell attribute changes
+      </li>
+      <li>
+        Changes to the table structure
+      </li>
+    </ul>
+    <p>
+      Implementation of these parts is distributed over different parts of 
+      application SimplyHTML. The following table is a summary of changes to 
+      SimplyHTML to implement table support:
+    </p>
+    <p>
+      
+    </p>
+    <table style=" width:80%; background-color:#ffffff;">
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            <b>Class</b>
+          </p>
+        </td>
+        <td style=" text-align:left; width:50%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe6e6; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            <b>changes</b>
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            FrmMain
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            actions needed to interface table manipulation functionality with 
+            the GUI
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SHTMLEditorPane
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            table structure manipulation
+          </p>
+          <p class="table">
+            appliance of attribute changes from TableDialog
+          </p>
+          <p class="table">
+            caret movement inside tables
+          </p>
+          <p class="table">
+            keymap and actions for caret movement
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SHTMLBoxPainter
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            new class for table cell rendering
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SHTMLWriter
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            new class with own implementation of an HTML writer (replaces 
+            SHTMLWriter of former stages completely)
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SHTMLDocument
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            support for manipulation of element attributes
+          </p>
+          <p class="table">
+            additional support for removing elements
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            LengthValue
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            class to represent a CSS length value divided into value and unit
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SHTMLBlockView
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            extension of BlockView to support SHTMLTableView
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SHTMLTableView
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            extension of TableView to support individual rendering of cell 
+            borders
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            TableDialog
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            Dialog for table attribute changes
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            DialogShell
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            new common base class for dialogs of application SimplyHTML
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            AttributeComponent
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            Interface to replace interface FontComponent of former stages of 
+            SimplyHTML
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SHTMLEditorKit
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            extended ViewFactory for support of SHTMLTableView
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            BoundariesPanel
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            Panel to show and manipulate boundaries of a rectangular object 
+            such as a table cell
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            SizeSelectorPanel
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            Panel to show and manipulate a CSS size value
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            CombinedAttribute
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            Class to model CSS shorthand properties
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" text-align:left; width:30%; border-right-width:0pt; padding-right:4pt; padding-bottom:2pt; border-left-width:0pt; margin-left:1pt; margin-right:1pt; margin-bottom:1pt; background-color:#ebe7e7; padding-left:4pt; padding-top:0pt; border-bottom-width:0pt; margin-top:1pt; border-top-width:0pt;" valign="top">
+          <p class="table">
+            BorderPanel
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            Panel to show and manipulate properties of table cell borders
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p>
+      
+    </p>
+    <p>
+      As seen from above list, many classes are affected by table support in 
+      SimplyHTML. The major functionality however is in <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> and <font face="'Courier New',Monospaced,Monospace">
+      TableDialog</font>. Details of the implementation are described in the 
+      following chapters.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic91.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic91.htm
new file mode 100644
index 0000000..711d274
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic91.htm
@@ -0,0 +1,183 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Manipulating the table structure
+    </p>
+    <p>
+      Manipulation of an existing table structure is necessary for following 
+      actions
+    </p>
+    <ul>
+      <li>
+        append row
+      </li>
+      <li>
+        append column
+      </li>
+      <li>
+        insert row
+      </li>
+      <li>
+        insert column
+      </li>
+      <li>
+        delete row
+      </li>
+      <li>
+        delete column
+      </li>
+    </ul>
+    <p>
+      Each of the above table manipulations is implemented in class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> with repective methods (<font face="'Courier New',Monospaced,Monospace">
+insertTableColumn</font>, <font face="'Courier New',Monospaced,Monospace">
+      appendTableCol</font>, etc.). All table manipulation methods of class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> have following similarities.
+    </p>
+    <p class="heading3">
+      Common logic
+    </p>
+    <p>
+      Insertions and additions of rows and columns are all done by using 
+      methods <font face="'Courier New',Monospaced,Monospace">insertAfterEnd</font>
+ and <font face="'Courier New',Monospaced,Monospace">insertBeforeStart</font> 
+      of class <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font>
+ respectively. Deletions of rows and columns are both done by using methods <font face="'Courier New',Monospaced,Monospace">
+remove</font> and <font face="'Courier New',Monospaced,Monospace">
+      removeElements</font> of class <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font> respectively.
+    </p>
+    <p>
+      All table manipulation methods assume that they are called while the 
+      caret is somewhere inside a table cell. If not, they do nothing. As 
+      opposed to <a href="../../topic16/topic86/topic93.htm">attribute changes</a>
+ the table manipulation methods are designed for being called with a single 
+      action command ('delete row', 'insert column', etc.).
+    </p>
+    <p class="heading2">
+      Adding rows
+    </p>
+    <p>
+      To add a row, the current (insert) or last (append) row is copied by 
+      iterating the row and cell elements and creating an HTML string making 
+      up that element structure including attributes but without text content. 
+      The resulting HTML code is inserted before the current row element 
+      (insert) or inserted after the last row element (append) by use of 
+      method <font face="'Courier New',Monospaced,Monospace">insertAfterEnd</font>
+ and <font face="'Courier New',Monospaced,Monospace">insertBeforeStart</font> 
+      of class <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font>
+ .
+    </p>
+    <p class="heading3">
+      How it works
+    </p>
+    <p>
+      To accomplish the above functionality method <font face="'Courier New',Monospaced,Monospace">
+createNewRow</font> is shared by methods <font face="'Courier New',Monospaced,Monospace">
+insertTableRow</font> and <font face="'Courier New',Monospaced,Monospace">
+      appendTableRow</font> of class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font>. Method <font face="'Courier New',Monospaced,Monospace">
+      createNewRow</font> uses <font face="'Courier New',Monospaced,Monospace">
+      getTableRowHTML</font> of class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> to do the actual assembling of HTML code. Method <font face="'Courier New',Monospaced,Monospace">
+getTableRowHTML</font> in turn uses methods <font face="'Courier New',Monospaced,Monospace">
+startTag</font> and <font face="'Courier New',Monospaced,Monospace">endTag</font>
+ of class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic86/topic95.htm">
+SHTMLWriter</a></font> to generate HTML.
+    </p>
+    <p class="heading3">
+      Entry point for Actions
+    </p>
+    <p>
+      Methods <font face="'Courier New',Monospaced,Monospace">insertTableRow</font>
+ and <font face="'Courier New',Monospaced,Monospace">appendTableRow</font> are 
+      as well the entry points for respective actions of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> to connect this functionality with GUI elements such as menus 
+      and tool bar buttons. They both find out the table row (current or last) 
+      by determining the current table cell with the help of method <font face="'Courier New',Monospaced,Monospace">
+getCurTableCell</font>. Method <font face="'Courier New',Monospaced,Monospace">
+      getCurTableCell</font> is discussed in more detail in the chapter about 
+      how to implement a customized caret movement and key mapping.
+    </p>
+    <p class="heading2">
+      Removing rows
+    </p>
+    <p>
+      Removing a table row is comparably simple. Because a table row is 
+      represented by a single element with child elements belonging to that 
+      row only, it is sufficient to just delete this particular element from 
+      the document strucutre.
+    </p>
+    <p>
+      To remove a row method <font face="'Courier New',Monospaced,Monospace">
+      deleteTableRow</font> is called. It is as well the method used in <font face="'Courier New',Monospaced,Monospace">
+FrmMain's</font> respective action. Method <font face="'Courier New',Monospaced,Monospace">
+deleteTableRow</font> gets the row the caret currently is in and deletes it by 
+      calling method <font face="'Courier New',Monospaced,Monospace">
+      removeElement</font>.
+    </p>
+    <p class="heading2">
+      Adding columns
+    </p>
+    <p>
+      As opposed to working with rows, table columns are harder to manipulate 
+      because the cells of a column are spread over all row elements. To add a 
+      column, the same logic is used as in adding rows except that method <font face="'Courier New',Monospaced,Monospace">
+createTableColumn</font> iterates through all rows of a table working on the 
+      particular cell belonging to the column in question in each row.
+    </p>
+    <p class="heading3">
+      Retaining table width
+    </p>
+    <p>
+      Another exception is that SimplyHTML adjusts cell widths by taking half 
+      of the width of the current column for the new column. In method 
+      creatTableColumn the half width is applied to the column the new column 
+      is to be inserted before. Then the new column is created with the same 
+      width so that in total the table width did not change.
+    </p>
+    <p class="heading2">
+      Removing columns
+    </p>
+    <p>
+      To remove a column again the same logic is used as with rows but 
+      respective method <font face="'Courier New',Monospaced,Monospace">
+      deleteTableCol</font> is the most complicated of table manipulation 
+      methods.
+    </p>
+    <p class="heading3">
+      Retaining table width
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">deleteTableCol</font> 
+      first determines which column to increase in width after removal of the 
+      current column. By default the column on the left of the current column 
+      is taken. If the current column is the first in the table the column 
+      right of the current column is taken instead.
+    </p>
+    <p>
+      The method then gets the width values of both columns and finds out the 
+      sum of both widths. The sum is only taken if the unit of both width 
+      values is the same (both percent or point). If a sum could be taken, it 
+      is added to an attribute set.
+    </p>
+    <p class="heading3">
+      Removing cells
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">deleteTableCol</font> 
+      then iterates through all rows in the table removing the cell of each 
+      row belonging to the column to remove and then adds the new width to its 
+      adjacent cell left or right respectively. To remove a cell method <font face="'Courier New',Monospaced,Monospace">
+removeElements</font> of class <font face="'Courier New',Monospaced,Monospace">
+      SHTMLDocument</font> is used. For some reason I did not find out up to 
+      now why but method <font face="'Courier New',Monospaced,Monospace">remove</font>
+ of class <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font> 
+      does not work when used on the last column in a table.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic92.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic92.htm
new file mode 100644
index 0000000..53a62f1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic92.htm
@@ -0,0 +1,190 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Table structure in documents
+    </p>
+    <p>
+      As mentioned <a href="../../topic16/topic74/topic78.htm">previously</a>, 
+      Documents are modeled by <font face="'Courier New',Monospaced,Monospace">
+      Elements</font> which are hierarchically linked according to the content 
+      structure in the document. To manipulate a table structure it is 
+      necessary to know how a document models HTML code for a table.
+    </p>
+    <p>
+      In HTML a table is coded like this
+    </p>
+    <p style=" text-align:left; font-family:'Courier New',Monospaced,Monospace; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-bottom:0pt; background-color:#ffffff; margin-top:6pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><table> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:10pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><tr> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:20pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><td> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:30pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><p> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:40pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2">row 1, column 1 </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:30pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></p></font><font size="2">
+ </font>
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:20pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></td> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:20pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><td> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:30pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><p> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:40pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2">row 1, column 2 </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:30pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></p></font><font size="2">
+ </font>
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:20pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></td> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:10pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></tr> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:10pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><tr> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:20pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><td> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:30pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><p> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:40pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2">row 2, column 1 </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:30pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></p></font><font size="2">
+ </font>
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:20pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></td> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:20pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><td> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:30pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"><p> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:40pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2">row 2, column 2 </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:30pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></p></font><font size="2">
+ </font>
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:20pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></td> </font>
+
+    </p>
+    <p style=" text-align:left; font-family:Arial,Sans-Serif; font-style:normal; text-decoration:none; font-size:12pt; font-weight:normal; color:#000000; margin-left:10pt; background-color:#ffffff; margin-top:0pt;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></tr> </font>
+
+    </p>
+    <p style=" font-family:'Courier New',Monospaced,Monospace; font-size:12pt; color:#000000; margin-top:0pt; background-color:#ffffff; text-decoration:none; text-align:left; font-style:normal; font-weight:normal;" class="code">
+      <font face="'Courier New',Monospaced,Monospace" size="2"></table> </font>
+
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      Rendered inside a document above HTML code might show as follows 
+      (display differs depending on style sheet settings)
+    </p>
+    <p>
+      
+    </p>
+    <table style=" width:80%;">
+      <tr>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            row 1, column 1
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            row 1, column 2
+          </p>
+        </td>
+      </tr>
+      <tr>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            row 2, column 1
+          </p>
+        </td>
+        <td style=" width:50%;" valign="top">
+          <p class="table">
+            row 2, column 2
+          </p>
+        </td>
+      </tr>
+    </table>
+    <p>
+      
+    </p>
+    <p>
+      The element strucutre to be generated inside a document has to be built 
+      similar to the HTML code above. Above table viewed with the ElementTree 
+      class in SimplyHTML would produce a view such as the following.
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      <img src="../../images/elemTree.jpg" width="408" height="420">
+      
+    </p>
+    <p>
+      
+    </p>
+    <p>
+      To manipulate a table or its parts, an application has to work on that 
+      element strucutre and its attributes.
+    </p>
+    <p>
+      <b>Note: </b>To find out or try how a document's element structure look 
+      like, SimplyHTML's ElementTree function is quite helpful. It shows a 
+      window as shown with a tree having a node for each element in the 
+      element structure of the currently shown document. All element 
+      attributes are shown next to each tree node.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic93.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic93.htm
new file mode 100644
index 0000000..3f9c6e1
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic93.htm
@@ -0,0 +1,131 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Changing table and cell attributes
+    </p>
+    <p>
+      In the previous chapters basic methods for creating and manipulating a 
+      table <i>structure</i> are explained in detail. In this chapter it is 
+      discussed how to select and apply <i>attribute </i>changes to an 
+      existing table structure.
+    </p>
+    <p class="heading3">
+      Structural changes vs. attribute changes
+    </p>
+    <p>
+      Structural changes to a table (insert row, delete column, etc.) all can 
+      be done in a single step. To add these functions to the GUI of an 
+      application, a single menu item or tool bar button is sufficient. A GUI 
+      for table attribute changes is achieved not as easy. There are many 
+      attributes each talbe element can have and it would be very tedious to 
+      change single attributes through single menu items each.
+    </p>
+    <p>
+      Most of the time, attribute changes are to be applied as a group of 
+      changes to a group of elements as one (for instance changing all cells 
+      of one column to a certain width and background color). With class <font face="'Courier New',Monospaced,Monospace">
+TableDialog</font> a new dialog for changing table attributes is created 
+      therefore.
+    </p>
+    <p class="heading3">
+      Introducing TableDialog and DialogShell
+    </p>
+    <p>
+      It is called through new action <font face="'Courier New',Monospaced,Monospace">
+FormatTableAction</font> of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font>. With class <font face="'Courier New',Monospaced,Monospace">
+      TableDialog</font> the second formatting dialog is introduced after 
+      class <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic74/topic80.htm">
+FontDialog</a></font> which is why a new base class <font face="'Courier New',Monospaced,Monospace">
+DialogShell</font> is created too. <font face="'Courier New',Monospaced,Monospace">
+DialogShell</font> has all methods shared by dialogs of application SimplyHTML 
+      thus avoiding code redundancies.
+    </p>
+    <p class="heading2">
+      Class TableDialog
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">TableDialog</font> wraps 
+      all attributes of tables and table cells changeable in SimplyHTML into 
+      one dialog. It partly uses components already used in class <font face="'Courier New',Monospaced,Monospace">
+FontPanel</font> and partly introduces additional components.
+    </p>
+    <p class="heading3">
+      Common setting and getting of attributes
+    </p>
+    <p>
+      Class <font face="'Courier New',Monospaced,Monospace">AttributeSet</font>
+       in package <font face="'Courier New',Monospaced,Monospace">
+      javax.swing.text</font> provides a good way of grouping an arbitrary 
+      number of attributes and passing them between elements and components. 
+      For this reason application SimplyHTML uses interface <font face="'Courier New',Monospaced,Monospace">
+AttributeComponent</font> (renamend from FontComponent of stage 3) to define a 
+      common way of setting and getting attributes to and from GUI components 
+      via <font face="'Courier New',Monospaced,Monospace">AttributeSets</font>.
+    </p>
+    <p>
+      All components of <font face="'Courier New',Monospaced,Monospace">
+      TableDialog</font> are implementing interface <font face="'Courier New',Monospaced,Monospace">
+AttributeComponent</font>. They are held in two <font face="'Courier New',Monospaced,Monospace">
+Vectors</font>, one for table attributes and one for table cell attributes. 
+      Whenever a <font face="'Courier New',Monospaced,Monospace">TableDialog</font>
+ is created to reflect a current set of attributes existing for a table and 
+      table cell, simply respective attribute sets are passed to methods <font face="'Courier New',Monospaced,Monospace">
+setTableAttributes</font> and <font face="'Courier New',Monospaced,Monospace">
+      setCellAttributes</font>.
+    </p>
+    <p>
+      Both methods then iterate through the mentioned component <font face="'Courier New',Monospaced,Monospace">
+Vectors</font> calling method <font face="'Courier New',Monospaced,Monospace">
+      setValue</font> on each of their components. Each component then picks 
+      its attribute(s) from the attribute set and displays them accordingly. 
+      Similarly, attributes are returnd by <font face="'Courier New',Monospaced,Monospace">
+TableDialog</font> with methods <font face="'Courier New',Monospaced,Monospace">
+getTableAttributes</font> and <font face="'Courier New',Monospaced,Monospace">
+      getCellAttributes</font>. Again these methods iterate through the 
+      component <font face="'Courier New',Monospaced,Monospace">Vectors</font> 
+      to call method <font face="'Courier New',Monospaced,Monospace">getValue</font>
+ on each component returning attribute sets with the sum of all changed 
+      attributes.
+    </p>
+    <p class="heading3">
+      Returning only changed attributes
+    </p>
+    <p>
+      All components of <font face="'Courier New',Monospaced,Monospace">
+      TagbleDialog</font> 'remember' the original attribute value and only 
+      return an attribute when it was changed compared to that original value. 
+      This mechanism ensures only attributes being applied, that have been set 
+      through the dialog although other attributes were shown in the dialog as 
+      well. Without this mechanism always all attributes would be returned by 
+      the dialog regardless of wheteher they changed, returning only changed 
+      attributes avoids redundant storage of attributes.
+    </p>
+    <p class="heading2">
+      Applying attributes returned by TableDialog
+    </p>
+    <p>
+      To apply table attributes method <font face="'Courier New',Monospaced,Monospace">
+applyTableAttributes</font> of class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> is called. It gets the table element from the current 
+      caret position and passes it to method <font face="'Courier New',Monospaced,Monospace"><a href="../../topic16/topic86/topic96.htm">
+addAttributes</a></font> of class <font face="'Courier New',Monospaced,Monospace">
+SHTMLDocument</font> along with the attributes to apply.
+    </p>
+    <p>
+      Basically the same is done for applying cell attributes with the 
+      difference that a range of cells is passed in addition. Depending on the 
+      users choice to apply attributes to the current cell only, the current 
+      column, the current row or all cells of the table, method <font face="'Courier New',Monospaced,Monospace">
+applyCellAttributes</font> of class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> iterates through the appropriate range of table cells 
+      and calls method <font face="'Courier New',Monospaced,Monospace">
+      addAttributes</font> of class <font face="'Courier New',Monospaced,Monospace">
+SHTMLDocument</font> accordingly.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic94.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic94.htm
new file mode 100644
index 0000000..fec7189
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic94.htm
@@ -0,0 +1,72 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Caret movement in tables
+    </p>
+    <p>
+      As SimplyHTML now has all functionality to create and manipulate tables, 
+      it has to provide a way to move the caret inside a table conveniently. 
+      Most text processors usually allow to jump to the next or previous cell 
+      with the tab key while the caret is inside a table cell. Class <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> therefore has an own section of methods dealing with 
+      this kind of caret movement.
+    </p>
+    <p class="heading2">
+      Method getCurTableCell
+    </p>
+    <p>
+      With method <font face="'Courier New',Monospaced,Monospace">
+      getCurTableCell</font> the caret position inside a table is determined. 
+      It returns the cell the caret currently is in or null, if the caret is 
+      not inside a table. This is done by using method <font face="'Courier New',Monospaced,Monospace">
+findElementUp</font> of class <font face="'Courier New',Monospaced,Monospace">
+      Util</font> which looks for the next occurrence of a certain element (<font face="'Courier New',Monospaced,Monospace">
+TD</font> in this case) starting at a given element (the character element at 
+      the current position in this case).
+    </p>
+    <p>
+      This method is used in almost any table related methods.
+    </p>
+    <p class="heading2">
+      Methods getFirstTableCell and getLastTableCell
+    </p>
+    <p>
+      When the caret shall be moved from one cell of the table to another, it 
+      has to be determined if there are cells to move to from the current cell 
+      in a certain direction (previous or next). Methods <font face="'Courier New',Monospaced,Monospace">
+getFirstTableCell</font> and <font face="'Courier New',Monospaced,Monospace">
+      getLastTableCell</font> return the first and last cell in a table given 
+      any cell of that table.
+    </p>
+    <p class="heading2">
+      PrevCellAction and NextCellAction
+    </p>
+    <p>
+      Actions are used to actually move the caret from one cell to the next or 
+      previous one. Actions <font face="'Courier New',Monospaced,Monospace">
+      PrevCellAction</font> and <font face="'Courier New',Monospaced,Monospace">
+NextCellAction</font> use above methods to determine the next or previous cell 
+      to move to and then place the caret into that cell. Both actions are 
+      added to the key map of <font face="'Courier New',Monospaced,Monospace">
+      SHTMLEditorPane</font> with method <font face="'Courier New',Monospaced,Monospace">
+adjustKeyBindings</font> upon construction of the editor pane. <font face="'Courier New',Monospaced,Monospace">
+NextCellAction</font> is connected to the <font face="'Courier New',Monospaced,Monospace">
+TAB</font> key, <font face="'Courier New',Monospaced,Monospace">PrevCellAction</font>
+ is related to <font face="'Courier New',Monospaced,Monospace">SHIFT TAB</font>
+       .
+    </p>
+    <p>
+      For the case that the caret is not inside a table, both actions store 
+      the original action found in the key map for <font face="'Courier New',Monospaced,Monospace">
+TAB</font> and <font face="'Courier New',Monospaced,Monospace">SHIFT TAB</font>
+       respectively. If a table action is invoked by <font face="'Courier New',Monospaced,Monospace">
+TAB</font> or <font face="'Courier New',Monospaced,Monospace">SHIFT TAB</font> 
+      thereafter and the caret is not inside a table cell, the original action 
+      for the associated key is invoked.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic95.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic95.htm
new file mode 100644
index 0000000..0067d31
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic95.htm
@@ -0,0 +1,95 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Creating a new table
+    </p>
+    <p>
+      Compared to other table functions, to create a new table and to insert 
+      it into a document is a quite simple task. In SimplyHTML this is done 
+      with method <font face="'Courier New',Monospaced,Monospace">insertTable</font>
+ of class <font face="'Courier New',Monospaced,Monospace">SHTMLEditorPane</font>
+ (see below). This method is called by a new action of class <font face="'Courier New',Monospaced,Monospace">
+FrmMain</font> which allows this method to be connected to menus and tool bar 
+      buttons, etc.
+    </p>
+    <p class="heading2">
+      Method insertTable
+    </p>
+    <p>
+      Method <font face="'Courier New',Monospaced,Monospace">insertTable</font>
+       builds HTML code for an empty table having one row with a given number 
+      of cells. The number of cells to create is passed as a parameter so a 
+      calling method can implement a function asking the user for the desired 
+      number of table columns.
+    </p>
+    <p>
+      The generated HTML code then is inserted into the document of the <font face="'Courier New',Monospaced,Monospace">
+SHTMLEditorPane</font> by inserting it after the current paragraph element 
+      using method <font face="'Courier New',Monospaced,Monospace">
+      insertAfterEnd</font> of class <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>.
+    </p>
+    <p class="heading2">
+      Generating HTML with class SHTMLWriter
+    </p>
+    <p>
+      Package <font face="'Courier New',Monospaced,Monospace">
+      javax.swing.text.html</font> already provides classes to generate HTML 
+      for a given <font face="'Courier New',Monospaced,Monospace">Document</font>
+ . Class <font face="'Courier New',Monospaced,Monospace">HTMLWriter</font> of 
+      this package is meant for this job with the help of classes <font face="'Courier New',Monospaced,Monospace">
+AbstractWriter</font> and <font face="'Courier New',Monospaced,Monospace">
+      MinimalHTMLWriter</font>. Unfortunately these classes can not be used in 
+      the way it is needed by application SimplyHTML.
+    </p>
+    <p>
+      In stage 3 of SimplyHTML we already <a href="../../topic16/topic74/topic77.htm">
+extended HTMLWriter</a> with support to generate <font face="'Courier New',Monospaced,Monospace">
+SPAN</font> tags for character level attributes. To use the writer in the new 
+      context described here, finally it has been reimplemented completely so 
+      class <font face="'Courier New',Monospaced,Monospace">SHTMLWriter</font> 
+      now is a completely rewritten class not being a subclass of classes of 
+      the Swing package of Java anymore.
+    </p>
+    <p class="heading3">
+      Reusing methods of SHTMLWriter
+    </p>
+    <p>
+      As <font face="'Courier New',Monospaced,Monospace">SHTMLWriter</font> 
+      writes HTML code to any output writer passed as an argument, we can use 
+      it for generating an empty table as well simply by passing a <font face="'Courier New',Monospaced,Monospace">
+StringWriter</font> as the target for writing. Usually <font face="'Courier New',Monospaced,Monospace">
+SHTMLWriter</font> produces HTML based on the element structure of a given 
+      document. The methods necessary to do so however can be used to generate 
+      HTML not related to a document too.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">SHTMLWriter</font> 
+      provides two methods <font face="'Courier New',Monospaced,Monospace">
+      startTag</font> and <font face="'Courier New',Monospaced,Monospace">
+      endTag</font> which can be used to generate start and end tags as 
+      needed. Method <font face="'Courier New',Monospaced,Monospace">startTag</font>
+ accepts a set of attributes too, so start tags can be generated with 
+      appropriate HTML and CSS attributes if necessary.
+    </p>
+    <p class="heading2">
+      Using SHTMLWriter in method insertTable
+    </p>
+    <p>
+      To generate HTML for an empty table as described above, <font face="'Courier New',Monospaced,Monospace">
+SHTMLWriter</font> is instanciated to write to a new <font face="'Courier New',Monospaced,Monospace">
+StringWriter</font>. Methods <font face="'Courier New',Monospaced,Monospace">
+      startTag</font> and <font face="'Courier New',Monospaced,Monospace">
+      endTag</font> are called for the table, row and cell tags accordingly 
+      passing a set of attributes having the applicable table and cell widths. 
+      The <font face="'Courier New',Monospaced,Monospace">StringBuffer</font> 
+      of <font face="'Courier New',Monospaced,Monospace">StringWriter</font> 
+      is converted to a <font face="'Courier New',Monospaced,Monospace">String</font>
+ and inserted into the document finally.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic96.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic96.htm
new file mode 100644
index 0000000..ddc4cdc
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic96.htm
@@ -0,0 +1,66 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Enabling element and attribute changes
+    </p>
+    <p>
+      Before we take a closer look on table manipulation in the following 
+      chapters, some techniques used in application SimplyHTML for doing 
+      element and attribute changes shall be discussed here. Some functions 
+      are available through common methods in classes of package <font face="'Courier New',Monospaced,Monospace">
+javax.swing.text</font> and <font face="'Courier New',Monospaced,Monospace">
+      javax.swing.text.html</font>, others need to be enabled by own methods.
+    </p>
+    <p class="heading2">
+      Adding elements
+    </p>
+    <p>
+      To add an element such as table, row or cell tags to a document, 
+      application SimplyHTML uses methods <font face="'Courier New',Monospaced,Monospace">
+insertBeforeStart</font> and <font face="'Courier New',Monospaced,Monospace">
+      insertAfterEnd</font> of class <font face="'Courier New',Monospaced,Monospace">
+HTMLDocument</font>. These methods accept an HTML string to be inserted before 
+      or after an existing element of the document.
+    </p>
+    <p class="heading2">
+      Removing elements
+    </p>
+    <p>
+      Almost any removal from an HTML document can be done with method <font face="'Courier New',Monospaced,Monospace">
+remove</font> from class <font face="'Courier New',Monospaced,Monospace">
+      AbstractDocument</font>. Method <font face="'Courier New',Monospaced,Monospace">
+remove</font> is passed the start position inside the document and the length 
+      of the portion to remove. For some reason, this does not work on the 
+      last column of a table (explanations welcome!). An additional method <font face="'Courier New',Monospaced,Monospace">
+removeElements</font> in class <font face="'Courier New',Monospaced,Monospace">
+      SHTMLDocument</font> is provided as an additional way to remove elements 
+      working for the last table column too. This method does basically the 
+      same as <font face="'Courier New',Monospaced,Monospace">remove</font>.
+    </p>
+    <p class="heading2">
+      Changing attributes
+    </p>
+    <p>
+      Adding, removing and changing arbitrary attributes all can be done with 
+      the help of class <font face="'Courier New',Monospaced,Monospace">
+      MutableAttributeSet</font> and its subclasses. A <font face="'Courier New',Monospaced,Monospace">
+MutableAttributeSet</font> is created by getting an <font face="'Courier New',Monospaced,Monospace">
+AttributeSet</font> from an <font face="'Courier New',Monospaced,Monospace">
+      Element</font> and casting it to a <font face="'Courier New',Monospaced,Monospace">
+MutableAttributeSet</font>. Changes to that <font face="'Courier New',Monospaced,Monospace">
+MutableAttributeSet</font> then directly affect the <font face="'Courier New',Monospaced,Monospace">
+Element</font> the attributes belong to.
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font> 
+      however does not provide a way to change attributes in such way. Class <font face="'Courier New',Monospaced,Monospace">
+SHTMLDocument</font> therefore delivers a method <font face="'Courier New',Monospaced,Monospace">
+addAttributes</font> for changing attributes of an <font face="'Courier New',Monospaced,Monospace">
+Element</font> instead.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic16/topic86/topic99.htm b/src/com/lightdev/app/shtm/help/topic16/topic86/topic99.htm
new file mode 100644
index 0000000..7b7a762
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic16/topic86/topic99.htm
@@ -0,0 +1,103 @@
+<html>
+  <head>
+    <link href="../../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Enhancing cell border rendering
+    </p>
+    <p>
+      A prerequisite to manipulation of table and cell attributes as described <a href="../../topic16/topic86/topic93.htm">
+separately</a> is to provide some enhancement to the way cell borders are 
+      rendered by Java.
+    </p>
+    <p>
+      Up to J2SE 1.4 cell borders are not rendered individually and there is 
+      no way to have different colors for borders of different sides of a 
+      cell. Either a border is drawn around all sides of a table cell or no 
+      border is drawn. There is no way for example to draw a vertical border 
+      between two cells only while the other sides of these cells have no 
+      borders.
+    </p>
+    <p class="heading2">
+      Rendering mechanism
+    </p>
+    <p>
+      In general <font face="'Courier New',Monospaced,Monospace">Elements</font>
+ of an <font face="'Courier New',Monospaced,Monospace">HTMLDocument</font> are 
+      rendered through the pluggable design construct of <font face="'Courier New',Monospaced,Monospace">
+HTMLEditorKit.HTMLFactory</font>. The idea behind this design is to provide 
+      individual <font face="'Courier New',Monospaced,Monospace">Views</font> 
+      to render <font face="'Courier New',Monospaced,Monospace">Elements</font>
+       .
+    </p>
+    <p class="heading3">
+      Parts involved in cell border rendering
+    </p>
+    <p>
+      A table cell is rendered by class <font face="'Courier New',Monospaced,Monospace">
+BoxPainter</font> which is an inner class of class <font face="'Courier New',Monospaced,Monospace">
+StyleSheet. BoxPainter </font>is used in class <font face="'Courier New',Monospaced,Monospace">
+BlockView</font> which is a superclass of class <font face="'Courier New',Monospaced,Monospace">
+CellView</font>. <font face="'Courier New',Monospaced,Monospace">CellView</font>
+ in turn is an inner class of class <font face="'Courier New',Monospaced,Monospace">
+TableView</font><font face="Sans-Serif"> (terrible isn't it?).</font>
+    </p>
+    <p>
+      To change how borders are painted, <font face="'Courier New',Monospaced,Monospace">
+StyleSheet.BoxPainter</font> needs to be replaced by an own class. <font face="'Courier New',Monospaced,Monospace">
+TableView</font> could be subclassed and its <font face="'Courier New',Monospaced,Monospace">
+create</font> method could be reimplemented to provide a replacement of <font face="'Courier New',Monospaced,Monospace">
+CellView</font> replacing <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet.BoxPainter</font>.
+    </p>
+    <p class="heading2">
+      Enabling for individual border rendering
+    </p>
+    <p>
+      The constructor of <font face="'Courier New',Monospaced,Monospace">
+      TableView</font> is public but unfortunately the class itself is 
+      protected so there is no way to simply subclass <font face="'Courier New',Monospaced,Monospace">
+TableView</font> to replace the <font face="'Courier New',Monospaced,Monospace">
+ViewFactory</font> of <font face="'Courier New',Monospaced,Monospace">TableView</font>
+ with an own <font face="'Courier New',Monospaced,Monospace">CellView</font>. 
+      It is dificult to change the rendering while leaving the underlying 
+      classes untouched due to <font face="'Courier New',Monospaced,Monospace">
+      TableView</font> being protected (I did not want to write a complete new 
+      view or view factory only to change a little part - a complete new table 
+      view would be hard to write too...).
+    </p>
+    <p class="heading3">
+      Solution
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">SHTMLBoxPainter</font> 
+      is created allowing to draw borders around a table cell independently 
+      from each other. Width and color for each side are drawn independently 
+      and borders of adjacent cells are adjusted so that only one border is 
+      drawn instead of two when the adjacent cells have no margin..
+    </p>
+    <p>
+      To enable <font face="'Courier New',Monospaced,Monospace">SHTMLBoxPainter</font>
+ in place of <font face="'Courier New',Monospaced,Monospace">
+      StyleSheet.BoxPainter</font> the sources of the superclasses <font face="'Courier New',Monospaced,Monospace">
+BlockView</font> and <font face="'Courier New',Monospaced,Monospace">TableView</font>
+ are copied unchanged into new ones and only bring in <font face="'Courier New',Monospaced,Monospace">
+SHTMLBoxPainter</font> where appropriate. This is done by classes <font face="'Courier New',Monospaced,Monospace">
+SHTMLBlockView</font> and <font face="'Courier New',Monospaced,Monospace">
+      SHTMLTableView</font> respectively. Both classes had to be put into 
+      package <font face="'Courier New',Monospaced,Monospace">
+      javax.swing.text.html</font> to do so.
+    </p>
+    <p>
+      Due to class <font face="'Courier New',Monospaced,Monospace">TableView</font>
+ being protected admittedly this is an ugly solution so any other and more 
+      elegant and effortless one is welcome and highly appreciated!
+    </p>
+    <p>
+      Highly appreciated also would be an explanation why <font face="'Courier New',Monospaced,Monospace">
+TableView</font> is protected...
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic22.htm b/src/com/lightdev/app/shtm/help/topic22.htm
new file mode 100644
index 0000000..9dfabee
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic22.htm
@@ -0,0 +1,34 @@
+<html>
+  <head>
+    <link href="style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Getting started
+    </p>
+    <p>
+      Alright, you somehow found this tutorial, made it through lots of 
+      preliminary information about SimplyHTML and finally like to use it 
+      somehow. Thank you! And here is how it works:
+    </p>
+    <ol>
+      <li>
+        find out, if you meet the <a href="topic22/topic6.htm">requirements</a>
+      </li>
+      <li>
+        make sure, download and <a href="topic22/topic23.htm">installation</a> 
+        is complete (yes, you have to do it without fancy installers, but hey, 
+        relax: it is simple, even I can do it...)
+      </li>
+      <li>
+        and off you go by <a href="topic22/topic52.htm">starting the 
+        application</a>
+      </li>
+    </ol>
+    <p>
+      Seriously you should at least be familiar with this part of the 
+      documentation before you try to use SimplyHTML.
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic22/topic23.htm b/src/com/lightdev/app/shtm/help/topic22/topic23.htm
new file mode 100644
index 0000000..f0cd5ae
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic22/topic23.htm
@@ -0,0 +1,35 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Installation
+    </p>
+    <p class="heading2">
+      Java Web Start
+    </p>
+    <p>
+      No installation is necessary with Java Web Start, just go on to '<a href="../topic22/topic52.htm">
+Starting SimplyHTML</a>' when using <a href="../topic16/topic34/topic151.htm">
+      Java Web Start</a>.
+    </p>
+    <p class="heading2">
+      Traditional installation
+    </p>
+    <p>
+      Once downloaded the <a href="../topic1/topic24.htm">SimplyHTML 
+      distribution package</a> zip file
+    </p>
+    <ol>
+      <li>
+        create an arbitrary folder such as <font face="'Courier New',Monospaced,Monospace">
+C:\Programs\SimplyHTML</font>
+      </li>
+      <li>
+        extract all contents of the downloaded zip file into that folder
+      </li>
+    </ol>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic22/topic52.htm b/src/com/lightdev/app/shtm/help/topic22/topic52.htm
new file mode 100644
index 0000000..45f889c
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic22/topic52.htm
@@ -0,0 +1,99 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Starting SimplyHTML
+    </p>
+    <p class="heading2">
+      Java Web Start
+    </p>
+    <p>
+      The simplest way to run SimplyHTML is to press button 'Web Start Me Now' 
+      at <font color="#0033ff">http://www.lightdev.com/dev/sh.htm</font> . 
+      Alternately, direct your browser to <font color="#0033ff">
+      http://www.lightdev.com/shtm.jnlp</font> to achieve the same.
+    </p>
+    <p>
+      No file copying, no link or path settings, just one click.
+    </p>
+    <p class="heading2">
+      Traditional start
+    </p>
+    <p>
+      To run the executable JAR file without Java Web Start, use the following 
+      command on the command line prompt of your system
+    </p>
+    <p align="left" style=" margin-right:0; margin-left:0; margin-top:0pt; background-color:#ffffff; margin-bottom:0;">
+      (replace \ by / and omit <font face="'Courier New',Monospaced,Monospace">
+      .exe</font> on Unix or Linux systems)
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">[JRE]\bin\java.exe -jar 
+      [AppDir]\SimplyHTML.jar</font>
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">[AppDir]</font> in above 
+      command means the directory, you have installed SimplyHTML on your 
+      computer. <font face="'Courier New',Monospaced,Monospace">[JRE]</font> 
+      means the directory, the Java 2 Sandard Edition (J2SE) Runtime 
+      Environment (JRE) is stored on your computer.
+    </p>
+    <p class="standard">
+      <b>Note</b>: All paths should not contain blanks. A path such as <font face="'Courier New',Monospaced,Monospace">
+C:\Program Files\SimplyHTML </font>as the <font face="'Courier New',Monospaced,Monospace">
+<AppDir></font> will only work if it is put in quotes, such as in <font face="'Courier New',Monospaced,Monospace">
+"C:\Program Files\SimplyHTML\SimplyHTML.jar" </font>
+    </p>
+    <p class="heading2">
+      Example 1 (Windows)
+    </p>
+    <p>
+      If your JRE is in directory
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">
+      c:\programs\java\j2re1.4.0_01</font>
+    </p>
+    <p>
+      and SimplyHTML is in directory
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">c:\programs\SimplyHTML\</font>
+
+    </p>
+    <p>
+      the command to start SimplyHTML would be
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">
+      c:\programs\java\j2re1.4.0_01\bin\java.exe -jar 
+      c:\programs\SimplyHTML\SimplyHTML.jar </font>
+    </p>
+    <p class="heading2">
+      Example 2 (Linux)
+    </p>
+    <p>
+      On Linux your JRE might be on
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">
+      /usr/lib/java2/j2re1.4.0_01</font>
+    </p>
+    <p>
+      and SimplyHTML might be in
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">/opt/simplyhtml</font>
+    </p>
+    <p>
+      then the command to run SimplyHTML would be
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace">
+      /usr/lib/java2/j2re1.4.0_01/bin/java -jar /opt/simplyhtml/SimplyHTML.jar</font>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic22/topic6.htm b/src/com/lightdev/app/shtm/help/topic22/topic6.htm
new file mode 100644
index 0000000..5dd0470
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic22/topic6.htm
@@ -0,0 +1,55 @@
+<html>
+  <head>
+    <link href="../style.css" rel="stylesheet" type="text/css">
+    
+  </head>
+  <body>
+    <p class="heading1">
+      Requirements
+    </p>
+    <p class="heading2">
+      Java
+    </p>
+    <p>
+      To run SimplyHTML, a Java 2 Standard Editition (J2SE) Runtime 
+      Environment (JRE) of version <b>1.4</b> or higher is necessary. To work 
+      with the source code, a Software Development Kit (SDK) for J2SE version <b>
+1.4</b> or higher is required.
+    </p>
+    <p>
+      J2SE JRE and SDK are available at no charge at
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace" color="#0033ff">
+      http://java.sun.com/j2se/1.4</font><font color="#0033ff"> </font>
+    </p>
+    <p class="heading2">
+      JavaHelp
+    </p>
+    <p>
+      For using this tutorial as online help from out of the application, the <a href="../topic16/topic4/topic39/topic43.htm">
+JavaHelp</a> runtime extension is needed. The JavaHelp runtime extension is <u>
+      distributed with the SimplyHTML package</u> (file '<font face="'Courier New',Monospaced,Monospace">
+jhall.jar</font>'). To learn more about JavaHelp and for access to sources and 
+      API documentation of JavaHelp, please visit
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace" color="#0033ff">
+      http://java.sun.com/products/javahelp </font>
+    </p>
+    <p class="heading2">
+      Java Web Start
+    </p>
+    <p>
+      To install and run SimplyHTML directly from its home page the <a href="../topic16/topic34/topic151.htm">
+Java Web Start</a> extension is needed. Java Web Start is <u>installed 
+      together with the JRE</u> (see above) automatically. To learn more about 
+      Java Web Start technlogy and for access to sources and API 
+      documentation, please visit
+    </p>
+    <p>
+      <font face="'Courier New',Monospaced,Monospace" color="#0033ff">
+      http://java.sun.com/products/javawebstart</font>
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/help/topic73.htm b/src/com/lightdev/app/shtm/help/topic73.htm
new file mode 100644
index 0000000..18afdc2
--- /dev/null
+++ b/src/com/lightdev/app/shtm/help/topic73.htm
@@ -0,0 +1,84 @@
+<html>
+  <head>
+    <link type="text/css" href="style.css" rel="stylesheet">
+    
+  </head>
+  <body>
+    <p>
+      
+    </p>
+    <p style=" text-align:left;">
+      <img height="124" width="268" src="images/splashImage.jpg">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:bold; color:#000000; font-family:Arial,Sans-Serif; margin-left:20pt; text-decoration:none; font-style:normal; font-size:36pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:bold; color:#000000; font-family:Arial,Sans-Serif; margin-left:20pt; text-decoration:none; font-style:normal; font-size:36pt; text-align:left;">
+      Tutorial
+    </p>
+    <p>
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      Stage 11
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      April 27, 2003
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      Ulrich Hilger
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      info at lightdev.com
+    </p>
+    <p style=" margin-top:6pt; background-color:#ffffff; font-weight:normal; color:#000000; font-family:Arial,Sans-Serif; margin-left:40pt; text-decoration:none; font-style:normal; font-size:12pt; text-align:left;">
+      http://www.lightdev.com
+    </p>
+  </body>
+</html>
diff --git a/src/com/lightdev/app/shtm/package.html b/src/com/lightdev/app/shtm/package.html
new file mode 100644
index 0000000..43c0600
--- /dev/null
+++ b/src/com/lightdev/app/shtm/package.html
@@ -0,0 +1,15 @@
+<HTML>
+  <body>
+    SimplyHTML, a word processor based on Java, HTML and CSS
+
+    @author Ulrich Hilger, Dimitry Polivaev
+    @author <a href="http://simplyhtml.sourceforge.net/">http://simplyhtml.sourceforge.net/</a>
+    @author published under the terms and conditions of the
+         GNU General Public License,
+         for details see file gpl.txt in the distribution
+         package of this software
+
+    @version 0.12.2, 2007
+  </body>
+</HTML>
+
diff --git a/src/com/lightdev/app/shtm/plugin/package.html b/src/com/lightdev/app/shtm/plugin/package.html
new file mode 100644
index 0000000..70add55
--- /dev/null
+++ b/src/com/lightdev/app/shtm/plugin/package.html
@@ -0,0 +1,16 @@
+<HTML>
+  <body>
+		Components building a plug-in architecture for application
+    SimplyHTML, a word processor based on Java, HTML and CSS
+
+    @author Ulrich Hilger, Dimitry Polivaev
+    @author <a href="http://simplyhtml.sourceforge.net/">http://simplyhtml.sourceforge.net/</a>
+    @author published under the terms and conditions of the
+         GNU General Public License,
+         for details see file gpl.txt in the distribution
+         package of this software
+
+    @version 0.12.2, 2007
+  </body>
+</HTML>
+
diff --git a/src/com/lightdev/app/shtm/resources/SimplyHTML.properties b/src/com/lightdev/app/shtm/resources/SimplyHTML.properties
new file mode 100644
index 0000000..dd693ae
--- /dev/null
+++ b/src/com/lightdev/app/shtm/resources/SimplyHTML.properties
@@ -0,0 +1,421 @@
+#
+#  SimplyHTML, a word processor based on Java, HTML and CSS
+#  Copyright (C) 2002 Ulrich Hilger
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+
+#
+# SimplyHTML.properties
+#
+# resource bundle with strings for application SimplyHTML
+# - English Language (default) -
+#
+# plug-in menu definition
+#
+# this menu is defined by present plugins almost entirely
+# at least the menu label must be configured here.
+pluginLabel=Plugin
+
+# plug-in menu items
+managePluginsLabel=Manage plug-ins...
+managePluginsTip=change plug-in settings...
+
+# file menu definition
+#
+# each word (delimited by blanks) is a key for
+# menu item definitions (- = separator)
+#
+# file + 'Label' = label for file menu
+# new + 'Label' = label for 'New' menu item
+# open + 'Label' = label for 'Open' menu item
+#  etc.
+fileLabel=File
+
+#file menu items
+newLabel=New
+newTip=create new document...
+openLabel=Open...
+openTip=open a document...
+documentTitleLabel=Document title...
+setDefaultStyleRefLabel=Use existing default style sheet
+closeLabel=Close
+closeAllLabel=Close all
+saveLabel=Save
+saveAllLabel=Save all
+saveTip=save a document...
+saveAsLabel=Save as...
+exitLabel=Exit
+
+# edit menu definition
+editLabel=Edit
+
+# edit menu items
+undoLabel=Undo
+undoTip=undo
+redoLabel=Redo
+redoTip=redo
+cutLabel=Cut
+cutTip=cut
+copyLabel=Copy
+copyTip=copy
+pasteLabel=Paste
+pasteTip=paste
+pastePlainTextLabel=Paste plain text
+#pastePlainTextTip=Paste as plain text (without formatting)
+pasteHTMLLabel=Paste HTML
+selectAllLabel=Select all
+editPrefsLabel=Options...
+findReplaceLabel=Find & Replace
+findReplaceTip=find & replace
+
+#insert menu definition
+insertLabel=Insert
+#insert menu items
+insertTableLabel=Table...
+insertImageLabel=Image...
+insertImageTip=Insert image...
+# format menu definition
+formatLabel=Format
+
+# format menu items
+fontLabel=Font...
+fontTip=Format font...
+clearFormatLabel=Remove Formatting
+clearFormatTip=Remove Formatting
+fontBoldLabel=Bold
+fontBoldImage=resources/bold.gif
+fontBoldSelectedIcon=resources/bold_on.gif
+fontBoldTip=switch bold on/off
+fontItalicLabel=Italic
+fontItalicImage=resources/italic.gif
+fontItalicSelectedIcon=resources/italic_on.gif
+fontItalicTip=switch italic on/off
+fontUnderlineLabel=Underline
+fontUnderlineImage=resources/uline.gif
+fontUnderlineSelectedImage=resources/uline_on.gif
+fontColorTip=Font Color
+fontUnderlineTip=switch underline on/off
+fontStrikethroughLabel=Strikethrough
+formatTableLabel=Table...
+formatTableTip=Format Table
+toggleBulletsLabel=Bulleted List on/off
+toggleBulletsTip=Bulleted List on/off
+toggleNumbersLabel=Numbered List on/off
+toggleNumbersTip=Numbered list on/off
+formatListLabel=List...
+formatListTip=Change list format
+formatImageLabel=Image...
+formatImageTip=Edit image format
+formatParaLabel=Paragraph...
+formatParaTip=Change paragraph format
+editNamedStyleLabel=Named styles...
+editNamedStyleTip=Edit named styles
+paraAlignLeftLabel=Align Left
+paraAlignLeftTip=Set paragraph left alignment
+paraAlignCenterLabel=Align Center
+paraAlignCenterTip=Set paragraph center alignment
+paraAlignRightLabel=Align Right
+paraAlignRightTip=Set paragraph right alignment
+editLinkLabel=Link...
+editLinkTip=Change link settings...
+editAnchorsLabel=Anchors...
+editAnchorsTip=Set and change anchor links...
+
+# table menu definition
+
+# table menu items
+tableLabel=Table
+nextTableCellLabel=Next Cell
+prevTableCellLabel=Previous Cell
+insertTableRowLabel=Insert Row
+insertTableColLabel=Insert Column
+appendTableRowLabel=Append Row
+appendTableColLabel=Append Col
+deleteTableRowLabel=Delete Row
+deleteTableColLabel=Delete Column
+toggleTableHeaderCellLabel=Toggle Header Cell
+moveTableRowUpLabel = Move Row Up
+moveTableRowDownLabel = Move Row Down
+moveTableColumnLeftLabel = Move Column Left
+moveTableColumnRightLabel = Move Column Right
+
+# misc menu definition
+misc=elemTree gc test
+miscLabel=Misc
+
+# misc menu items
+elemTreeLabel=Show Element Tree
+gcLabel=Force Garbage Collection
+testLabel=Test: currently unused
+
+# help menu definition
+help=helpTopics - about
+helpLabel=Help
+
+# help menu items
+helpTopicsLabel=Help Topics
+helpTopicsTip=show help topics
+aboutLabel=About SimplyHTML...
+
+
+# About frame
+aboutFrameTitle=About this application
+
+# Font Dialog
+fontDialogTitle=Format Font
+
+# Font panel
+uLineLabel=Underline
+strikeLabel=Strikethrough
+previewLabel=Preview
+previewText=Preview text
+familyLabel=Family
+sizeLabel=Size
+plainName=plain
+boldName=bold
+italicName=italic
+boldItalicName=bold italic
+styleLabel=Style
+effectLabel=Effect
+colorLabel=Color
+foregroundLabel=Foreground:
+backgroundLabel=Background:
+noLineLabel=none
+
+# Paragraph style panel
+textIndentLabel=Indent:
+alignLabel=Alignment:
+alignLeft=left
+alignCenter=center
+alignRight=right
+valignLabel=Vert. Alignment:
+valignTop=top
+valignMiddle=middle
+valignBottom=bottom
+valignBaseline=baseline
+
+# Margin panel
+marginLabel=Outer
+paddingLabel=Inner
+
+# Table dialog
+tableDialogTitle=Format Table
+tablePanelTitle=Table format
+cellPanelTitle=Cell format
+tableWidthLabel=Width:
+tableBgColLabel=Background color:
+cellMarginTabLabel=Margin
+cellBorderTabLabel=Borders
+borderWidthLabel=Width
+borderColorLabel=Color:
+thisCellRangeLabel=this cell
+thisColRangeLabel=this column
+thisRowRangeLabel=this row
+allCellsRangeLabel=all cells
+applyCellAttrLabel=Apply to
+cellGenTabLabel=General
+
+# Paragraph style dialog
+paraStyleDialogTitle=Paragraph Style
+fontTabLabel=Font
+paraTabLabel=Paragraph
+stylePanelLabel=Named Style
+saveStyleButtonLabel=Save
+saveStyleAsButtonLabel=Save as...
+deleteStyleButtonLabel=Delete
+
+# Named style dialog
+namedStyleDialogTitle=Edit named styles
+
+# Tag names
+cTagNamePara=Paragraph
+cTagNameHead1=Heading 1
+cTagNameHead2=Heading 2
+cTagNameHead3=Heading 3
+cTagNameHead4=Heading 4
+cTagNameHead5=Heading 5
+cTagNameHead6=Heading 6
+cTagNameLink=Link
+cTagNameUL=Unordered List
+cTagNameOL=Ordered List
+
+# List dialog
+listDialogTitle=Format List
+listTypeLabel=Type:
+listPositionLabel=Position:
+listIndentTitle=Indent:
+listTypeDecimal=1.,2.,3.,4.
+listTypeLowerRoman=i.,ii.,iii.,iv.
+listTypeUpperRoman=I.,II.,III.,IV.
+listTypeLowerAlpha=a.,b.,c.,d.
+listTypeUpperAlpha=A.,B.,C.,D.
+listTypeDisc=file symbol as bullet
+listTypeCircle=round bulled
+listTypeSquare=square bullet
+listTypeNone=no bullet, no numbering
+listPosInside=inside
+listPosOutside=outside
+
+# Link dialog
+linkDialogTitle=Create / Edit Link
+linkStyleLabel=Style:
+linkTypeLabel=Type:
+linkAddressLabel=Address:
+linkBrowseLabel=Browse...
+linkAnchorLabel=Anchor:
+linkDisplayLabel=show link as
+showAsTextLabel=Text
+showAsImageLabel=Image
+linkTextLabel=Text
+linkImageLabel=Image
+emptyLinkImageLabel=Change...
+linkTypeName1=relative
+linkTypeName2=local
+linkTypeName3=WWW
+linkTypeName4=Gopher
+linkTypeName5=FTP
+linkTypeName6=Telnet
+linkTypeName7=Newsgroup
+linkTypeName8=E-Mail
+setImageLabel=Set...
+
+# Anchor dialog
+anchorDialogTitle=Edit anchors
+anchorPanelLabel=defined anchors
+docPanelLabel=Document
+addAnchorTitle=Add anchor
+addAnchorText=Name for anchor?
+
+# Element Tree Dialog
+elementTreeTitle=Element Tree
+
+# PluginManager dialog
+pluginManagerDialogTitle=Manage plug-ins
+pluginPanelTitle=Installed plugins
+deactivatePlugin=deactivate
+activatePlugin=activate
+pluginSettingsPanelTitle=Plugin settings
+togglePluginActivationCheckbox=activated
+dockLocationLabel=Dock location:
+pluginDockLocationNone=none
+pluginDockLocationTop=top
+pluginDockLocationRight=right
+pluginDockLocationBottom=bottom
+pluginDockLocationLeft=left
+
+# Preferences dialog
+prefsDialogTitle=Options
+prfShareDocResourcesLabel=this option has no function at all and is completeley obsolete
+prfLafLabel=Look and Feel:
+prefsPasteModeLabel=Default Paste Mode:
+prfWriteModeLabel=write HTML files as
+prfWriteModeHTML32Label=HTML 3.2 (e.g. JavaHelp)
+prfWriteModeHTML4Label=HTML 4
+linkDefaultStyleSheetLabel=link new documents with default style sheet
+pasteModeHTML=Paste as HTML
+pasteModePlainText=Paste as plain-text
+
+# Image dialog
+imageDialogTitle=Edit/Insert Image
+imgDirPanelTitle=Image files
+addImgBtnTitle=Add...
+delImgBtnTitle=Delete
+imgPreviewPanelTitle=Preview
+imgPropertiesPanelTitle=Properties
+imgScaleLabel=Scale:
+imgWidthLabel=Width:
+imgHeightLabel=Height:
+imgHSpaceLabel=horiz. space:
+imgVSpaceLabel=vert. space:
+imgAlignLabel=Alignment:
+imgAlignTop=top
+imgAlignMiddle=middle
+imgAlignBottom=bottom
+imgAlignLeft=left
+imgAlignCenter=center
+imgAlignRight=right
+oWidthLabel=orig. width:
+oHeightLabel=orig. height:
+imgBorderLabel=Border:
+
+# Find & replace dialog
+findReplaceDialogTitle=Find & Replace
+findNext=Find next...
+searchFromStart=Search from start
+searchFromStart.tooltip=Start searching at the top instead of at the cursor position.
+searchDown=Search down
+searchDown.tooltip=Search from top to bottom.
+wholeWordsOnly=Whole words only
+wholeWordsOnly.tooltip=Restrict matches to whole words.
+searchUp=Search up
+searchUp.tooltip=Search from bottom to top.
+matchCase=Match case
+matchCase.tooltip=Whether to honor case when matching.
+matchApproximately=Match approximately
+matchApproximately.tooltip=<html>Whether to allow approximate matches,<br/>i.e. searching for 'files' will find 'flies'.</html>
+replaceWith=Replace with:
+textToFind=Text to find:
+replace=Replace...
+searchWholeProject=Search whole project
+noMoreOccurrencesFound=no (more) occurrences found
+allOccurrencesReplaced=All occurrences replaced
+replaceThisQuery=replace this occurrence of
+replaceYes=Yes
+replaceNo=No
+replaceAll=All
+replaceDone=Done
+
+# Messages
+saveChangesQuery=Would you like to save your changes?
+confirmClosing=Confirm closing
+fileExistsQuery= already exists, overwrite it?
+confirmSaveAs=Confirm save as
+confirmDelete=Confirm delete
+deleteFileQuery=Would you really like to delete this file?
+deleteStyleQuery=Would you really like to delete this style?
+
+# Error messages
+docNameMissingError=Please specify name and location for the document through 'Save as'
+unableToUndoError=Unable to undo:
+unableToRedoError=Unable to redo:
+unableToOpenFileError=File can not be opened
+cantCreateURLError=Can not create a valid URL for\n
+helpNotFoundError=Help file could not be opened.\nPlease consult chapter 'Installation' of file 'readme.txt'
+
+# Miscellaneous text
+htmlFileDesc=HTML files
+imageFileDesc=Image files
+defaultDocName=Untitled
+cancelBtnName=Cancel
+closeBtnName=Close
+okBtnName=OK
+leftLabel=left:
+rightLabel=right:
+topLabel=top:
+bottomLabel=bottom:
+insertTableTitle=insertTable
+insertTableMsg=How many columns?
+close=Close
+standardStyleName=standard
+styleNameInputTitle=Save style
+styleNameInputText=Name of new style?
+newStyleDefaultName=new style
+docTitleTitle=Edit Document Title
+docTitleQuery=Set title to:
+layoutTabTitle=Layout view
+htmlTabTitle=HTML Code view
+printing_not_supported=Printing not supported on this java version, please upgrade
+printLabel=Print...
\ No newline at end of file
diff --git a/src/com/lightdev/app/shtm/resources/SimplyHTML_common.properties b/src/com/lightdev/app/shtm/resources/SimplyHTML_common.properties
new file mode 100644
index 0000000..1326268
--- /dev/null
+++ b/src/com/lightdev/app/shtm/resources/SimplyHTML_common.properties
@@ -0,0 +1,187 @@
+#
+#  SimplyHTML, a word processor based on Java, HTML and CSS
+#  Copyright (C) 2002 Ulrich Hilger
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+
+#
+# SimplyHTML.properties
+#
+# resource bundle with strings for application SimplyHTML
+# - English Language (default) -
+#
+# menubar definition
+#
+# each word (delimited by blanks) is a key for
+# menu definitions below
+
+menubar=file edit insert format table plugin misc help
+
+# toolbar definition
+#
+# each word (delimited by blanks) is a key for
+# an action in the tool bar (- = separator)
+
+toolBar=new open save - undo redo - cut copy paste - insertImage formatImage findReplace - helpTopics
+
+# format toolbar definition
+#
+# each word (delimited by blanks) is a key for
+# an action in the tool bar (- = separator)
+formatToolBar=fontFamily fontSize - fontBold fontItalic fontUnderline fontColor clearFormat
+
+# para toolbar definition
+#
+# each word (delimited by blanks) is a key for
+# an action in the tool bar (- = separator)
+
+paraToolBar=setTag setStyle - paraAlignLeft paraAlignCenter paraAlignRight - toggleBullets toggleNumbers
+
+# plug-in menu definition
+#
+# this menu is defined by present plugins almost entirely
+# at least the menu label must be configured here.
+plugin=managePlugins -
+
+
+# file menu definition
+#
+# each word (delimited by blanks) is a key for
+# menu item definitions (- = separator)
+#
+# file + 'Label' = label for file menu
+# new + 'Label' = label for 'New' menu item
+# open + 'Label' = label for 'Open' menu item
+#  etc.
+file=new - open - documentTitle setDefaultStyleRef - close closeAll - save saveAs saveAll - print exit
+
+#file menu items
+newImage=resources/new.gif
+openImage=resources/open.gif
+saveImage=resources/save.gif
+saveAllImage=resources/saveAll.gif
+
+# edit menu definition
+
+edit=undo redo - cut copy paste pasteOther - findReplace - selectAll - editPrefs
+popup=undo redo - cut copy paste pasteOther
+
+# edit menu items
+undoImage=resources/undo.gif
+redoImage=resources/redo.gif
+cutImage=resources/cut.gif
+copyImage=resources/copy.gif
+pasteImage=resources/paste.gif
+pasteOtherImage=resources/paste.gif
+editPrefsImage=resources/options.gif
+findReplaceImage=resources/fr.gif
+
+#insert menu definition
+insert=insertTable - insertImage
+#insert menu items
+insertTableImage=resources/table.gif
+insertImageImage=resources/image.gif
+
+# format menu definition
+format=font - formatPara paraAlignLeft paraAlignCenter paraAlignRight - editNamedStyle - formatTable - formatList toggleBullets toggleNumbers - formatImage - editLink editAnchors
+
+# format menu items
+fontImage=resources/font.gif
+clearFormatImage=resources/clearFormat.gif
+fontBoldSelectedIcon=resources/bold_on.gif
+fontItalicSelectedIcon=resources/italic_on.gif
+fontUnderlineSelectedIcon=resources/uline_on.gif
+fontColorSelectedIcon=resources/fontColor.gif
+formatTableImage=resources/fmtTab.gif
+toggleBulletsImage=resources/ul.gif
+toggleNumbersImage=resources/ol.gif
+formatParaImage=resources/fmtPara.gif
+paraAlignLeftImage=resources/algnLft.gif
+paraAlignLeftSelectedIcon=resources/algnLft_on.gif
+paraAlignCenterImage=resources/algnCtr.gif
+paraAlignCenterSelectedIcon=resources/algnCtr_on.gif
+paraAlignRightImage=resources/algnRt.gif
+paraAlignRightSelectedIcon=resources/algnRt_on.gif
+editLinkImage=resources/link.gif
+
+# table menu definition
+table=nextTableCell prevTableCell - appendTableRow appendTableCol - insertTableRow insertTableCol - deleteTableRow deleteTableCol - toggleTableHeaderCell - moveTableRowUp moveTableRowDown moveTableColumnLeft moveTableColumnRight
+
+# table menu items
+deleteTableColImage=resources/delCol.gif
+insertTableRowImage=resources/insRow.gif
+insertTableColImage=resources/insCol.gif
+deleteTableRowImage=resources/delRow.gif
+
+# misc menu definition
+misc=elemTree gc test
+
+# misc menu items
+
+# help menu definition
+help=helpTopics - about
+
+# help menu items
+helpTopicsImage=resources/help.gif
+
+# Action properties
+fontBoldImage=resources/bold.gif
+fontItalicImage=resources/italic.gif
+fontUnderlineImage=resources/uline.gif
+fontColorImage=resources/fontColor.gif
+
+# About frame
+appImage=resources/appImage.jpg
+appIcon=resources/icon_trans.gif
+
+# Splah screen
+splashImage=resources/splashImage.jpg
+
+
+# Link dialog
+linkType1=relative
+linkType2=file
+linkType3=http
+linkType4=gopher
+linkType5=ftp
+linkType6=telnet
+linkType7=news
+linkType8=mailto
+
+# Anchor dialog
+
+# Element Tree Dialog
+
+# PluginManager dialog
+
+
+# Image dialog
+
+# Find & replace dialog
+
+# Messages
+
+# Error messages
+
+# Miscellaneous text
+okBtnName=OK
+standardStyleName=standard
+
+# not use shtml standard style for new documents
+use_std_styles=false
+
+approximate_search_threshold = 0.65
+
diff --git a/src/com/lightdev/app/shtm/resources/SimplyHTML_de.properties b/src/com/lightdev/app/shtm/resources/SimplyHTML_de.properties
new file mode 100644
index 0000000..e1c5f10
--- /dev/null
+++ b/src/com/lightdev/app/shtm/resources/SimplyHTML_de.properties
@@ -0,0 +1,410 @@
+#
+#  SimplyHTML, a word processor based on Java, HTML and CSS
+#  Copyright (C) 2002 Ulrich Hilger
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+
+#
+# SimplyHTML_de.properties
+#
+# resource bundle with strings for application SimplyHTML
+#  - German Language -
+#
+# plug-in menu definition
+#
+# this menu is defined by present plugins almost entirely
+# at least the menu label must be configured here.
+pluginLabel=Plugin
+# plug-in menu items
+managePluginsLabel=Plug-ins verwalten...
+managePluginsTip=Plug-in Einstellungen \u00e4ndern...
+
+# file menu definition
+#
+# each word (delimited by blanks) is a key for
+# menu item definitions (- = separator)
+#
+# file + 'Label' = label for file menu
+# new + 'Label' = label for 'New' menu item
+# open + 'Label' = label for 'Open' menu item
+#  etc.
+fileLabel=Datei
+
+#file menu items
+newLabel=Neu
+newTip=neues Dokument erzeugen...
+openLabel=\u00d6ffnen...
+openTip=Dokument \u00f6ffnen...
+documentTitleLabel=Dokumenttitel...
+setDefaultStyleRefLabel=Bestehende Standard-Formatvorlage verwenden
+closeLabel=Schlie\u00dfen
+closeAllLabel=Alle Schlie\u00dfen
+saveLabel=Sichern
+saveAllLabel=Alle sichern
+saveTip=Dokument speichern...
+saveAsLabel=Sichern unter...
+exitLabel=Beenden
+
+# edit menu definition
+editLabel=Bearbeiten
+
+# edit menu items
+undoLabel=R\u00fcckg\u00e4ngig
+undoTip=R\u00fcckg\u00e4ngig
+redoLabel=Wiederholen
+redoTip=Wiederholen
+cutLabel=Ausschneiden
+cutTip=Ausschneiden
+copyLabel=Kopieren
+copyTip=Kopieren
+pasteLabel=Einf\u00fcgen
+pasteTip=Einf\u00fcgen
+pastePlainTextLabel=Einf\u00fcgen als Text
+pasteHTMLLabel=Einf\u00fcgen als HTML
+pastePlainTextTip=Einf\u00fcgen als Text (ohne Formatierung)
+selectAllLabel=Alles Ausw\u00e4hlen
+editPrefsLabel=Optionen...
+findReplaceLabel=Suchen & Ersetzen
+findReplaceTip=Suchen & Ersetzen
+
+#insert menu definition
+insertLabel=Einf\u00fcgen
+#insert menu items
+insertTableLabel=Tabelle Einf\u00fcgen...
+insertImageLabel=Bild...
+insertImageTip=Bild Einfügen...
+# format menu definition
+formatLabel=Format
+
+# format menu items
+fontLabel=Zeichen...
+fontTip=Zeichen formatieren...
+clearFormatLabel=Formattierung l\u00f6schen
+clearFormatTip=Formattierung l\u00f6schen
+fontBoldLabel=Fett
+fontBoldImage=resources/bold.gif
+fontBoldSelectedIcon=resources/bold_on.gif
+fontBoldTip=fett an- und ausschalten
+fontItalicLabel=Kursiv
+fontItalicImage=resources/italic.gif
+fontItalicSelectedIcon=resources/italic_on.gif
+fontItalicTip=kursiv an- und ausschalten
+fontUnderlineLabel=Unterstreichung
+fontUnderlineImage=resources/uline.gif
+fontUnderlineTip=unterstreichen an- und ausschalten
+fontColorTip=Textfarbe
+formatTableLabel=Tabelle...
+formatTableTip=Tabelle formatieren...
+toggleBulletsLabel=Aufz\u00e4hlung ein/aus
+toggleBulletsTip=Aufz\u00e4hlung ein/aus
+toggleNumbersLabel=Numerierung ein/aus
+toggleNumbersTip=Numerierung ein/aus
+formatListLabel=Liste...
+formatListTip=Listenformat \u00e4ndern
+formatParaLabel=Absatz...
+formatParaTip=Absatzformat \u00e4ndern
+editNamedStyleLabel=Formatvorlage...
+editNamedStyleTip=Formatvorlagen bearbeiten
+paraAlignLeftLabel=Linksb\u00fcndig
+paraAlignLeftTip=Paragraph linksb\u00fcndig ausrichten
+paraAlignCenterLabel=Zentriert
+paraAlignCenterTip=Paragraph zentriert ausrichten
+paraAlignRightLabel=Rechtsb\u00fcndig
+paraAlignRightTip=Paragraph rechtsb\u00fcndig ausrichten
+editLinkLabel=Verkn\u00fcpfung...
+editLinkTip=Verkn\u00fcpfung bearbeiten...
+editAnchorsLabel=Anker...
+editAnchorsTip=Anker setzen und \u00e4ndern...
+
+# table menu definition
+
+# table menu items
+tableLabel=Tabelle
+nextTableCellLabel=N\u00e4chste Zelle
+prevTableCellLabel=Vorige Zelle
+insertTableRowLabel=Zeile einf\u00fcgen
+insertTableColLabel=Spalte einf\u00fcgen
+appendTableRowLabel=Zeile anh\u00e4ngen
+appendTableColLabel=Spalte anh\u00e4ngen
+deleteTableRowLabel=Zeile l\u00f6schen
+deleteTableColLabel=Spalte l\u00f6schen
+
+# misc menu definition
+misc=elemTree gc test
+miscLabel=Verschiedenes
+
+# misc menu items
+elemTreeLabel=Elementbaum
+gcLabel=Garbage Collection
+testLabel=Test: derzeit unbenutzt
+
+# help menu definition
+help=helpTopics - about
+helpLabel=Hilfe
+
+# help menu items
+helpTopicsLabel=Hilfethemen
+helpTopicsTip=Hilfethemen
+aboutLabel=\u00dcber SimplyHTML...
+
+
+# About frame
+aboutFrameTitle=\u00dcber dieses Programm
+
+# Font dialog
+fontDialogTitle=Zeichen formatieren
+
+# Font panel
+uLineLabel=Unterstrichen
+strikeLabel=Durchgestrichen
+previewLabel=Vorschau
+previewText=Dies ist ein Test
+familyLabel=Familie
+sizeLabel=Gr\u00f6\u00dfe
+plainName=Standard
+boldName=fett
+italicName=kursiv
+boldItalicName=fett kursiv
+styleLabel=Stil
+effectLabel=Effekt
+colorLabel=Farbe
+foregroundLabel=Vordergrund:
+backgroundLabel=Hintergrund:
+noLineLabel=kein
+
+# Paragraph style panel
+textIndentLabel=Einr\u00fcckung:
+alignLabel=Ausrichtung:
+alignLeft=links
+alignCenter=zentriert
+alignRight=rechts
+valignLabel=Vert. Ausrichtung:
+valignTop=oben
+valignMiddle=mittig
+valignBottom=unten
+valignBaseline=an Basislinie
+
+# Margin panel
+marginLabel=Au\u00dfen
+paddingLabel=Innen
+
+# Table dialog
+tableDialogTitle=Tabelle formatieren
+tablePanelTitle=Tabellenformat
+cellPanelTitle=Zellenformat
+tableWidthLabel=Breite:
+tableBgColLabel=Hintergrundfarbe:
+cellMarginTabLabel=Abstand
+cellBorderTabLabel=Rahmen
+borderWidthLabel=Breite
+borderColorLabel=Farbe:
+thisCellRangeLabel=diese Zelle
+thisColRangeLabel=diese Spalte
+thisRowRangeLabel=diese Zeile
+allCellsRangeLabel=alle Zellen
+applyCellAttrLabel=Anwenden auf
+cellGenTabLabel=Allgemein
+
+# Paragraph style dialog
+paraStyleDialogTitle=Absatzformat
+fontTabLabel=Zeichen
+paraTabLabel=Absatz
+stylePanelLabel=Formatvorlage
+saveStyleButtonLabel=Speichern
+saveStyleAsButtonLabel=Speichern unter...
+deleteStyleButtonLabel=L\u00f6schen
+
+# Named style dialog
+namedStyleDialogTitle=Formatvorlagen bearbeiten
+
+# Tag names
+cTagNamePara=Absatz
+cTagNameHead1=\u00dcberschrift 1
+cTagNameHead2=\u00dcberschrift 2
+cTagNameHead3=\u00dcberschrift 3
+cTagNameHead4=\u00dcberschrift 4
+cTagNameHead5=\u00dcberschrift 5
+cTagNameHead6=\u00dcberschrift 6
+cTagNameLink=Verkn\u00fcpfung
+cTagNameUL=Bullet-Liste
+cTagNameOL=nummerierte Liste
+
+# List dialog
+listDialogTitle=Liste formatieren
+listTypeLabel=Typ:
+listPositionLabel=Position:
+listIndentTitle=Einr\u00fcckung:
+listTypeDecimal=1.,2.,3.,4.
+listTypeLowerRoman=i.,ii.,iii.,iv.
+listTypeUpperRoman=I.,II.,III.,IV.
+listTypeLowerAlpha=a.,b.,c.,d.
+listTypeUpperAlpha=A.,B.,C.,D.
+listTypeDisc=ausgef\u00fcllter Kreis als Bulletzeichen
+listTypeCircle=leerer Kreis Bulletzeichen
+listTypeSquare=rechteckiges Bulletzeichen
+listTypeNone=kein Bulletzeichen, keine Nummerierung
+listPosInside=einger\u00fcckt
+listPosOutside=ausger\u00fcckt
+
+# Link dialog
+linkDialogTitle=Verkn\u00fcpfung erzeugen / bearbeiten
+linkStyleLabel=Format:
+linkTypeLabel=Typ:
+linkAddressLabel=Adresse:
+linkBrowseLabel=Durchsuchen...
+linkAnchorLabel=Anker:
+linkDisplayLabel=zeige Verkn\u00fcpfung als
+showAsTextLabel=Text
+showAsImageLabel=Bild
+linkTextLabel=Text
+linkImageLabel=Bild
+setImageLabel=\u00c4ndern...
+linkTypeName1=relativ
+linkTypeName2=lokal
+linkTypeName3=WWW
+linkTypeName4=Gopher
+linkTypeName5=FTP
+linkTypeName6=Telnet
+linkTypeName7=Newsgroup
+linkTypeName8=E-Mail
+setImageLabel=Set...
+
+# Anchor dialog
+anchorDialogTitle=Anker bearbeiten
+anchorPanelLabel=definierte Anker
+docPanelLabel=Dokument
+addAnchorTitle=Anker hinzuf\u00fcgen
+addAnchorText=Name des Ankers?
+
+# Element Tree Dialog
+elementTreeTitle=Elementbaum
+
+# PluginManager dialog
+pluginManagerDialogTitle=Plug-ins verwalten
+pluginPanelTitle=Installierte Plugins
+deactivatePlugin=deaktivieren
+activatePlugin=aktivieren
+pluginSettingsPanelTitle=Plugin Einstellungen
+togglePluginActivationCheckbox=aktiviert
+dockLocationLabel=Docken auf Seite:
+pluginDockLocationNone=keine
+pluginDockLocationTop=oben
+pluginDockLocationRight=rechts
+pluginDockLocationBottom=unten
+pluginDockLocationLeft=links
+
+# Preferences dialog
+prefsDialogTitle=Optionen
+prfShareDocResourcesLabel=diese Option hat absolut keine Funktion und ist deshalb v\u00f6llig obsolet
+prfLafLabel=Look and Feel:
+prefsPasteModeLabel=Standard-Einf\u00fcgemodus:
+prfWriteModeLabel=HTML Dateien speichern als
+prfWriteModeHTML32Label=HTML 3.2 (z.B. JavaHelp)
+prfWriteModeHTML4Label=HTML 4
+linkDefaultStyleSheetLabel=verwende Standard-Formatvorlage f\u00fcr neue Dokumente
+pasteModeHTML=Einf\u00fcgen als HTML
+pasteModePlainText=Einf\u00fcgen als Text
+
+# Image dialog
+imageDialogTitle=Bild bearbeiten/einf\u00fcgen
+imgDirPanelTitle=Bilddateien
+addImgBtnTitle=Hinzuf\u00fcgen...
+delImgBtnTitle=L\u00f6schen
+imgPreviewPanelTitle=Vorschau
+imgPropertiesPanelTitle=Eigenschaften
+imgScaleLabel=Skalierung:
+imgWidthLabel=Breite:
+imgHeightLabel=H\u00f6he:
+imgHSpaceLabel=horiz. Abstand:
+imgVSpaceLabel=vert. Abstand:
+imgAlignLabel=Ausrichtung:
+imgAlignTop=oben
+imgAlignMiddle=mittig
+imgAlignBottom=unten
+imgAlignLeft=links
+imgAlignCenter=zentriert
+imgAlignRight=rechts
+oWidthLabel=orig. Breite:
+oHeightLabel=orig. H\u00f6he:
+imgBorderLabel=Rahmen:
+
+# Find & replace dialog
+findReplaceDialogTitle=Suchen & Ersetzen
+findNext=Suchen...
+searchFromStart=vom Anfang aus suchen
+searchFromStart.tooltip=Von Anfang an (und nicht ab der Cursorposition) suchen.
+searchDown=nach unten suchen
+searchDown.tooltip=Von oben nach unten suchen.
+wholeWordsOnly=nur ganze Worte
+wholeWordsOnly.tooltip=Treffer auf ganze Wörter beschränken.
+searchUp=nach oben suchen
+searchUp.tooltip=Von unten nach oben suchen.
+matchCase=Gro\u00df- und Kleinschreibung beachten
+matchCase.tooltip=Gibt an, ob Groß/Kleinschreibung bei der Suche beachtet werden soll.
+matchApproximately=Approximative Suche
+matchApproximately.tooltip=<html>Gibt an, ob approximative Treffer angezeigt werden sollen,<br/>z.B. Suche nach 'files' findet 'flies'.</html>
+replaceWith=Ersetzen mit:
+textToFind=Suche Text:
+replace=Ersetzen...
+searchWholeProject=gesamtes Projekt durchsuchen
+noMoreOccurrencesFound=Keine (Weiteren) gefunden
+allOccurrencesReplaced=alle ersetzt
+replaceThisQuery=Ersetze dieses Vorkommnis von
+replaceYes=Ja
+replaceNo=Nein
+replaceAll=Alle
+replaceDone=Fertig
+
+# Messages
+saveChangesQuery=M\u00f6chten Sie die \u00c4nderungen speichern?
+confirmClosing=Schlie\u00dfen best\u00e4tigen
+fileExistsQuery= besteht bereits, \u00fcberschreiben?
+confirmSaveAs=Sichern unter best\u00e4tigen
+confirmDelete=L\u00f6schen best\u00e4tigen
+deleteFileQuery=M\u00f6chten Sie die Datei wirklich l\u00f6schen?
+deleteStyleQuery=M\u00f6chten Sie die Formatvorlage wirklich l\u00f6schen?
+
+# Error messages
+docNameMissingError=Bitte geben Sie Name und Ablageort f\u00fcr das Dokument mit Befehl 'Sichern unter' an.
+unableToUndoError=R\u00fcckg\u00e4ngig nicht m\u00f6glich:
+unableToRedoError=Wiederholen nicht m\u00f6glich:
+unableToOpenFileError=Datei kann nicht ge\u00f6ffnet werden
+cantCreateURLError=Kann keine g\u00fcltige URL erzeugen f\u00fcr\n
+helpNotFoundError=Hilfedatei konnte nicht ge\u00f6ffnet werden.\nBitte lesen Sie Kapitel 'Installation' der Datei 'readme.txt'
+
+# Miscellaneous text
+htmlFileDesc=HTML Dateien
+imageFileDesc=Bilddateien
+defaultDocName=Ohne Titel
+cancelBtnName=Abbrechen
+closeBtnName=Schlie\u00dfen
+okBtnName=OK
+leftLabel=links:
+rightLabel=rechts:
+topLabel=oben:
+bottomLabel=unten:
+insertTableTitle=Tabelle einf\u00fcgen
+insertTableMsg=Wieviele Spalten?
+close=Schliessen
+standardStyleName=standard
+styleNameInputTitle=Formatvorlage speichern
+styleNameInputText=Name der Formatvorlage?
+newStyleDefaultName=neue Formatvorlage
+docTitleTitle=Dokumenttitel bearbeiten
+docTitleQuery=Neuer Titel:
+layoutTabTitle=Layout Ansicht
+htmlTabTitle=HTML Code Ansicht
+printLabel=Drucken...
\ No newline at end of file
diff --git a/src/com/lightdev/app/shtm/resources/algnCtr.gif b/src/com/lightdev/app/shtm/resources/algnCtr.gif
new file mode 100644
index 0000000..8d24740
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/algnCtr.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/algnCtr_on.gif b/src/com/lightdev/app/shtm/resources/algnCtr_on.gif
new file mode 100644
index 0000000..5b20e78
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/algnCtr_on.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/algnLft.gif b/src/com/lightdev/app/shtm/resources/algnLft.gif
new file mode 100644
index 0000000..3da838d
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/algnLft.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/algnLft_on.gif b/src/com/lightdev/app/shtm/resources/algnLft_on.gif
new file mode 100644
index 0000000..0ae3829
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/algnLft_on.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/algnRt.gif b/src/com/lightdev/app/shtm/resources/algnRt.gif
new file mode 100644
index 0000000..0440b66
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/algnRt.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/algnRt_on.gif b/src/com/lightdev/app/shtm/resources/algnRt_on.gif
new file mode 100644
index 0000000..3f90304
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/algnRt_on.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/appIcon.gif b/src/com/lightdev/app/shtm/resources/appIcon.gif
new file mode 100644
index 0000000..6ec4266
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/appIcon.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/appImage.jpg b/src/com/lightdev/app/shtm/resources/appImage.jpg
new file mode 100644
index 0000000..c18611d
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/appImage.jpg differ
diff --git a/src/com/lightdev/app/shtm/resources/bold.gif b/src/com/lightdev/app/shtm/resources/bold.gif
new file mode 100644
index 0000000..d42d805
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/bold.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/bold_de.gif b/src/com/lightdev/app/shtm/resources/bold_de.gif
new file mode 100644
index 0000000..4c6e5a1
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/bold_de.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/bold_on.gif b/src/com/lightdev/app/shtm/resources/bold_on.gif
new file mode 100644
index 0000000..e6d561e
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/bold_on.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/bold_on_de.gif b/src/com/lightdev/app/shtm/resources/bold_on_de.gif
new file mode 100644
index 0000000..17f4ad2
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/bold_on_de.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/clearFormat.gif b/src/com/lightdev/app/shtm/resources/clearFormat.gif
new file mode 100644
index 0000000..63160d7
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/clearFormat.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/copy.gif b/src/com/lightdev/app/shtm/resources/copy.gif
new file mode 100644
index 0000000..2bab7b5
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/copy.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/cut.gif b/src/com/lightdev/app/shtm/resources/cut.gif
new file mode 100644
index 0000000..1a4cc28
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/cut.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/default.css b/src/com/lightdev/app/shtm/resources/default.css
new file mode 100644
index 0000000..54bd2d8
--- /dev/null
+++ b/src/com/lightdev/app/shtm/resources/default.css
@@ -0,0 +1,67 @@
+a { text-decoration:underline;
+    color:#0000ff; }
+
+ol { margin-top:6;
+     font-family:SansSerif, Sans-Serif;
+     margin-left:30;
+     font-size:12;
+     list-style-position:outside; }
+
+p { text-decoration:none;
+    text-indent:0;
+    font-weight:normal;
+    padding-top:0;
+    margin-top:6;
+    vertical-align:top;
+    font-style:normal;
+    font-size:12;
+    padding-right:0;
+    padding-bottom:0;
+    font-family:SansSerif, Sans-Serif;
+    padding-left:0;
+    color:#000000;
+    margin-left:0;
+    text-align:left;
+    margin-bottom:0;
+    margin-right:0; }
+
+h1 { text-decoration:none;
+     text-indent:0;
+     font-weight:bold;
+     padding-top:0;
+     margin-top:6;
+     vertical-align:top;
+     font-style:normal;
+     font-size:18;
+     padding-right:0;
+     padding-bottom:0;
+     background-color:#ffffff;
+     font-family:SansSerif, Sans-Serif;
+     padding-left:0;
+     color:#000000;
+     margin-left:0;
+     text-align:left;
+     margin-bottom:0;
+     margin-right:0; }
+
+td { padding-top:0;
+     margin-top:0;
+     border-style:solid;
+     vertical-align:top;
+     padding-bottom:0;
+     padding-right:0;
+     border-color:#000000;
+     padding-left:2;
+     text-align:left;
+     margin-left:0;
+     margin-bottom:0;
+     margin-right:0; }
+
+li { margin-top:0; }
+
+ul { margin-top:6;
+     font-size:12;
+     margin-left:30;
+     list-style-position:outside;
+     font-family:SansSerif, Sans-Serif; }
+
diff --git a/src/com/lightdev/app/shtm/resources/delCol.gif b/src/com/lightdev/app/shtm/resources/delCol.gif
new file mode 100644
index 0000000..6a86230
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/delCol.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/delRow.gif b/src/com/lightdev/app/shtm/resources/delRow.gif
new file mode 100644
index 0000000..1e55d9b
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/delRow.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/empty.gif b/src/com/lightdev/app/shtm/resources/empty.gif
new file mode 100644
index 0000000..2c0f709
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/empty.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/fmtImg.gif b/src/com/lightdev/app/shtm/resources/fmtImg.gif
new file mode 100644
index 0000000..b3f81d8
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/fmtImg.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/fmtLink.gif b/src/com/lightdev/app/shtm/resources/fmtLink.gif
new file mode 100644
index 0000000..dd7d543
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/fmtLink.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/fmtPara.gif b/src/com/lightdev/app/shtm/resources/fmtPara.gif
new file mode 100644
index 0000000..c5af95b
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/fmtPara.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/fmtTab.gif b/src/com/lightdev/app/shtm/resources/fmtTab.gif
new file mode 100644
index 0000000..ced11f9
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/fmtTab.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/font.gif b/src/com/lightdev/app/shtm/resources/font.gif
new file mode 100644
index 0000000..02078ff
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/font.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/fontColor.gif b/src/com/lightdev/app/shtm/resources/fontColor.gif
new file mode 100644
index 0000000..bc9ebc2
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/fontColor.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/fr.gif b/src/com/lightdev/app/shtm/resources/fr.gif
new file mode 100644
index 0000000..4c9b0f7
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/fr.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/gpl.txt b/src/com/lightdev/app/shtm/resources/gpl.txt
new file mode 100644
index 0000000..1bcc46f
--- /dev/null
+++ b/src/com/lightdev/app/shtm/resources/gpl.txt
@@ -0,0 +1,342 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+
diff --git a/src/com/lightdev/app/shtm/resources/help.gif b/src/com/lightdev/app/shtm/resources/help.gif
new file mode 100644
index 0000000..1da2229
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/help.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/icon_trans.gif b/src/com/lightdev/app/shtm/resources/icon_trans.gif
new file mode 100644
index 0000000..3f579d8
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/icon_trans.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/image.gif b/src/com/lightdev/app/shtm/resources/image.gif
new file mode 100644
index 0000000..1ef271c
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/image.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/insCol.gif b/src/com/lightdev/app/shtm/resources/insCol.gif
new file mode 100644
index 0000000..f51f278
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/insCol.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/insRow.gif b/src/com/lightdev/app/shtm/resources/insRow.gif
new file mode 100644
index 0000000..4c6efad
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/insRow.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/insTab.gif b/src/com/lightdev/app/shtm/resources/insTab.gif
new file mode 100644
index 0000000..dbc89ec
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/insTab.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/italic.gif b/src/com/lightdev/app/shtm/resources/italic.gif
new file mode 100644
index 0000000..f1fd75a
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/italic.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/italic_de.gif b/src/com/lightdev/app/shtm/resources/italic_de.gif
new file mode 100644
index 0000000..e42c37b
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/italic_de.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/italic_on.gif b/src/com/lightdev/app/shtm/resources/italic_on.gif
new file mode 100644
index 0000000..9078e80
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/italic_on.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/italic_on_de.gif b/src/com/lightdev/app/shtm/resources/italic_on_de.gif
new file mode 100644
index 0000000..345614b
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/italic_on_de.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/link.gif b/src/com/lightdev/app/shtm/resources/link.gif
new file mode 100644
index 0000000..a4858bc
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/link.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/new.gif b/src/com/lightdev/app/shtm/resources/new.gif
new file mode 100644
index 0000000..1d01eda
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/new.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/ol.gif b/src/com/lightdev/app/shtm/resources/ol.gif
new file mode 100644
index 0000000..e1bf0fb
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/ol.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/ol_on.gif b/src/com/lightdev/app/shtm/resources/ol_on.gif
new file mode 100644
index 0000000..9642167
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/ol_on.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/open.gif b/src/com/lightdev/app/shtm/resources/open.gif
new file mode 100644
index 0000000..2a0bef6
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/open.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/options.gif b/src/com/lightdev/app/shtm/resources/options.gif
new file mode 100644
index 0000000..ea49ba4
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/options.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/paste.gif b/src/com/lightdev/app/shtm/resources/paste.gif
new file mode 100644
index 0000000..ea46e69
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/paste.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/redo.gif b/src/com/lightdev/app/shtm/resources/redo.gif
new file mode 100644
index 0000000..afdce6c
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/redo.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/save.gif b/src/com/lightdev/app/shtm/resources/save.gif
new file mode 100644
index 0000000..109c5a1
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/save.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/saveAll.gif b/src/com/lightdev/app/shtm/resources/saveAll.gif
new file mode 100644
index 0000000..9588438
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/saveAll.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/splashImage.jpg b/src/com/lightdev/app/shtm/resources/splashImage.jpg
new file mode 100644
index 0000000..9addf64
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/splashImage.jpg differ
diff --git a/src/com/lightdev/app/shtm/resources/table.gif b/src/com/lightdev/app/shtm/resources/table.gif
new file mode 100644
index 0000000..834a549
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/table.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/tableBorders.gif b/src/com/lightdev/app/shtm/resources/tableBorders.gif
new file mode 100644
index 0000000..838275e
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/tableBorders.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/ul.gif b/src/com/lightdev/app/shtm/resources/ul.gif
new file mode 100644
index 0000000..03b6349
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/ul.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/ul_on.gif b/src/com/lightdev/app/shtm/resources/ul_on.gif
new file mode 100644
index 0000000..b42f702
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/ul_on.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/uline.gif b/src/com/lightdev/app/shtm/resources/uline.gif
new file mode 100644
index 0000000..a871d89
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/uline.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/uline_on.gif b/src/com/lightdev/app/shtm/resources/uline_on.gif
new file mode 100644
index 0000000..8756777
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/uline_on.gif differ
diff --git a/src/com/lightdev/app/shtm/resources/undo.gif b/src/com/lightdev/app/shtm/resources/undo.gif
new file mode 100644
index 0000000..6d6b319
Binary files /dev/null and b/src/com/lightdev/app/shtm/resources/undo.gif differ
diff --git a/src/com/sun/demo/ElementTreePanel.java b/src/com/sun/demo/ElementTreePanel.java
new file mode 100644
index 0000000..c7b6ff6
--- /dev/null
+++ b/src/com/sun/demo/ElementTreePanel.java
@@ -0,0 +1,567 @@
+/*
+ * @(#)ElementTreePanel.java	1.16 04/07/26 slightly modified (line 121)
+ *
+ * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * -Redistribution of source code must retain the above copyright notice, this
+ *  list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduce the above copyright notice,
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
+ * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
+ * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
+ * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
+ * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
+ * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed, licensed or intended
+ * for use in the design, construction, operation or maintenance of any
+ * nuclear facility.
+ */
+/*
+ * @(#)ElementTreePanel.java	1.16 04/07/26
+ */
+/* for use in SimplyHTML */
+package com.sun.demo;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.SwingConstants;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.StyleConstants;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+
+/**
+ * Displays a tree showing all the elements in a text Document. Selecting
+ * a node will result in reseting the selection of the JTextComponent.
+ * This also becomes a CaretListener to know when the selection has changed
+ * in the text to update the selected item in the tree.
+ *
+ * @author Scott Violet
+ * @version 1.16 07/26/04
+ */
+public class ElementTreePanel extends JPanel implements CaretListener, DocumentListener, PropertyChangeListener,
+        TreeSelectionListener {
+    /** Tree showing the documents element structure. */
+    protected JTree tree;
+    /** Text component showing elemenst for. */
+    protected JTextComponent editor;
+    /** Model for the tree. */
+    protected ElementTreeModel treeModel;
+    /** Set to true when updatin the selection. */
+    protected boolean updatingSelection;
+
+    public ElementTreePanel(final JTextComponent editor) {
+        this.editor = editor;
+        final Document document = editor.getDocument();
+        // Create the tree.
+        treeModel = new ElementTreeModel(document);
+        tree = new JTree(treeModel) {
+            public String convertValueToText(final Object value, final boolean selected, final boolean expanded,
+                                             final boolean leaf, final int row, final boolean hasFocus) {
+                // Should only happen for the root
+                if (!(value instanceof Element)) {
+                    return value.toString();
+                }
+                final Element e = (Element) value;
+                final AttributeSet as = e.getAttributes().copyAttributes();
+                String asString;
+                if (as != null) {
+                    final StringBuffer retBuffer = new StringBuffer("[");
+                    final Enumeration names = as.getAttributeNames();
+                    while (names.hasMoreElements()) {
+                        final Object nextName = names.nextElement();
+                        if (nextName != StyleConstants.ResolveAttribute) {
+                            retBuffer.append(" ");
+                            retBuffer.append(nextName);
+                            retBuffer.append("=");
+                            retBuffer.append(as.getAttribute(nextName));
+                        }
+                    }
+                    retBuffer.append(" ]");
+                    asString = retBuffer.toString();
+                }
+                else {
+                    asString = "[ ]";
+                }
+                if (e.isLeaf()) {
+                    return e.getName() + " [" + e.getStartOffset() + ", " + e.getEndOffset() + "] Attributes: "
+                            + asString;
+                }
+                return e.getName() + " [" + e.getStartOffset() + ", " + e.getEndOffset() + "] Attributes: " + asString;
+            }
+        };
+        tree.addTreeSelectionListener(this);
+        /* commented out for use in SimplyHTML */// tree.setDragEnabled(true);
+        // Don't show the root, it is fake.
+        tree.setRootVisible(false);
+        // Since the display value of every node after the insertion point
+        // changes every time the text changes and we don't generate a change
+        // event for all those nodes the display value can become off.
+        // This can be seen as '...' instead of the complete string value.
+        // This is a temporary workaround, increase the needed size by 15,
+        // hoping that will be enough.
+        tree.setCellRenderer(new DefaultTreeCellRenderer() {
+            public Dimension getPreferredSize() {
+                final Dimension retValue = super.getPreferredSize();
+                if (retValue != null) {
+                    retValue.width += 15;
+                }
+                return retValue;
+            }
+        });
+        // become a listener on the document to update the tree.
+        document.addDocumentListener(this);
+        // become a PropertyChangeListener to know when the Document has
+        // changed.
+        editor.addPropertyChangeListener(this);
+        // Become a CaretListener
+        editor.addCaretListener(this);
+        // configure the panel and frame containing it.
+        setLayout(new BorderLayout());
+        add(new JScrollPane(tree), BorderLayout.CENTER);
+        // Add a label above tree to describe what is being shown
+        final JLabel label = new JLabel("Elements that make up the current document", SwingConstants.CENTER);
+        label.setFont(new Font("Dialog", Font.BOLD, 14));
+        add(label, BorderLayout.NORTH);
+        setPreferredSize(new Dimension(400, 400));
+    }
+
+    /**
+     * Resets the JTextComponent to <code>editor</code>. This will update
+     * the tree accordingly.
+     */
+    public void setEditor(final JTextComponent editor) {
+        if (this.editor == editor) {
+            return;
+        }
+        if (this.editor != null) {
+            final Document oldDoc = this.editor.getDocument();
+            oldDoc.removeDocumentListener(this);
+            this.editor.removePropertyChangeListener(this);
+            this.editor.removeCaretListener(this);
+        }
+        this.editor = editor;
+        if (editor == null) {
+            treeModel = null;
+            tree.setModel(null);
+        }
+        else {
+            final Document newDoc = editor.getDocument();
+            newDoc.addDocumentListener(this);
+            editor.addPropertyChangeListener(this);
+            editor.addCaretListener(this);
+            treeModel = new ElementTreeModel(newDoc);
+            tree.setModel(treeModel);
+        }
+    }
+
+    // PropertyChangeListener
+    /**
+     * Invoked when a property changes. We are only interested in when the
+     * Document changes to reset the DocumentListener.
+     */
+    public void propertyChange(final PropertyChangeEvent e) {
+        if (e.getSource() == getEditor() && e.getPropertyName().equals("document")) {
+            getEditor();
+            final Document oldDoc = (Document) e.getOldValue();
+            final Document newDoc = (Document) e.getNewValue();
+            // Reset the DocumentListener
+            oldDoc.removeDocumentListener(this);
+            newDoc.addDocumentListener(this);
+            // Recreate the TreeModel.
+            treeModel = new ElementTreeModel(newDoc);
+            tree.setModel(treeModel);
+        }
+    }
+
+    // DocumentListener
+    /**
+     * Gives notification that there was an insert into the document.  The
+     * given range bounds the freshly inserted region.
+     *
+     * @param e the document event
+     */
+    public void insertUpdate(final DocumentEvent e) {
+        updateTree(e);
+    }
+
+    /**
+     * Gives notification that a portion of the document has been
+     * removed.  The range is given in terms of what the view last
+     * saw (that is, before updating sticky positions).
+     *
+     * @param e the document event
+     */
+    public void removeUpdate(final DocumentEvent e) {
+        updateTree(e);
+    }
+
+    /**
+     * Gives notification that an attribute or set of attributes changed.
+     *
+     * @param e the document event
+     */
+    public void changedUpdate(final DocumentEvent e) {
+        updateTree(e);
+    }
+
+    // CaretListener
+    /**
+     * Messaged when the selection in the editor has changed. Will update
+     * the selection in the tree.
+     */
+    public void caretUpdate(final CaretEvent e) {
+        if (!updatingSelection) {
+            getEditor();
+            final int selBegin = Math.min(e.getDot(), e.getMark());
+            final int end = Math.max(e.getDot(), e.getMark());
+            final Vector paths = new Vector();
+            final TreeModel model = getTreeModel();
+            final Object root = model.getRoot();
+            final int rootCount = model.getChildCount(root);
+            // Build an array of all the paths to all the character elements
+            // in the selection.
+            for (int counter = 0; counter < rootCount; counter++) {
+                int start = selBegin;
+                while (start <= end) {
+                    final TreePath path = getPathForIndex(start, root, (Element) model.getChild(root, counter));
+                    final Element charElement = (Element) path.getLastPathComponent();
+                    paths.addElement(path);
+                    if (start >= charElement.getEndOffset()) {
+                        start++;
+                    }
+                    else {
+                        start = charElement.getEndOffset();
+                    }
+                }
+            }
+            // If a path was found, select it (them).
+            final int numPaths = paths.size();
+            if (numPaths > 0) {
+                final TreePath[] pathArray = new TreePath[numPaths];
+                paths.copyInto(pathArray);
+                updatingSelection = true;
+                try {
+                    getTree().setSelectionPaths(pathArray);
+                    getTree().scrollPathToVisible(pathArray[0]);
+                }
+                finally {
+                    updatingSelection = false;
+                }
+            }
+        }
+    }
+
+    // TreeSelectionListener
+    /**
+      * Called whenever the value of the selection changes.
+      * @param e the event that characterizes the change.
+      */
+    public void valueChanged(final TreeSelectionEvent e) {
+        final JTree tree = getTree();
+        if (!updatingSelection && tree.getSelectionCount() == 1) {
+            final TreePath selPath = tree.getSelectionPath();
+            final Object lastPathComponent = selPath.getLastPathComponent();
+            if (!(lastPathComponent instanceof DefaultMutableTreeNode)) {
+                final Element selElement = (Element) lastPathComponent;
+                updatingSelection = true;
+                try {
+                    getEditor().select(selElement.getStartOffset(), selElement.getEndOffset());
+                }
+                finally {
+                    updatingSelection = false;
+                }
+            }
+        }
+    }
+
+    // Local methods
+    /**
+     * @return tree showing elements.
+     */
+    protected JTree getTree() {
+        return tree;
+    }
+
+    /**
+     * @return JTextComponent showing elements for.
+     */
+    protected JTextComponent getEditor() {
+        return editor;
+    }
+
+    /**
+     * @return TreeModel implementation used to represent the elements.
+     */
+    public DefaultTreeModel getTreeModel() {
+        return treeModel;
+    }
+
+    /**
+     * Updates the tree based on the event type. This will invoke either
+     * updateTree with the root element, or handleChange.
+     */
+    protected void updateTree(final DocumentEvent event) {
+        updatingSelection = true;
+        try {
+            final TreeModel model = getTreeModel();
+            final Object root = model.getRoot();
+            for (int counter = model.getChildCount(root) - 1; counter >= 0; counter--) {
+                updateTree(event, (Element) model.getChild(root, counter));
+            }
+        }
+        finally {
+            updatingSelection = false;
+        }
+    }
+
+    /**
+     * Creates TreeModelEvents based on the DocumentEvent and messages
+     * the treemodel. This recursively invokes this method with children
+     * elements.
+     * @param event indicates what elements in the tree hierarchy have
+     * changed.
+     * @param element Current element to check for changes against.
+     */
+    protected void updateTree(final DocumentEvent event, final Element element) {
+        final DocumentEvent.ElementChange ec = event.getChange(element);
+        if (ec != null) {
+            final Element[] removed = ec.getChildrenRemoved();
+            final Element[] added = ec.getChildrenAdded();
+            final int startIndex = ec.getIndex();
+            // Check for removed.
+            if (removed != null && removed.length > 0) {
+                final int[] indices = new int[removed.length];
+                for (int counter = 0; counter < removed.length; counter++) {
+                    indices[counter] = startIndex + counter;
+                }
+                getTreeModel().nodesWereRemoved((TreeNode) element, indices, removed);
+            }
+            // check for added
+            if (added != null && added.length > 0) {
+                final int[] indices = new int[added.length];
+                for (int counter = 0; counter < added.length; counter++) {
+                    indices[counter] = startIndex + counter;
+                }
+                getTreeModel().nodesWereInserted((TreeNode) element, indices);
+            }
+        }
+        if (!element.isLeaf()) {
+            int startIndex = element.getElementIndex(event.getOffset());
+            final int elementCount = element.getElementCount();
+            final int endIndex = Math.min(elementCount - 1,
+                element.getElementIndex(event.getOffset() + event.getLength()));
+            if (startIndex > 0 && startIndex < elementCount
+                    && element.getElement(startIndex).getStartOffset() == event.getOffset()) {
+                // Force checking the previous element.
+                startIndex--;
+            }
+            if (startIndex != -1 && endIndex != -1) {
+                for (int counter = startIndex; counter <= endIndex; counter++) {
+                    updateTree(event, element.getElement(counter));
+                }
+            }
+        }
+        else {
+            // Element is a leaf, assume it changed
+            getTreeModel().nodeChanged((TreeNode) element);
+        }
+    }
+
+    /**
+     * Returns a TreePath to the element at <code>position</code>.
+     */
+    protected TreePath getPathForIndex(final int position, final Object root, final Element rootElement) {
+        TreePath path = new TreePath(root);
+        Element child = rootElement.getElement(rootElement.getElementIndex(position));
+        path = path.pathByAddingChild(rootElement);
+        path = path.pathByAddingChild(child);
+        while (!child.isLeaf()) {
+            child = child.getElement(child.getElementIndex(position));
+            path = path.pathByAddingChild(child);
+        }
+        return path;
+    }
+
+    /**
+     * ElementTreeModel is an implementation of TreeModel to handle displaying
+     * the Elements from a Document. AbstractDocument.AbstractElement is
+     * the default implementation used by the swing text package to implement
+     * Element, and it implements TreeNode. This makes it trivial to create
+     * a DefaultTreeModel rooted at a particular Element from the Document.
+     * Unfortunately each Document can have more than one root Element.
+     * Implying that to display all the root elements as a child of another
+     * root a fake node has be created. This class creates a fake node as
+     * the root with the children being the root elements of the Document
+     * (getRootElements).
+     * <p>This subclasses DefaultTreeModel. The majority of the TreeModel
+     * methods have been subclassed, primarily to special case the root.
+     */
+    public static class ElementTreeModel extends DefaultTreeModel {
+        protected Element[] rootElements;
+
+        public ElementTreeModel(final Document document) {
+            super(new DefaultMutableTreeNode("root"), false);
+            rootElements = document.getRootElements();
+        }
+
+        /**
+         * Returns the child of <I>parent</I> at index <I>index</I> in
+         * the parent's child array.  <I>parent</I> must be a node
+         * previously obtained from this data source. This should
+         * not return null if <i>index</i> is a valid index for
+         * <i>parent</i> (that is <i>index</i> >= 0 && <i>index</i>
+         * < getChildCount(<i>parent</i>)).
+         *
+         * @param   parent  a node in the tree, obtained from this data source
+         * @return  the child of <I>parent</I> at index <I>index</I>
+         */
+        public Object getChild(final Object parent, final int index) {
+            if (parent == root) {
+                return rootElements[index];
+            }
+            return super.getChild(parent, index);
+        }
+
+        /**
+         * Returns the number of children of <I>parent</I>.  Returns 0
+         * if the node is a leaf or if it has no children.
+         * <I>parent</I> must be a node previously obtained from this
+         * data source.
+         *
+         * @param   parent  a node in the tree, obtained from this data source
+         * @return  the number of children of the node <I>parent</I>
+         */
+        public int getChildCount(final Object parent) {
+            if (parent == root) {
+                return rootElements.length;
+            }
+            return super.getChildCount(parent);
+        }
+
+        /**
+         * Returns true if <I>node</I> is a leaf.  It is possible for
+         * this method to return false even if <I>node</I> has no
+         * children.  A directory in a filesystem, for example, may
+         * contain no files; the node representing the directory is
+         * not a leaf, but it also has no children.
+         *
+         * @param   node    a node in the tree, obtained from this data source
+         * @return  true if <I>node</I> is a leaf
+         */
+        public boolean isLeaf(final Object node) {
+            if (node == root) {
+                return false;
+            }
+            return super.isLeaf(node);
+        }
+
+        /**
+         * Returns the index of child in parent.
+         */
+        public int getIndexOfChild(final Object parent, final Object child) {
+            if (parent == root) {
+                for (int counter = rootElements.length - 1; counter >= 0; counter--) {
+                    if (rootElements[counter] == child) {
+                        return counter;
+                    }
+                }
+                return -1;
+            }
+            return super.getIndexOfChild(parent, child);
+        }
+
+        /**
+         * Invoke this method after you've changed how node is to be
+         * represented in the tree.
+         */
+        public void nodeChanged(final TreeNode node) {
+            if (listenerList != null && node != null) {
+                TreeNode parent = node.getParent();
+                if (parent == null && node != root) {
+                    parent = root;
+                }
+                if (parent != null) {
+                    final int anIndex = getIndexOfChild(parent, node);
+                    if (anIndex != -1) {
+                        final int[] cIndexs = new int[1];
+                        cIndexs[0] = anIndex;
+                        nodesChanged(parent, cIndexs);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Returns the path to a particluar node. This is recursive.
+         */
+        protected TreeNode[] getPathToRoot(final TreeNode aNode, int depth) {
+            TreeNode[] retNodes;
+            /* Check for null, in case someone passed in a null node, or
+               they passed in an element that isn't rooted at root. */
+            if (aNode == null) {
+                if (depth == 0) {
+                    return null;
+                }
+                else {
+                    retNodes = new TreeNode[depth];
+                }
+            }
+            else {
+                depth++;
+                if (aNode == root) {
+                    retNodes = new TreeNode[depth];
+                }
+                else {
+                    TreeNode parent = aNode.getParent();
+                    if (parent == null) {
+                        parent = root;
+                    }
+                    retNodes = getPathToRoot(parent, depth);
+                }
+                retNodes[retNodes.length - depth] = aNode;
+            }
+            return retNodes;
+        }
+    }
+}
diff --git a/src/com/sun/demo/ExampleFileFilter.java b/src/com/sun/demo/ExampleFileFilter.java
new file mode 100644
index 0000000..1d5fc55
--- /dev/null
+++ b/src/com/sun/demo/ExampleFileFilter.java
@@ -0,0 +1,278 @@
+/*
+ * @(#)ExampleFileFilter.java	1.8 04/07/26
+ * 
+ * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * -Redistribution of source code must retain the above copyright notice, this
+ *  list of conditions and the following disclaimer.
+ * 
+ * -Redistribution in binary form must reproduce the above copyright notice, 
+ *  this list of conditions and the following disclaimer in the documentation
+ *  and/or other materials provided with the distribution.
+ * 
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may 
+ * be used to endorse or promote products derived from this software without 
+ * specific prior written permission.
+ * 
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
+ * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
+ * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
+ * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
+ * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
+ * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ * 
+ * You acknowledge that this software is not designed, licensed or intended
+ * for use in the design, construction, operation or maintenance of any
+ * nuclear facility.
+ */
+/*
+ * @(#)ExampleFileFilter.java	1.8 04/07/26
+ */
+/* for use in SimplyHTML */
+package com.sun.demo;
+
+import java.io.File;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * A convenience implementation of FileFilter that filters out
+ * all files except for those type extensions that it knows about.
+ *
+ * Extensions are of the type ".foo", which is typically found on
+ * Windows and Unix boxes, but not on Macinthosh. Case is ignored.
+ *
+ * Example - create a new filter that filerts out all files
+ * but gif and jpg image files:
+ *
+ *     JFileChooser chooser = new JFileChooser();
+ *     ExampleFileFilter filter = new ExampleFileFilter(
+ *                   new String{"gif", "jpg"}, "JPEG & GIF Images")
+ *     chooser.addChoosableFileFilter(filter);
+ *     chooser.showOpenDialog(this);
+ *
+ * @version 1.8 07/26/04
+ * @author Jeff Dinkins
+ */
+public class ExampleFileFilter extends FileFilter {
+    private static String TYPE_UNKNOWN = "Type Unknown";
+    private static String HIDDEN_FILE = "Hidden File";
+    private Hashtable filters = null;
+    private String description = null;
+    private String fullDescription = null;
+    private boolean useExtensionsInDescription = true;
+
+    /**
+     * Creates a file filter. If no filters are added, then all
+     * files are accepted.
+     *
+     * @see #addExtension
+     */
+    public ExampleFileFilter() {
+        filters = new Hashtable();
+    }
+
+    /**
+     * Creates a file filter that accepts files with the given extension.
+     * Example: new ExampleFileFilter("jpg");
+     *
+     * @see #addExtension
+     */
+    public ExampleFileFilter(final String extension) {
+        this(extension, null);
+    }
+
+    /**
+     * Creates a file filter that accepts the given file type.
+     * Example: new ExampleFileFilter("jpg", "JPEG Image Images");
+     *
+     * Note that the "." before the extension is not needed. If
+     * provided, it will be ignored.
+     *
+     * @see #addExtension
+     */
+    public ExampleFileFilter(final String extension, final String description) {
+        this();
+        if (extension != null) {
+            addExtension(extension);
+        }
+        if (description != null) {
+            setDescription(description);
+        }
+    }
+
+    /**
+     * Creates a file filter from the given string array.
+     * Example: new ExampleFileFilter(String {"gif", "jpg"});
+     *
+     * Note that the "." before the extension is not needed adn
+     * will be ignored.
+     *
+     * @see #addExtension
+     */
+    public ExampleFileFilter(final String[] filters) {
+        this(filters, null);
+    }
+
+    /**
+     * Creates a file filter from the given string array and description.
+     * Example: new ExampleFileFilter(String {"gif", "jpg"}, "Gif and JPG Images");
+     *
+     * Note that the "." before the extension is not needed and will be ignored.
+     *
+     * @see #addExtension
+     */
+    public ExampleFileFilter(final String[] filters, final String description) {
+        this();
+        for (int i = 0; i < filters.length; i++) {
+            // add filters one by one
+            addExtension(filters[i]);
+        }
+        if (description != null) {
+            setDescription(description);
+        }
+    }
+
+    /**
+     * Return true if this file should be shown in the directory pane,
+     * false if it shouldn't.
+     *
+     * Files that begin with "." are ignored.
+     *
+     * @see #getExtension
+     * @see FileFilter#accepts
+     */
+    public boolean accept(final File f) {
+        if (f != null) {
+            if (f.isDirectory()) {
+                return true;
+            }
+            final String extension = getExtension(f);
+            if (extension != null && filters.get(getExtension(f)) != null) {
+                return true;
+            };
+        }
+        return false;
+    }
+
+    /**
+     * Return the extension portion of the file's name .
+     *
+     * @see #getExtension
+     * @see FileFilter#accept
+     */
+    public String getExtension(final File f) {
+        if (f != null) {
+            final String filename = f.getName();
+            final int i = filename.lastIndexOf('.');
+            if (i > 0 && i < filename.length() - 1) {
+                return filename.substring(i + 1).toLowerCase();
+            };
+        }
+        return null;
+    }
+
+    /**
+     * Adds a filetype "dot" extension to filter against.
+     *
+     * For example: the following code will create a filter that filters
+     * out all files except those that end in ".jpg" and ".tif":
+     *
+     *   ExampleFileFilter filter = new ExampleFileFilter();
+     *   filter.addExtension("jpg");
+     *   filter.addExtension("tif");
+     *
+     * Note that the "." before the extension is not needed and will be ignored.
+     */
+    public void addExtension(final String extension) {
+        if (filters == null) {
+            filters = new Hashtable(5);
+        }
+        filters.put(extension.toLowerCase(), this);
+        fullDescription = null;
+    }
+
+    /**
+     * Returns the human readable description of this filter. For
+     * example: "JPEG and GIF Image Files (*.jpg, *.gif)"
+     *
+     * @see setDescription
+     * @see setExtensionListInDescription
+     * @see isExtensionListInDescription
+     * @see FileFilter#getDescription
+     */
+    public String getDescription() {
+        if (fullDescription == null) {
+            if (description == null || isExtensionListInDescription()) {
+                fullDescription = description == null ? "(" : description + " (";
+                // build the description from the extension list
+                final Enumeration extensions = filters.keys();
+                if (extensions != null) {
+                    fullDescription += "." + (String) extensions.nextElement();
+                    while (extensions.hasMoreElements()) {
+                        fullDescription += ", ." + (String) extensions.nextElement();
+                    }
+                }
+                fullDescription += ")";
+            }
+            else {
+                fullDescription = description;
+            }
+        }
+        return fullDescription;
+    }
+
+    /**
+     * Sets the human readable description of this filter. For
+     * example: filter.setDescription("Gif and JPG Images");
+     *
+     * @see setDescription
+     * @see setExtensionListInDescription
+     * @see isExtensionListInDescription
+     */
+    public void setDescription(final String description) {
+        this.description = description;
+        fullDescription = null;
+    }
+
+    /**
+     * Determines whether the extension list (.jpg, .gif, etc) should
+     * show up in the human readable description.
+     *
+     * Only relevent if a description was provided in the constructor
+     * or using setDescription();
+     *
+     * @see getDescription
+     * @see setDescription
+     * @see isExtensionListInDescription
+     */
+    public void setExtensionListInDescription(final boolean b) {
+        useExtensionsInDescription = b;
+        fullDescription = null;
+    }
+
+    /**
+     * Returns whether the extension list (.jpg, .gif, etc) should
+     * show up in the human readable description.
+     *
+     * Only relevent if a description was provided in the constructor
+     * or using setDescription();
+     *
+     * @see getDescription
+     * @see setDescription
+     * @see setExtensionListInDescription
+     */
+    public boolean isExtensionListInDescription() {
+        return useExtensionsInDescription;
+    }
+}
diff --git a/src/com/sun/demo/package.html b/src/com/sun/demo/package.html
new file mode 100644
index 0000000..143489b
--- /dev/null
+++ b/src/com/sun/demo/package.html
@@ -0,0 +1,7 @@
+<HTML>
+  <body>
+		Parts from the example classes from Sun used for application
+    SimplyHTML, a word processor based on Java, HTML and CSS
+  </body>
+</HTML>
+
diff --git a/src/de/calcom/cclib/text/FindReplaceDialog.java b/src/de/calcom/cclib/text/FindReplaceDialog.java
new file mode 100644
index 0000000..8956589
--- /dev/null
+++ b/src/de/calcom/cclib/text/FindReplaceDialog.java
@@ -0,0 +1,1080 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2003 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package de.calcom.cclib.text;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+import javax.swing.MutableComboBoxModel;
+import javax.swing.RootPaneContainer;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultHighlighter;
+import javax.swing.text.Document;
+import javax.swing.text.Highlighter;
+
+import com.lightdev.app.shtm.SHTMLPanel;
+import com.lightdev.app.shtm.Util;
+
+import de.calcom.cclib.text.PseudoDamerauLevenshtein.Alignment;
+
+/**
+ * Dialog to manage find and replace on a <code>Document</code> shown
+ * in a <code>JEditorPane</code>.
+ *
+ * <p>The component has a 'pluggable' interface about how to deal with the
+ * event that one document has been searched to the end. If it is
+ * constructed with a FindReplaceListener, it shows an additional
+ * checkbox 'Whole project' where the user can select, if a group of
+ * documents shall be searched instead of a single document.</p>
+ *
+ * <p>If only one document is searched, the dialog searches only in the
+ * document currently shown in the editor.</p>
+ *
+ * <p>By adding a FindReplaceListener listening for FindReplaceEvents,
+ * the FindReplaceDialog notifies other classes about the fact that a
+ * group of documents shall be searched instead of only the current one.</p>
+ *
+ * <p>Initially FindReplaceDialog notifies the listener that the first document
+ * in the group shall be loaded into the editor.</p>
+ *
+ * <p>After loading the first document and resuming the find or replace
+ * operation, the listener gets informed that the end of a document has been
+ * reached. A handling method for that event should cause the editor to
+ * load the next document in the group before it resumes the find or
+ * replace operation.</p>
+ *
+ * <p><b>Example for an implementation of FindReplaceListener:</b></p>
+ * <p><b>IMPORTANT: </b>the methods of the FindReplaceListener need to
+ * call either resumeOperation() or terminateOperation() on the
+ * FindReplaceDialog, that fired the FindReplaceEvent. Otherwise
+ * the FindReplaceDialog could 'hang'.</p>
+ * <p>
+ * <pre>
+ *   FindReplaceDialog frd = new FindReplaceDialog(aFrame,
+ *                             myEditorPane, new MyFindReplaceListener());
+ *
+ *   protected class MyFindReplaceListener implements FindReplaceListener {
+ *     public void getNextDocument(FindReplaceEvent e) {
+ *       if(documentsLeft()) { // documentsLeft() is a method coded somewhere else
+ *         myEditorPane.setDocument(nextDocument()); // nextDocument() is a method coded somewhere else
+ *         ((FindReplaceDialog) e.getSource()).resumeOperation();
+ *       }
+ *       else {
+ *         ((FindReplaceDialog) e.getSource()).terminateOperation();
+ *       }
+ *     }
+ *
+ *     public void getFirstDocument(FindReplaceEvent e) {
+ *       myEditorPane.setDocument(firstDocument()); // firstDocument() is a method coded somewhere else
+ *       ((FindReplaceDialog) e.getSource()).resumeOperation();
+ *     }
+ *   }
+ * </pre>
+ * </p>
+ *
+ * <p>Added i18n support for application SimplyHTML in version 1.5</p>
+ *
+ * @author Ulrich Hilger
+ * @author CalCom
+ * @author <a href="http://www.calcom.de">http://www.calcom.de</a>
+ * @author <a href="mailto:info at calcom.de">info at calcom.de</a>
+ *
+ * @version 1.5, April 27, 2003
+ *
+ * @see javax.swing.text.Document
+ * @see javax.swing.JEditorPane
+ */
+public class FindReplaceDialog extends JDialog {
+    /* ---- Constructor(s) start -----------*/
+    /**
+     * Construct a <code>FindReplaceDialog</code>.
+     *
+     * <p>Does not show the dialog window, as fields 'editor' and 'doc'
+     * have to be set separately before the dialog is operable.</p>
+     *
+     * @see javax.swing.JEditorPane
+     * @see javax.swing.text.Document
+     * @see java.awt.Frame
+     */
+    public FindReplaceDialog() {
+        try {
+            jbInit();
+            initDialogContents();
+            rememberSearchTermFromSelection();
+            pack();
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Construct a <code>FindReplaceDialog</code>.
+     *
+     * <p>Shows the dialog window modal, packed and centered over the owning
+     * <code>Frame</code> after construction.</p>
+     *
+     * <p>Using this constructor implies the dialog shall be used in mode
+     * MODE_DOCUMENT</p>
+     *
+     * @param owner  the <code>Frame</code> that owns this dialog
+     * @param editor  <code>JEditorPane</code> displaying the
+     *                    <code>Document</code> to seach in
+     *
+     * @see javax.swing.JEditorPane
+     * @see javax.swing.text.Document
+     * @see java.awt.Frame
+     */
+    public FindReplaceDialog(final Frame owner, final JEditorPane editor) {
+        setEditor(editor);
+        setMode(MODE_DOCUMENT);
+        try {
+            jbInit();
+            initDialogContents();
+            centerDialog(owner);
+            rememberSearchTermFromSelection();
+            pack();
+            setVisible(true);
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Construct a <code>FindReplaceDialog</code>.
+     *
+     * <p>Shows the dialog window modal, packed and centered over the owning
+     * <code>Frame</code> after construction.</p>
+     *
+     * <p>Using this constructor implies the dialog shall be used in mode
+     * MODE_PROJECT</p>
+     *
+     * @param owner  the <code>Frame</code> that owns this dialog
+     * @param editor  <code>JEditorPane</code> displaying the
+     *                    <code>Document</code> to seach in
+     * @param listener  listener for handling FindReplaceEvents
+     *
+     * @see javax.swing.JEditorPane
+     * @see javax.swing.text.Document
+     * @see java.awt.Frame
+     */
+    public FindReplaceDialog(final Frame owner, final JEditorPane editor, final FindReplaceListener listener) {
+        setEditor(editor);
+        setMode(MODE_PROJECT);
+        addFindReplaceListener(listener);
+        try {
+            jbInit();
+            initDialogContents();
+            centerDialog(owner);
+            rememberSearchTermFromSelection();
+            pack();
+            setVisible(true);
+        }
+        catch (final Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /* --------- Constructor(s) end ------------- */
+    
+    private void rememberSearchTermFromSelection()
+    {
+    	if (editor.getSelectedText() != null)
+    	{
+    		rememberSearchTerm(editor.getSelectedText(), jcomboSearchTerm);
+    	}
+    }
+    
+    /* --------- Event handling start ------------- */
+    /**
+     * add an event listener to this dialog.
+     *
+     * @param  listener  the event listener to add
+     */
+    public void addFindReplaceListener(final FindReplaceListener listener) {
+        listeners.addElement(listener);
+    }
+
+    /**
+     * remove an event listener from this dialog.
+     *
+     * @param  listener  the event listener to remove
+     */
+    public void removeFindReplaceListener(final FindReplaceListener listener) {
+        listeners.removeElement(listener);
+    }
+
+    /**
+     * notify listeners interested in this event that it occurred
+     *
+     * @param  node  the node, that is affected by the event
+     */
+    private void fireGetNextDocument() {
+        final Enumeration listenerList = listeners.elements();
+        while (listenerList.hasMoreElements()) {
+            ((FindReplaceListener) listenerList.nextElement()).getNextDocument(new FindReplaceEvent(this));
+        }
+    }
+
+    /**
+     * notify listeners interested in this event that it occurred
+     *
+     * @param  node  the node, that is affected by the event
+     */
+    private void fireGetFirstDocument() {
+        final Enumeration listenerList = listeners.elements();
+        while (listenerList.hasMoreElements()) {
+            ((FindReplaceListener) listenerList.nextElement()).getFirstDocument(new FindReplaceEvent(this));
+        }
+    }
+
+    /**
+     * notify listeners interested in this event that it occurred
+     *
+     * @param  node  the node, that is affected by the event
+     */
+    private void fireFindReplaceTerminated() {
+        final Enumeration listenerList = listeners.elements();
+        while (listenerList.hasMoreElements()) {
+            ((FindReplaceListener) listenerList.nextElement()).findReplaceTerminated(new FindReplaceEvent(this));
+        }
+    }
+
+    /**
+     * Resume the current operation after a getFirstDocument or getNextDocument
+     * event was fired
+     */
+    public void resumeOperation() {
+        doc = editor.getDocument();
+        findInProgress = false;
+        initFind();
+        switch (operation) {
+            case OP_FIND:
+                find();
+                break;
+            case OP_REPLACE:
+                replace();
+                break;
+        }
+    }
+
+    /**
+     * Terminate the current operation
+     */
+    public void terminateOperation() {
+        switch (operation) {
+            case OP_FIND:
+                message(Util.getResourceString(SHTMLPanel.getResources(), "noMoreOccurrencesFound"));
+                toggleState(STATE_UNLOCKED);
+                jbtnReplace.setEnabled(true);
+                break;
+            case OP_REPLACE:
+                switch (replaceChoice) {
+                    case RO_YES:
+                    case RO_NO:
+                        message(Util.getResourceString(SHTMLPanel.getResources(), "noMoreOccurrencesFound"));
+                        break;
+                    case RO_ALL:
+                        message(Util.getResourceString(SHTMLPanel.getResources(), "allOccurrencesReplaced"));
+                        break;
+                }
+                toggleState(STATE_UNLOCKED);
+                setVisible(true);
+                break;
+        }
+        operation = OP_NONE;
+        fireFindReplaceTerminated();
+    }
+
+    /**
+     * perform a find, when button 'find next' is pressed
+     */
+    private void jbtnFindNext_actionPerformed(final ActionEvent e) {
+        operation = OP_FIND;
+        jbtnReplace.setEnabled(false);
+        if (mode == MODE_PROJECT && jcbProject.isSelected() && listeners.size() > 0 && !findInProgress) {
+            fireGetFirstDocument();
+        }
+        else {
+            initFind();
+            find();
+        }
+    }
+
+    /**
+     * perform a replace, when button 'replace' is pressed
+     */
+    private void jbtnReplace_actionPerformed(final ActionEvent e) {
+        operation = OP_REPLACE;
+        replaceChoice = RO_YES;
+        setVisible(false);
+        if (mode == MODE_PROJECT && jcbProject.isSelected() && listeners.size() > 0 && !findInProgress) {
+            fireGetFirstDocument();
+        }
+        else {
+            initFind();
+            replace();
+        }
+    }
+
+    /**
+     * Cancels the current find operation and switches the dialog back to
+     * normal.
+     */
+    private void jbtnCancel_actionPerformed(final ActionEvent e) {
+        toggleState(STATE_UNLOCKED);
+        jbtnReplace.setEnabled(true);
+    }
+
+    /**
+     * When Close is pressed, store the pressed button in the result
+     * of this dialog and dispose the dialog.
+     */
+    private void jbtnClose_actionPerformed(final ActionEvent e) {
+        result = JOptionPane.OK_OPTION;
+        dispose();
+    }
+
+    /* --------- Event handling end ------------- */
+    /* --------- Getters and setters start ------------- */
+    /**
+     * Set the JEditorPane holding the document to be searched
+     *
+     * @param editor  the JEditorPane holding the document to be searched
+     *
+     * @see javax.swing.JEditorPane
+     */
+    public void setEditor(final JEditorPane editor) {
+        this.editor = editor;
+        doc = editor.getDocument();
+    }
+
+    /**
+     * Set the mode.
+     *
+     * <p>Switches between</p>
+     * <ul>
+     * <li>MODE_DOCUMENT: only the document currently viewed in the editor can be
+     *    searched</li>
+     * <li>MODE_PROJECT: An additional check box allows to choose, whether or not
+     *    the user likes to search a whole group of documents.</li>
+     * </ul>
+     *
+     * @param mode  one of MODE_DOCUMENT and MODE_PROJECT
+     */
+    public void setMode(final int mode) {
+        this.mode = mode;
+        if (mode == MODE_PROJECT) {
+            jcbProject.setVisible(true);
+        }
+        else {
+            jcbProject.setVisible(false);
+        }
+    }
+    
+	public void setSearchingBusyCursor()
+	{
+		//RootPaneContainer root = (RootPaneContainer)getTopLevelAncestor();
+		getRootPane().getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+		getRootPane().getGlassPane().setVisible(true);
+	}
+	
+	public void setSearchingDefaultCursor()
+	{
+		//RootPaneContainer root = (RootPaneContainer)getTopLevelAncestor();
+		getRootPane().getGlassPane().setCursor(Cursor.getDefaultCursor());
+		getRootPane().getGlassPane().setVisible(false);
+	}
+
+
+    /* --------- Getters and setters end ------------- */
+    /* --------- Find implementation start ------ */
+    /**
+     * Initialize the find operation by reading all relevant settings and
+     * locking the dialog window.
+     */
+    private void initFind() {
+    	//System.out.format("initFind(findInProgress=%s)\n", findInProgress);
+        if (!findInProgress) {
+            try {
+                searchText = doc.getText(0, doc.getLength());
+            }
+            catch (final Exception e) {
+                e.printStackTrace();
+            }
+            searchTerm = (String)jcomboSearchTerm.getEditor().getItem();
+            //System.out.format("initFind(): searchTerm='%s'\n", searchTerm);
+            
+            rememberSearchTerm(searchTerm, jcomboSearchTerm);
+            matchCaseSetting.getAndSet(jcbMatchCase.isSelected());
+            matchApproxSetting.getAndSet(jcbMatchApprox.isSelected());
+            
+            replacementText = jtfReplace.getText();
+            replaceDiff = replacementText.length() - searchTerm.length();
+            offset = 0;
+            if (!jcbMatchCase.isSelected()) {
+                searchTerm = searchTerm.toLowerCase();
+                searchText = searchText.toLowerCase();
+            }
+            
+            if (jcbMatchApprox.isSelected())
+            {
+            	initApproximateSearch();
+            }
+            else
+            {
+	            initExactSearch();
+            }
+            toggleState(STATE_LOCKED);
+        }
+    }
+
+	private void initExactSearch() {
+	    if (jcbStartOnTop.isSelected()) {
+	        if (jrbUp.isSelected()) {
+	            lastPosition = doc.getLength();
+	        }
+	        else {
+	            lastPosition = -1;
+	        }
+	    }
+	    else {
+	        lastPosition = editor.getSelectionStart();
+	    }
+    }
+
+	private void initApproximateSearch() {
+	    PseudoDamerauLevenshtein PDL = new PseudoDamerauLevenshtein();
+	    PDL.init(searchTerm, searchText, true, jcbMatchCase.isSelected());
+	    
+	    // get the approximate search threshold parameter (0.65 by default)
+	    // (see http://freeplane.sourceforge.net/wiki/index.php/Approximate_search)
+	    double threshold = Double.parseDouble(Util.getPreference("approximate_search_threshold", null));
+	    //System.out.format("simplyhtml: approximate_search_threshold=%.2f\n", threshold);
+	    
+	    try
+	    {
+	    	setSearchingBusyCursor();
+	    	currentApproximateMatches = PDL.computeAlignments(threshold);
+	    }
+	    finally
+	    {
+	    	setSearchingDefaultCursor();
+	    }
+	    if (jcbStartOnTop.isSelected())
+	    {
+	    	if (jrbUp.isSelected()) // search bottom-up
+	    	{
+	    		currentApproximateMatchIndex = currentApproximateMatches.size();
+	    	}
+	    	else // search top-down
+	    	{
+	    		currentApproximateMatchIndex = -1;
+	    	}
+	    }
+	    else
+	    {
+	    	int start = editor.getSelectionStart();
+	    	// get first match after 'start'
+	    	int i = 0;
+	    	currentApproximateMatchIndex = 0;
+	    	for (Alignment ali: currentApproximateMatches)
+	    	{
+	    		if (ali.getMatchStart() >= start)
+	    		{
+	    			currentApproximateMatchIndex = i - 1;
+	    			break;
+	    		}
+	    		i++;
+	    	}
+	    }
+    }
+
+    /**
+     * Initiate a find or find next operation, whatever applies. If no (more)
+     * hits are found, a message is displayed and the dialog is unlocked for a
+     * new search operation.
+     */
+    private void find() {
+        if (!doFind()) {
+            if (mode == MODE_PROJECT && jcbProject.isSelected() && listeners.size() > 0) {
+                fireGetNextDocument();
+            }
+            else {
+                terminateOperation();
+            }
+        }
+    }
+
+    /**
+     * Look for the next occurrence of the search phrase either as whole word
+     * or as part of a word, depending on the current dialog setting.
+     *
+     * <p>If the phrase is found (again), its position is 'remembered' for a
+     * possible findNext and its postion is highlighted in the underlying
+     * <code>JEditorPane</code>.
+     *
+     * @return  true, if the phrase was found (again), false if not
+     *
+     * @see javax.swing.JEditorPane
+     */
+    private boolean doFind() {
+        boolean found = false;
+        int start;
+        if (jcbMatchApprox.isSelected())
+        	start = findNextApproximately();
+        else
+        {
+        	start = findNext();
+        	if (jcbWholeWords.isSelected()) {
+        		start = findWholeWords(start);
+        	}
+        }
+        if (start >= 0) { // we found a match!
+            lastPosition = start;
+            if (jrbDown.isSelected()) {
+                start += offset;
+            }
+            editor.setCaretPosition(start);
+            editor.moveCaretPosition(start + getMatchLength());
+            editor.getCaret().setSelectionVisible(true);
+            found = true;
+        }
+//        System.out.format("doFind() => start=%d/found=%s\n",
+//        		start, found);
+        return found;
+    }
+    
+    private int getMatchLength()
+    {
+    	if (jcbMatchApprox.isSelected())
+    		return currentApproximateMatches.get(currentApproximateMatchIndex).getMatch().length();
+    	else
+    		return searchTerm.length();
+    }
+    
+    private int findNextApproximately()
+    { 
+    	int nextIndex = currentApproximateMatchIndex + (jrbUp.isSelected() ? -1 : +1);
+    	if (nextIndex < 0 || nextIndex >= currentApproximateMatches.size())
+    	{
+    		return -1;
+    	}
+    	else
+    	{
+    		currentApproximateMatchIndex = nextIndex;
+    		return currentApproximateMatches.get(nextIndex).getMatchStart();
+    	}
+    }
+
+    /**
+     * Finds the next occurrence of the search term, starting from the last position,
+     * either in the direction up or down, returning the position of the found occurrence.
+     *
+     * @return the start position of the next occurrence or
+     *                          0 if no more hits were found
+     */
+    private int findNext() {
+    	// avoid endless loop due to "" always being found
+    	if (searchTerm.length() == 0)
+    		return -1;
+    	
+        int start = -1; // -1 means not found.
+        if (jrbUp.isSelected()) {
+            if (lastPosition < doc.getLength()) {
+                start = searchText.lastIndexOf(searchTerm, lastPosition - 1);
+            }
+            else {
+                start = searchText.lastIndexOf(searchTerm, lastPosition);
+            }
+        }
+        else {
+            if (lastPosition >= 0) {
+                start = searchText.indexOf(searchTerm, lastPosition + searchTerm.length());
+            }
+            else {
+                start = searchText.indexOf(searchTerm, lastPosition);
+            }
+        }
+        return start;
+    }
+
+    /**
+     * Find the next whole word occurrence of the searched phrase from
+     * a given position.
+     *
+     * @param start  the position to start the search at
+     *
+     * @return the start position of the next occurrence or
+     *                          0 if no more hits were found
+     */
+    private int findWholeWords(int start) {
+        while ((start > 0)
+                && ((!isSeparator(searchText.charAt(start - 1))) || (!isSeparator(searchText.charAt(start
+                        + searchTerm.length()))))) {
+            lastPosition = start;
+            start = findNext();
+        }
+        return start;
+    }
+
+    /* ----------- Find implementation end ------- */
+    /* ----------- Replace implementation start ------- */
+    /**
+     * Initiate a replace operation. If no (more)
+     * hits are found, a message is displayed and the dialog is unlocked for a
+     * new search operation.
+     */
+    private void replace() {
+        while (replaceChoice != RO_DONE && doFind()) {
+            if (replaceChoice != RO_ALL) {
+                replaceChoice = getReplaceChoice();
+            }
+            switch (replaceChoice) {
+                case RO_YES:
+                    replaceOne();
+                    break;
+                case RO_ALL:
+                    replaceOne();
+                    while (doFind()) {
+                        replaceOne();
+                    }
+                    break;
+            }
+        }
+        if (mode == MODE_PROJECT && jcbProject.isSelected() && listeners.size() > 0) {
+            switch (replaceChoice) {
+                case RO_YES:
+                case RO_NO:
+                case RO_ALL:
+                    fireGetNextDocument();
+                    break;
+                case RO_DONE:
+                    terminateOperation();
+                    break;
+            }
+        }
+        else {
+            terminateOperation();
+        }
+    }
+
+    /**
+     * Show an option window asking the user for a decision about what to
+     * do with the found occurrence during a replace operation.
+     *
+     * @return the chosen option, one of RO_YES, RO_NO, RO_DONE and RO_ALL
+     */
+    private int getReplaceChoice() {
+        final String msg = Util.getResourceString(SHTMLPanel.getResources(), "replaceThisQuery") + " '" + searchTerm
+                + "'?";
+        return JOptionPane.showOptionDialog(this, msg,
+            Util.getResourceString(SHTMLPanel.getResources(), "findReplaceDialogTitle"),
+            JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, replaceOptions, null);
+    }
+
+    /**
+     * Replace the currently selected occurrence of the search phrase
+     */
+    private void replaceOne() {
+        editor.replaceSelection(replacementText);
+        offset += replaceDiff;
+    }
+
+    /* ----------- Replace implementation end ------- */
+    /* ----------- Helper methods start ------- */
+    /**
+     * Set dialog components to their inital state
+     */
+    private void initDialogContents() {
+        jbtnCancel.setEnabled(false);
+        jrbUp.setSelected(false);
+        jrbDown.setSelected(true);
+        jcbWholeWords.setSelected(false);
+        jcbMatchCase.setSelected(matchCaseSetting.get());
+        jcbMatchApprox.setSelected(matchApproxSetting.get());
+        jcbStartOnTop.setSelected(true);
+        jcbProject.setSelected(false);
+        
+        MutableComboBoxModel searchTermComboModel = (MutableComboBoxModel)jcomboSearchTerm.getModel();
+        while (searchTermComboModel.getSize() > 0)
+        {
+        	searchTermComboModel.removeElementAt(0);
+        }
+        for (final String searchTerm: searchTermHistory)
+        {
+        	searchTermComboModel.addElement(searchTerm);
+        }
+        jcomboSearchTerm.setEditable(true);
+        
+        jtfReplace.setText("");
+    }
+
+    /**
+     * Center this dialog window relative to its owning <code>Frame</code>.
+     *
+     * @param owner  <code>Frame</code> owning this dialog
+     *
+     * @see java.awt.Frame
+     */
+    public void centerDialog(final Frame owner) {
+        final Dimension dlgSize = getPreferredSize();
+        final Dimension frmSize = owner.getSize();
+        final Point loc = owner.getLocation();
+        setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y);
+    }
+
+    /**
+     * Toggle the state of the dialog window.
+     *
+     * <p>The state of the dialog is either unlocked (no find in progress) or
+     * locked (find in progress).</p>
+     *
+     * @param unlocked  one of FindReplaceDialog.STATE_LOCKED and
+     *      FindReplaceDialog.STATE_UNLOCKED
+     */
+    private void toggleState(final boolean unlocked) {
+        jbtnCancel.setEnabled(!unlocked);
+        jbtnClose.setEnabled(unlocked);
+        jcomboSearchTerm.setEnabled(unlocked);
+        jtfReplace.setEnabled(unlocked);
+        jLabel3.setEnabled(unlocked);
+        jLabel4.setEnabled(unlocked);
+        jcbWholeWords.setEnabled(unlocked);
+        jcbMatchCase.setEnabled(unlocked);
+        jcbMatchApprox.setEnabled(unlocked);
+        jcbStartOnTop.setEnabled(unlocked);
+        jrbUp.setEnabled(unlocked);
+        jrbDown.setEnabled(unlocked);
+        jcbProject.setEnabled(unlocked);
+        findInProgress = !unlocked;
+    }
+
+    /**
+     * method for determining whether or not a character is a
+     * word separator.
+     */
+    private boolean isSeparator(final char ch) {
+        int i = 0;
+        while ((i < WORD_SEPARATORS.length) && (ch != WORD_SEPARATORS[i])) {
+            i++;
+        }
+        return (i < WORD_SEPARATORS.length);
+    }
+
+    /**
+     * Show an information message
+     */
+    private void message(final String msgText) {
+        JOptionPane.showMessageDialog(this, msgText,
+            Util.getResourceString(SHTMLPanel.getResources(), "findReplaceDialogTitle"),
+            JOptionPane.INFORMATION_MESSAGE);
+    }
+
+    /* ----------- Helper methods end ------- */
+    /** GUI builder init */
+    private void jbInit() throws Exception {
+        final KeyListener escapeKeyListender = new KeyAdapter() {
+            public void keyPressed(final KeyEvent e) {
+                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                    e.consume();
+                    jbtnClose_actionPerformed(null);
+                }
+            }
+        };
+        titledBorder1 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white, new Color(142, 142, 142)),
+            "Options");
+        final ButtonGroup bgSearchDirection = new ButtonGroup();
+        jbtnFindNext.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(final ActionEvent e) {
+                jbtnFindNext_actionPerformed(e);
+            }
+        });
+        jbtnFindNext.setText(Util.getResourceString(SHTMLPanel.getResources(), "findNext"));
+        jbtnFindNext.setPreferredSize(new Dimension(100, 27));
+        jbtnFindNext.setMinimumSize(new Dimension(100, 27));
+        jbtnFindNext.setMaximumSize(new Dimension(100, 27));
+        jbtnFindNext.addKeyListener(escapeKeyListender);
+        jcbStartOnTop.setText(Util.getResourceString(SHTMLPanel.getResources(), "searchFromStart"));
+        jcbStartOnTop.setToolTipText(Util.getResourceString(SHTMLPanel.getResources(), "searchFromStart.tooltip"));
+        jrbDown.setText(Util.getResourceString(SHTMLPanel.getResources(), "searchDown"));
+        
+        jcbWholeWords.setText(Util.getResourceString(SHTMLPanel.getResources(), "wholeWordsOnly"));
+        jcbWholeWords.setToolTipText(Util.getResourceString(SHTMLPanel.getResources(), "wholeWordsOnly.tooltip"));
+        jrbDown.setToolTipText(Util.getResourceString(SHTMLPanel.getResources(), "searchDown.tooltip"));
+        jrbUp.setToolTipText(Util.getResourceString(SHTMLPanel.getResources(), "searchUp.tooltip"));
+        
+        jpnlBtn.setLayout(gridBagLayout4);
+        jpnlOptions.setBorder(titledBorder1);
+        jpnlOptions.setLayout(gridLayout2);
+        jpnlFind.setLayout(gridBagLayout5);
+        jtfReplace.setMinimumSize(new Dimension(4, 12));
+        jtfReplace.setPreferredSize(new Dimension(59, 12));
+        jtfReplace.setText("jtfReplace");
+        jtfReplace.addKeyListener(new KeyAdapter() {
+            public void keyPressed(final KeyEvent e) {
+                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                    e.consume();
+                    jbtnClose_actionPerformed(null);
+                }
+                else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+                    e.consume();
+                    jbtnReplace_actionPerformed(null);
+                    jbtnReplace.requestFocus();
+                }
+            }
+        });
+        jpnlMain.setLayout(gridBagLayout6);
+        jrbUp.setText(Util.getResourceString(SHTMLPanel.getResources(), "searchUp"));
+        jcomboSearchTerm.setMinimumSize(new Dimension(4, 12));
+        jcomboSearchTerm.setPreferredSize(new Dimension(63, 12));
+        //jcomboSearchTerm.setText("jtfPhrase");
+        jcomboSearchTerm.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
+            public void keyPressed(final KeyEvent e) {
+                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                    e.consume();
+                    jbtnClose_actionPerformed(null);
+                }
+                else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+                    e.consume();
+                    jbtnFindNext_actionPerformed(null);
+                    jbtnFindNext.requestFocus();
+                }
+            }
+        });
+        
+        jcbMatchCase.setText(Util.getResourceString(SHTMLPanel.getResources(), "matchCase"));
+        jcbMatchCase.setToolTipText(Util.getResourceString(SHTMLPanel.getResources(), "matchCase.tooltip"));
+        jcbMatchApprox.setText(Util.getResourceString(SHTMLPanel.getResources(), "matchApproximately"));
+        jcbMatchApprox.setToolTipText(Util.getResourceString(SHTMLPanel.getResources(), "matchApproximately.tooltip"));
+        
+        jLabel3.setText(Util.getResourceString(SHTMLPanel.getResources(), "replaceWith"));
+        jLabel4.setText(Util.getResourceString(SHTMLPanel.getResources(), "textToFind"));
+        jbtnClose.setMaximumSize(new Dimension(100, 27));
+        jbtnClose.setMinimumSize(new Dimension(100, 27));
+        jbtnClose.setPreferredSize(new Dimension(100, 27));
+        jbtnClose.setText(Util.getResourceString(SHTMLPanel.getResources(), "closeBtnName"));
+        jbtnClose.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(final ActionEvent e) {
+                jbtnClose_actionPerformed(e);
+            }
+        });
+        gridLayout2.setRows(4);
+        gridLayout2.setColumns(2);
+        this.setModal(true);
+        this.setTitle(Util.getResourceString(SHTMLPanel.getResources(), "findReplaceDialogTitle"));
+        jbtnReplace.setMaximumSize(new Dimension(100, 27));
+        jbtnReplace.setMinimumSize(new Dimension(100, 27));
+        jbtnReplace.setPreferredSize(new Dimension(100, 27));
+        jbtnReplace.setText(Util.getResourceString(SHTMLPanel.getResources(), "replace"));
+        jbtnReplace.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(final ActionEvent e) {
+                jbtnReplace_actionPerformed(e);
+            }
+        });
+        jbtnReplace.addKeyListener(escapeKeyListender);
+        jbtnCancel.setMaximumSize(new Dimension(100, 27));
+        jbtnCancel.setMinimumSize(new Dimension(100, 27));
+        jbtnCancel.setPreferredSize(new Dimension(100, 27));
+        jbtnCancel.setText(Util.getResourceString(SHTMLPanel.getResources(), "cancelBtnName"));
+        jbtnCancel.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(final ActionEvent e) {
+                jbtnCancel_actionPerformed(e);
+            }
+        });
+        jcbProject.setText(Util.getResourceString(SHTMLPanel.getResources(), "searchWholeProject"));
+        this.getContentPane().add(jpnlMain, BorderLayout.NORTH);
+        jpnlBtn.add(jbtnFindNext, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
+            GridBagConstraints.NONE, new Insets(4, 4, 0, 4), 0, 0));
+        jpnlBtn.add(jbtnClose, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
+            GridBagConstraints.NONE, new Insets(0, 4, 4, 4), 0, 0));
+        jpnlBtn.add(jbtnReplace, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
+            GridBagConstraints.NONE, new Insets(4, 4, 4, 4), 0, 0));
+        jpnlBtn.add(jbtnCancel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
+            GridBagConstraints.NONE, new Insets(4, 4, 4, 4), 0, 0));
+        jpnlMain.add(jpnlFind, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST,
+            GridBagConstraints.BOTH, new Insets(4, 4, 4, 4), 0, 0));
+        jpnlMain.add(jpnlBtn, new GridBagConstraints(1, 0, 1, 2, 1.0, 1.0, GridBagConstraints.NORTHEAST,
+            GridBagConstraints.NONE, new Insets(4, 4, 4, 4), 0, 0));
+        jpnlFind.add(jcomboSearchTerm, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
+            GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 12));
+        jpnlFind.add(jLabel4, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
+            GridBagConstraints.NONE, new Insets(4, 4, 4, 4), 0, 0));
+        jpnlFind.add(jtfReplace, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
+            GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 12));
+        jpnlFind.add(jLabel3, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
+            GridBagConstraints.NONE, new Insets(4, 4, 4, 4), 0, 0));
+        jpnlMain.add(jpnlOptions, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.SOUTHWEST,
+            GridBagConstraints.NONE, new Insets(4, 4, 4, 4), 0, 0));
+
+        jpnlOptions.add(jcbMatchCase, null);
+        jpnlOptions.add(jcbMatchApprox, null);
+        jpnlOptions.add(jcbWholeWords, null);
+        jpnlOptions.add(jrbUp, null);
+        jpnlOptions.add(jcbStartOnTop, null);
+        jpnlOptions.add(jrbDown, null);
+        jpnlOptions.add(jcbProject, null);
+        bgSearchDirection.add(jrbUp);
+        bgSearchDirection.add(jrbDown);
+        
+        // this is necessary so that the button fires on enter key press
+        // (for continuing a search)ok, 
+        getRootPane().setDefaultButton(jbtnFindNext);
+    }
+
+    /* ----------------- class fields ------------------------------ */
+    /** result value for this dialog */
+    private int result;
+    /** mode of dialog */
+    private int mode;
+    /** JEditorPane containing the document to search in */
+    private JEditorPane editor;
+    /** Document to search in */
+    private Document doc;
+    /** search text from the document */
+    private String searchText;
+    /** search phrase to find */
+    private String searchTerm;
+    /** new phrase to replace the searched phrase with */
+    
+    /* search results for approximate matching */
+    private List<PseudoDamerauLevenshtein.Alignment> currentApproximateMatches;
+    private int currentApproximateMatchIndex;
+    
+    private String replacementText;
+    /** last start position, the search phrase was found at in the document */
+    private int lastPosition;
+    /** two fields to correct position differences during replace operations */
+    private int offset;
+    private int replaceDiff;
+    /** indicates if a find is already in progress */
+    private boolean findInProgress = false;
+    /** indicates the current operation */
+    private int operation;
+    /** choice of replace operation */
+    private int replaceChoice;
+    /** the listeners for FindReplaceEvents */
+    private final Vector listeners = new Vector(0);
+    /** separators for whole words only search */
+    private static final char[] WORD_SEPARATORS = { ' ', '\t', '\n', '\r', '\f', '.', ',', ':', '-', '(', ')', '[',
+            ']', '{', '}', '<', '>', '/', '|', '\\', '\'', '\"' };
+    /** options for replacing */
+    private static final Object[] replaceOptions = { Util.getResourceString(SHTMLPanel.getResources(), "replaceYes"),
+            Util.getResourceString(SHTMLPanel.getResources(), "replaceNo"),
+            Util.getResourceString(SHTMLPanel.getResources(), "replaceAll"),
+            Util.getResourceString(SHTMLPanel.getResources(), "replaceDone") };
+    /* Constants for method toggleState */
+    public static final boolean STATE_LOCKED = false;
+    public static final boolean STATE_UNLOCKED = true;
+    /* Constants for replaceOptions */
+    public static final int RO_YES = 0;
+    public static final int RO_NO = 1;
+    public static final int RO_ALL = 2;
+    public static final int RO_DONE = 3;
+    /* Constants for dialog mode */
+    public static final int MODE_DOCUMENT = 1;
+    public static final int MODE_PROJECT = 2;
+    /* Constants for operation */
+    public static final int OP_NONE = 0;
+    public static final int OP_FIND = 1;
+    public static final int OP_REPLACE = 2;
+    /* ---- GUI elements start ---------*/
+    private TitledBorder titledBorder1;
+    private final JButton jbtnFindNext = new JButton();
+    private final JCheckBox jcbStartOnTop = new JCheckBox();
+    private final JRadioButton jrbDown = new JRadioButton();
+    private final JCheckBox jcbWholeWords = new JCheckBox();
+    private final JPanel jpnlBtn = new JPanel();
+    private final JPanel jpnlOptions = new JPanel();
+    private final JPanel jpnlFind = new JPanel();
+    private final JTextField jtfReplace = new JTextField();
+    private final JPanel jpnlMain = new JPanel();
+    private final JRadioButton jrbUp = new JRadioButton();
+    private final JComboBox jcomboSearchTerm = new JComboBox();
+    private final JCheckBox jcbMatchCase = new JCheckBox();
+    private final JCheckBox jcbMatchApprox = new JCheckBox();
+    private final JLabel jLabel3 = new JLabel();
+    private final JLabel jLabel4 = new JLabel();
+    private final GridBagLayout gridBagLayout4 = new GridBagLayout();
+    private final GridBagLayout gridBagLayout5 = new GridBagLayout();
+    private final JButton jbtnClose = new JButton();
+    private final GridBagLayout gridBagLayout6 = new GridBagLayout();
+    private final GridLayout gridLayout2 = new GridLayout();
+    private final JButton jbtnReplace = new JButton();
+    private final JButton jbtnCancel = new JButton();
+    private final JCheckBox jcbProject = new JCheckBox();
+    /* ---- GUI elements end ---------*/
+    
+    public static synchronized void rememberSearchTerm(final String searchTerm, final JComboBox searchTermCombo)
+    {
+    	//System.out.format("rememberSearchTerm(%s)\n", searchTerm);
+    	if (searchTerm.equals(""))
+    		return;
+    	
+    	MutableComboBoxModel searchTermComboModel = (MutableComboBoxModel)searchTermCombo.getModel();
+		
+    	// remove this term from the history
+    	if (searchTermHistory.contains(searchTerm))
+    	{
+    		searchTermHistory.remove(searchTerm);
+    		searchTermComboModel.removeElement(searchTerm);
+    	}
+    	
+    	// (re)insert at top of list
+    	searchTermHistory.add(0, searchTerm);
+    	searchTermComboModel.insertElementAt(searchTerm, 0);
+		
+    	searchTermCombo.setSelectedItem(searchTerm);
+    }
+    
+    private final static List<String> searchTermHistory = new LinkedList<String>();
+    private final static AtomicBoolean matchCaseSetting = new AtomicBoolean(false);
+    private final static AtomicBoolean matchApproxSetting = new AtomicBoolean(false);
+}
diff --git a/src/de/calcom/cclib/text/FindReplaceEvent.java b/src/de/calcom/cclib/text/FindReplaceEvent.java
new file mode 100644
index 0000000..060fe20
--- /dev/null
+++ b/src/de/calcom/cclib/text/FindReplaceEvent.java
@@ -0,0 +1,39 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2003 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package de.calcom.cclib.text;
+
+import java.util.EventObject;
+
+/**
+ * This is simply overriding EventObject by storing a FindReplaceDialog
+ * into the source field of the superclass.
+ *
+ * <p>Added i18n support for application SimplyHTML in version 1.5</p>
+ *
+ * @author Ulrich Hilger
+ * @author CalCom
+ * @author <a href="http://www.calcom.de">http://www.calcom.de</a>
+ * @author <a href="mailto:info at calcom.de">info at calcom.de</a>
+ * @version 1.5, April 27, 2003
+ */
+public class FindReplaceEvent extends EventObject {
+    public FindReplaceEvent(final FindReplaceDialog source) {
+        super(source);
+    }
+}
diff --git a/src/de/calcom/cclib/text/FindReplaceListener.java b/src/de/calcom/cclib/text/FindReplaceListener.java
new file mode 100644
index 0000000..7bb5806
--- /dev/null
+++ b/src/de/calcom/cclib/text/FindReplaceListener.java
@@ -0,0 +1,69 @@
+/*
+ * SimplyHTML, a word processor based on Java, HTML and CSS
+ * Copyright (C) 2003 Ulrich Hilger
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package de.calcom.cclib.text;
+
+import java.util.EventListener;
+
+/**
+ * Interface for implementing a listener for <code>FindReplaceEvents</code>.
+ *
+ * <p>For implementing this interface, methods getFirstDocument and
+ * getNextDocument need to be overridden by code providing a new document
+ * for the a FindReplaceDialog. Once a new document is on hand,
+ * methods resumeOperation or terminateOperation of the FindReplaceDialog
+ * need to be called from out of this interfaces methods to resume or
+ * terminate the find or replace operation,
+ * which is waiting for the new document in the FindReplaceDialog.</p>
+ *
+ * <p>Added i18n support for application SimplyHTML in version 1.5</p>
+ *
+ * @author Ulrich Hilger
+ * @author CalCom
+ * @author <a href="http://www.calcom.de">http://www.calcom.de</a>
+ * @author <a href="mailto:info at calcom.de">info at calcom.de</a>
+ *
+ * @version 1.5, April 27, 2003
+ */
+public interface FindReplaceListener extends EventListener {
+    /**
+     * this events gets fired, when a FindReplaceDialog has reached
+     * the end of the current document and requires the next document
+     * of a group of documents.
+     *
+     * @param  e  the object having details for the event
+     */
+    public void getNextDocument(FindReplaceEvent e);
+
+    /**
+     * this events gets fired, when a FindReplaceDialog has initiated
+     * an operation for a group of documents which requires to start at
+     * the first document.
+     *
+     * @param  e  the object having details for the event
+     */
+    public void getFirstDocument(FindReplaceEvent e);
+
+    /**
+     * this event gets fired when a FindReplaceDialog has finalized its
+     * task.
+     *
+     * @param  e  the object having details for the event
+     */
+    public void findReplaceTerminated(FindReplaceEvent e);
+}
diff --git a/src/de/calcom/cclib/text/PseudoDamerauLevenshtein.java b/src/de/calcom/cclib/text/PseudoDamerauLevenshtein.java
new file mode 100644
index 0000000..65ca02a
--- /dev/null
+++ b/src/de/calcom/cclib/text/PseudoDamerauLevenshtein.java
@@ -0,0 +1,570 @@
+/*
+ *  Freeplane - mind map editor
+ *  Copyright (C) 2012 Dimitry Polivaev
+ *
+ *  This file's author is Felix Natter
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.calcom.cclib.text;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+import java.util.TreeSet;
+
+/**
+ * Pseudo-Damerau-Levenshtein (aka "Optimal String Distance")
+ * implementation which allows some non-adjacent transpositions(?)
+ * Computes the edit distance with insertions/deletions/substitutions/transpositions.
+ * 
+ * Optionally the edit distance of a semi-global alignment is computed which
+ * allows the search term to be shifted free-of-cost (i.e. dist("file", "a file is")==0).
+ * 
+ * Some properties are explained in the unit test, {@link org.freeplane.features.filter.EditDistanceStringMatchingStrategiesTest}.
+ * 
+ * TODO: use unicode code points instead of chars !!
+ * 
+ * @author Felix Natter <fnatter at gmx.net>
+ *
+ */
+public class PseudoDamerauLevenshtein {
+	public enum Type { Global, SemiGlobal };
+	private int[][] matrix;
+	private String searchTerm;
+	private String searchText;
+	private final int costIndel = 1;
+	private final int costMismatch = 1;
+	private final int costTranspos = 1;
+	private Type type;
+	private Stack<Alignment> alignmentsInProgress;
+	private ArrayList<Alignment> alignmentsDone;
+	
+	public class Alignment implements Comparable<Alignment>
+	{
+		private final String searchTermString;
+		private final String searchTextString;
+		private final double prob;
+		private final int matchStart;
+		private final int matchEnd;
+		private final int r, c;
+		
+		public int getMatchStart()
+		{
+			return matchStart;
+		}
+		
+		public int getMatchEnd()
+		{
+			return matchEnd;
+		}
+		
+		public boolean overlapsWith(final Alignment other)
+		{	
+			return (matchStart <= other.matchStart && other.matchStart <= matchEnd-1) || // endpoint of this lies in other
+				   (other.matchStart <= matchStart && matchStart <= other.matchEnd-1); // endpoint of other lies in this
+				   
+		}
+				
+		@Override
+		public int hashCode() {
+			final int prime = 31;
+			int result = 1;
+			result = prime * result + getOuterType().hashCode();
+			result = prime * result + c;
+			result = prime * result + matchEnd;
+			result = prime * result + matchStart;
+			long temp;
+			temp = Double.doubleToLongBits(prob);
+			result = prime * result + (int) (temp ^ (temp >>> 32));
+			result = prime * result + r;
+			result = prime
+					* result
+					+ ((searchTermString == null) ? 0 : searchTermString
+							.hashCode());
+			result = prime
+					* result
+					+ ((searchTextString == null) ? 0 : searchTextString
+							.hashCode());
+			return result;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj) {
+				return true;
+			}
+			if (obj == null) {
+				return false;
+			}
+			if (getClass() != obj.getClass()) {
+				return false;
+			}
+			Alignment other = (Alignment) obj;
+			if (!getOuterType().equals(other.getOuterType())) {
+				return false;
+			}
+			if (c != other.c) {
+				return false;
+			}
+			if (matchEnd != other.matchEnd) {
+				return false;
+			}
+			if (matchStart != other.matchStart) {
+				return false;
+			}
+			if (Double.doubleToLongBits(prob) != Double
+					.doubleToLongBits(other.prob)) {
+				return false;
+			}
+			if (r != other.r) {
+				return false;
+			}
+			if (searchTermString == null) {
+				if (other.searchTermString != null) {
+					return false;
+				}
+			} else if (!searchTermString.equals(other.searchTermString)) {
+				return false;
+			}
+			if (searchTextString == null) {
+				if (other.searchTextString != null) {
+					return false;
+				}
+			} else if (!searchTextString.equals(other.searchTextString)) {
+				return false;
+			}
+			return true;
+		}
+
+
+
+		public String getMatch()
+		{
+			return searchText.substring(matchStart, matchEnd);
+		}
+		
+		public int compareTo(final Alignment other)
+		{
+			if (prob == other.prob)
+			{
+				return new Integer(getMatch().length()).compareTo(new Integer(other.getMatch().length())); 
+			}
+			else
+			{
+				return new Double(prob).compareTo(new Double(other.prob));
+			}
+		}
+		
+		public void print()
+		{
+			System.out.format("Alignment@%x[%.2f]:\n%s\n%s\n=> matches '%s' [%d,%d]\n",
+					hashCode(), prob, searchTermString, searchTextString, getMatch(),
+					matchStart,matchEnd);
+		}
+		
+		@Override
+		public String toString()
+		{
+			return String.format("Ali@%x[%s,%.2f,%d,%d]", hashCode(), getMatch(), prob, matchStart, matchEnd);
+		}
+		
+		public Alignment(final String searchTermString, final String searchTextString, final double prob,
+				final int matchStart, final int matchEnd, final int r, final int c)
+		{
+			this.searchTermString = searchTermString;
+			this.searchTextString = searchTextString;
+			this.prob = prob;
+			this.matchStart = matchStart;
+			this.matchEnd = matchEnd;
+			this.r = r;
+			this.c = c;
+		}
+
+
+
+		private PseudoDamerauLevenshtein getOuterType() {
+			return PseudoDamerauLevenshtein.this;
+		}
+	}
+	
+	private boolean isMatch(int i, int j) 
+	{
+		char col = searchTerm.charAt(i-1);
+		char row = searchText.charAt(j-1);
+		if (col == row || row == '-')
+			return true;
+		else
+			return false;
+	}
+	
+	public int distance() {
+		
+		matrix = new int[searchTerm.length()+1][searchText.length()+1]; // [row][col]
+		
+		 // first column: start-gap penalties for searchTerm
+		for (int i = 0; i <= (int)searchTerm.length(); i++)
+			matrix[i][0] = i*costIndel;
+		
+		// first row: start-gap penalties for searchText
+		if (type == Type.Global)
+		{
+			for (int j = 1; j <= (int)searchText.length(); j++)
+				matrix[0][j] = j*costIndel;
+		}
+		else if (type == Type.SemiGlobal)
+		{
+			Arrays.fill(matrix[0], 0);
+		}
+		
+		// compute the rest of the matrix
+		for (int i = 1; i <= searchTerm.length(); i++) 
+		{
+			for (int j = 1; j <= searchText.length(); j++) 
+			{
+				int cost_try_match = matrix[i-1][j-1] + (isMatch(i,j) ? 0 : costMismatch);
+				int cost_ins = matrix[i-1][j] + costIndel;
+				int cost_del = matrix[i][j-1] + costIndel;
+				matrix[i][j] = Math.min(cost_try_match, Math.min(cost_ins, cost_del));
+				
+				if (i >= 2 && j >= 2 &&
+					    searchTerm.charAt(i-2) == searchText.charAt(j-1) &&
+					    searchTerm.charAt(i-1) == searchText.charAt(j-2))
+				{
+					matrix[i][j] = Math.min(matrix[i][j], matrix[i-2][j-2] + costTranspos);
+				}
+		  	}
+		}
+		//writeMatrix(matrix);
+		if (type == Type.Global)
+		{
+			return matrix[searchTerm.length()][searchText.length()];
+		}
+		else
+		{
+			int min = Integer.MAX_VALUE;
+			for (int j = 1; j <= searchText.length()+1; j++)
+			{
+				min = Math.min(min, matrix[searchTerm.length()][j-1]);
+			}
+			return min;
+		}
+	
+	}
+	
+	private void writeMatrix(int[][] H)
+	{
+		for (int i = 0; i < H.length; i++)
+		{
+			for (int j = 0; j < H[0].length; j++)
+			{
+				System.out.format(" %3d", H[i][j]);
+			}
+			System.out.println();
+		}
+	}
+	
+	public List<Alignment> computeAlignments(final double minProb)
+	{
+		alignmentsInProgress = new Stack<Alignment>();
+		alignmentsDone = new ArrayList<Alignment>();
+		
+		int dist = distance(); // this computes the Dynamic Programming matrix according to Levenshtein
+		
+		if (type == Type.Global && getMatchProb(dist) > minProb)
+		{
+			alignmentsInProgress.push(new Alignment("", "", getMatchProb(dist), 0, searchText.length(),
+					searchTerm.length(), searchText.length()));
+		}
+		else
+		{
+			// semi-global "substring" alignment
+			StringBuilder searchTermSuffix = new StringBuilder();
+			StringBuilder searchTextSuffix = new StringBuilder();
+			for (int c = searchText.length() + 1; c >= 1; c--)
+			{
+				if (c <= searchText.length())
+				{
+					searchTermSuffix.append('-');
+					searchTextSuffix.insert(0, searchText.charAt(c-1));
+				}
+				double prob = getMatchProb(matrix[searchTerm.length()][c-1]); 
+				if (prob > minProb)
+				{
+					alignmentsInProgress.push(new Alignment(searchTermSuffix.toString(), searchTextSuffix.toString(),
+							prob, 0, searchText.length() - searchTextSuffix.length(), searchTerm.length(), c - 1));
+				}
+			}
+		}
+		
+		while (!alignmentsInProgress.isEmpty())
+		{
+			developAlignment(alignmentsInProgress.pop());
+		}
+		
+		// filter (overlapping) alignments
+		alignmentsDone = filterAlignments(alignmentsDone);
+		
+		sortAlignments(alignmentsDone);
+
+		/*
+		System.out.format("--NON-OVERLAPPPING ALIGNMENTS-------------------\n");
+		for (Alignment ali: alignmentsDone)
+		{
+			ali.print();
+		}
+		*/
+		
+		matrix = null;
+		
+		//return alignmentsDone.toArray(new Alignment[alignmentsDone.size()]);
+		return alignmentsDone;
+	}
+	
+	/**
+	 * Keep only non-overlapping matches (alignments) while preferring alignments with high score (prob)
+	 * TODO: this is a heuristic, is the problem NP complete?
+	 * 
+	 * @param alignments alignments list to filter
+	 * @return filtered alignment list
+	 */
+	static ArrayList<Alignment> filterAlignments(final ArrayList<Alignment> alignments)
+	{
+		if (alignments.isEmpty())
+			return new ArrayList<Alignment>();
+		
+		// sort by score and match length (see Alignment.compareTo()) 
+		Collections.sort(alignments, Collections.reverseOrder());
+		
+		ArrayList<Alignment> clusters = new ArrayList<Alignment>(alignments.size());
+		// start with a single cluster
+		clusters.add(alignments.get(0));
+		alignments.remove(0);
+		
+		// assign alignments to clusters
+		for (Alignment ali: alignments)
+		{
+			boolean found_cluster = false;
+			for (int j = 0; j < clusters.size(); j++)
+			{
+				if (ali.overlapsWith(clusters.get(j)))
+				{
+					found_cluster = true;
+					// keep either current cluster center or set to 'ali'
+					if (ali.compareTo(clusters.get(j)) > 0)
+					{
+						clusters.set(j, ali);
+					}
+				}
+			}
+			if (!found_cluster)
+			{
+				clusters.add(ali);
+			}
+		}
+		return clusters;
+	}	
+	
+	/**
+	 * Sort alignments (matches) by start positions
+	 * @param alignments list of alignments to sort
+	 */
+	static void sortAlignments(final ArrayList<Alignment> alignments)
+	{
+		Collections.sort(alignments, new Comparator<Alignment>()
+				{
+
+					public int compare(Alignment o1, Alignment o2) {
+						return new Integer(o1.matchStart).compareTo(o2.matchStart);
+					}
+			
+				});
+	}
+	
+//	private void printAlignmentsFrom(final String searchTermSuffix, final String searchTextSuffix, final int r, final int c,
+//			double prob, int matchStart, int matchEnd)
+	private void developAlignment(final Alignment ali)
+	{
+//		System.out.format("developAlignment(term=%s, text=%s, r=%d, c=%d)",
+//				ali.searchTermString, ali.searchTextString, ali.r, ali.c);
+		
+		if (ali.r == 0 && ali.c == 0)
+		{
+			alignmentsDone.add(ali);
+//			System.out.println();
+//			ali.print();
+		}
+		else
+		{
+			// TODO: comments!!
+			
+			// match/mismatch
+			if (ali.r >= 1 && ali.c >= 1 && matrix[ali.r][ali.c] == matrix[ali.r-1][ali.c-1] + (isMatch(ali.r,ali.c) ? 0 : costMismatch))
+			{
+//				System.out.format("=> match/mismatch\n");
+				
+				alignmentsInProgress.push(new Alignment(
+						/*searchTerm.charAt(ali.r-1) + ali.searchTermString*/ null,
+						/*searchText.charAt(ali.c-1) + ali.searchTextString*/ null,
+						ali.prob, ali.matchStart, ali.matchEnd, ali.r - 1, ali.c - 1)
+						);
+			}
+
+			/*
+			// free insertions at the beginning of the searchTerm
+			if (ali.c >= 1 && type == Type.SemiGlobal && ali.r == 0 && matrix[ali.r][ali.c-1] == 0)
+			{
+				System.out.format("=> insertion at beginning\n");
+				
+				alignmentsInProgress.push(new Alignment(
+						"-" + ali.searchTermString,
+						searchText.charAt(ali.c-1) + ali.searchTextString,
+						ali.prob, ali.matchStart + 1, ali.matchEnd, ali.r, ali.c - 1)
+						);
+			}
+			*/
+			if (type == Type.SemiGlobal && ali.r == 0)
+			{
+//				System.out.format("=> insertions at beginning\n");
+				int c = ali.c, matchStart = ali.matchStart;
+				StringBuilder searchTermPrefix = new StringBuilder();
+				StringBuilder searchTextPrefix = new StringBuilder();
+				while (c > 0)
+				{
+					//searchTermPrefix.append('-');
+					//searchTextPrefix.insert(0, searchText.charAt(c-1));
+					matchStart += 1;
+					c--;
+				}
+				alignmentsInProgress.push(new Alignment(
+						/*searchTermPrefix.toString() + ali.searchTermString*/ null,
+						/*searchTextPrefix.toString() + ali.searchTextString*/ null,
+						ali.prob, matchStart, ali.matchEnd, 0, 0)
+						);
+			}
+
+			// insertion
+			if (ali.c >= 1 && matrix[ali.r][ali.c] == matrix[ali.r][ali.c-1] + costIndel)
+			{
+//				System.out.format("=> insertion\n");
+
+				alignmentsInProgress.push(new Alignment(
+						/*"-" + ali.searchTermString*/ null,
+						/* searchText.charAt(ali.c-1) + ali.searchTextString*/ null,
+						ali.prob, ali.matchStart, ali.matchEnd, ali.r, ali.c - 1)
+						);
+			}
+						
+			// deletion
+			if (ali.r >= 1 && matrix[ali.r][ali.c] == matrix[ali.r-1][ali.c] + costIndel)
+			{
+//				System.out.format("=> deletion\n");
+				
+				alignmentsInProgress.push(new Alignment(
+						/*searchTerm.charAt(ali.r-1) + ali.searchTermString*/ null,
+						/*"-" + ali.searchTextString*/ null,
+						ali.prob, ali.matchStart, ali.matchEnd, ali.r - 1, ali.c)
+						);
+			}
+			
+			// Damerau-Extension (transpositions)
+			if (ali.r >= 2 && ali.c >= 2 && matrix[ali.r][ali.c] == matrix[ali.r-2][ali.c-2] + costTranspos &&
+			    searchTerm.charAt(ali.r-2) == searchText.charAt(ali.c-1) &&
+			    searchTerm.charAt(ali.r-1) == searchText.charAt(ali.c-2))
+			{
+//				System.out.format("=> transposition\n");
+				
+				alignmentsInProgress.push(new Alignment(
+						/*searchTerm.substring(ali.r - 2, ali.r) + ali.searchTermString*/ null,
+						/*searchText.substring(ali.c - 2, ali.c) + ali.searchTextString*/ null,
+						ali.prob, ali.matchStart, ali.matchEnd, ali.r - 2, ali.c - 2)
+						);
+			}
+		}
+	}
+
+	private float getMatchProb(final int distance)
+	{
+		if (type == Type.SemiGlobal)
+		{
+			return 1.0F - ((float)distance / searchTerm.length());
+		}
+		else
+		{
+			return 1.0F - ((float)distance / Math.min(searchTerm.length(), searchText.length()));
+		}
+	}
+	
+	public float matchProb()
+	{
+		//LogUtils.severe("minMatchProb=" +StringMatchingStrategy.APPROXIMATE_MATCHING_MINPROB);
+		int dist = distance();
+		matrix = null;
+		//LogUtils.severe(String.format("DLevDist(%s,%s) = %d\n", searchTerm, searchText, dist));
+		return getMatchProb(dist);
+	}
+	
+	public PseudoDamerauLevenshtein() {
+		//LogUtils.severe("minMatchProb=" +StringMatchingStrategy.APPROXIMATE_MATCHING_MINPROB);
+	}
+
+	public void init(String searchTerm, String searchText,
+			boolean subStringMatch, boolean caseSensitive) 
+	{
+		if (searchTerm == null || searchText == null)
+		{
+			throw new IllegalArgumentException("Null searchText/searchTerm!");
+		}
+
+		if (caseSensitive)
+		{
+			this.searchTerm = searchTerm;
+			this.searchText = searchText;
+		}
+		else
+		{
+			this.searchTerm = searchTerm.toLowerCase();
+			this.searchText= searchText.toLowerCase();
+		}
+		this.type = subStringMatch ? Type.SemiGlobal : Type.Global;
+	}
+
+	/*
+	public boolean matches(String searchTerm, String searchText,
+			boolean subStringMatch, boolean caseSensitive) 
+	{
+		init(searchTerm, searchText, subStringMatch, caseSensitive);
+		
+		return matchProb() > StringMatchingStrategy.APPROXIMATE_MATCHING_MINPROB; 
+	}
+
+	public Match[] getMatches(String searchTerm,
+			String searchText, boolean subStringMatch, boolean caseSensitive, double minProb) {
+		init(searchTerm, searchText, subStringMatch, caseSensitive);
+		List<Match> matches = new ArrayList<Match>();
+		for (Alignment ali: computeAlignments(minProb))
+		{
+			matches.add(new Match(ali.matchStart, ali.matchEnd));
+		}
+		return matches.toArray(new Match[matches.size()]);
+	}
+	*/
+
+}
diff --git a/src/de/calcom/cclib/text/package.html b/src/de/calcom/cclib/text/package.html
new file mode 100644
index 0000000..711c40d
--- /dev/null
+++ b/src/de/calcom/cclib/text/package.html
@@ -0,0 +1,16 @@
+<HTML>
+  <body>
+    Work on text in various manners.
+
+    <p>
+      The classes in this package extend the Swing EditorPane by allowing
+      drag and drop and cut and paste on styled text.
+    </p>
+
+    @author Ulrich Hilger, Dimitry Polivaev
+    @author <a href="http://simplyhtml.sourceforge.net/">http://simplyhtml.sourceforge.net/</a>
+
+    @version 0.12.2, 2007
+  </body>
+</HTML>
+

-- 
simplyhtml packaging



More information about the pkg-java-commits mailing list