Initial revision
[old-projects.git] / ekit / com / hexidec / ekit / EkitCore_Spell.java
diff --git a/ekit/com/hexidec/ekit/EkitCore_Spell.java b/ekit/com/hexidec/ekit/EkitCore_Spell.java
new file mode 100644 (file)
index 0000000..cc31e19
--- /dev/null
@@ -0,0 +1,2879 @@
+/*
+GNU Lesser General Public License
+
+EkitCore - Base Java Swing HTML Editor & Viewer Class (Spellcheck Version)
+Copyright (C) 2000-2003 Howard Kistler
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+package com.hexidec.ekit;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Vector;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTextField;
+import javax.swing.JTextPane;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.KeyStroke;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.event.UndoableEditListener;
+import javax.swing.filechooser.FileFilter;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.ChangedCharSetException;
+import javax.swing.text.DefaultEditorKit;
+import javax.swing.text.DefaultStyledDocument;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.PlainDocument;
+import javax.swing.text.Position;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyledDocument;
+import javax.swing.text.StyledEditorKit;
+import javax.swing.text.StyledEditorKit.FontSizeAction;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.StyleSheet;
+import javax.swing.text.rtf.RTFEditorKit;
+import javax.swing.undo.UndoManager;
+import javax.swing.undo.CannotUndoException;
+
+import com.hexidec.ekit.action.*;
+import com.hexidec.ekit.component.*;
+import com.hexidec.util.Base64Codec;
+import com.hexidec.util.Translatrix;
+
+import  com.swabunga.spell.engine.*;
+import  com.swabunga.spell.event.*;
+import  com.swabunga.spell.swing.*;
+
+/** EkitCore
+  * Main application class for editing and saving HTML in a Java text component
+  *
+  * @author Howard Kistler
+  * @version 0.9g
+  *
+  * REQUIREMENTS
+  * Java 2 (JDK 1.3 or 1.4)
+  * Swing Library
+  */
+
+public class EkitCore extends JPanel implements ActionListener, KeyListener, DocumentListener, SpellCheckListener
+{
+       /* Components */
+       private JSplitPane jspltDisplay;
+       private JTextPane jtpMain;
+       private ExtendedHTMLEditorKit htmlKit;
+       private ExtendedHTMLDocument htmlDoc;
+       private StyleSheet styleSheet;
+       private JTextPane jtpSource;
+       private JScrollPane jspSource;
+       private JToolBar jToolBar;
+
+       private JCheckBoxMenuItem jcbmiViewToolbar;
+       private JCheckBoxMenuItem jcbmiViewSource;
+
+       private JButtonNoFocus jbtnNewHTML;
+       private JButtonNoFocus jbtnOpenHTML;
+       private JButtonNoFocus jbtnSaveHTML;
+       private JButtonNoFocus jbtnCut;
+       private JButtonNoFocus jbtnCopy;
+       private JButtonNoFocus jbtnPaste;
+       private JButtonNoFocus jbtnBold;
+       private JButtonNoFocus jbtnItalic;
+       private JButtonNoFocus jbtnUnderline;
+       private JButtonNoFocus jbtnStrike;
+       private JButtonNoFocus jbtnSuperscript;
+       private JButtonNoFocus jbtnSubscript;
+       private JButtonNoFocus jbtnUList;
+       private JButtonNoFocus jbtnOList;
+       private JButtonNoFocus jbtnClearFormat;
+       private JButtonNoFocus jbtnAnchor;
+       private JToggleButtonNoFocus jtbtnViewSource;
+       private JComboBoxNoFocus jcmbStyleSelector;
+
+       private Frame frameHandler;
+
+       private HTMLUtilities htmlUtilities = new HTMLUtilities(this);
+
+       /* Actions */
+       private StyledEditorKit.BoldAction actionFontBold;
+       private StyledEditorKit.ItalicAction actionFontItalic;
+       private StyledEditorKit.UnderlineAction actionFontUnderline;
+       private FormatAction actionFontStrike;
+       private FormatAction actionFontSuperscript;
+       private FormatAction actionFontSubscript;
+       private ListAutomationAction actionListUnordered;
+       private ListAutomationAction actionListOrdered;
+       private CustomAction actionSelectFont;
+       private CustomAction actionClearFormat;
+       private CustomAction actionInsertAnchor;
+
+       protected UndoManager undoMngr;
+       protected UndoAction undoAction;
+       protected RedoAction redoAction;
+
+       /* Menus */
+       private JMenuBar jMenuBar;
+       private JMenu jMenuFile;
+       private JMenu jMenuEdit;
+       private JMenu jMenuView;
+       private JMenu jMenuFont;
+       private JMenu jMenuFormat;
+       private JMenu jMenuInsert;
+       private JMenu jMenuTable;
+       private JMenu jMenuForms;
+       private JMenu jMenuSearch;
+       private JMenu jMenuTools;
+       private JMenu jMenuHelp;
+       private JMenu jMenuDebug;
+
+       /* Constants */
+       // Menu Keys
+       public static final String KEY_MENU_FILE   = "file";
+       public static final String KEY_MENU_EDIT   = "edit";
+       public static final String KEY_MENU_VIEW   = "view";
+       public static final String KEY_MENU_FONT   = "font";
+       public static final String KEY_MENU_FORMAT = "format";
+       public static final String KEY_MENU_INSERT = "insert";
+       public static final String KEY_MENU_TABLE  = "table";
+       public static final String KEY_MENU_FORMS  = "forms";
+       public static final String KEY_MENU_SEARCH = "search";
+       public static final String KEY_MENU_TOOLS  = "tools";
+       public static final String KEY_MENU_HELP   = "help";
+       public static final String KEY_MENU_DEBUG  = "debug";
+
+       // Tool Keys
+       public static final String KEY_TOOL_SEP       = "separator";
+       public static final String KEY_TOOL_NEW       = "new";
+       public static final String KEY_TOOL_OPEN      = "open";
+       public static final String KEY_TOOL_SAVE      = "save";
+       public static final String KEY_TOOL_CUT       = "cut";
+       public static final String KEY_TOOL_COPY      = "copy";
+       public static final String KEY_TOOL_PASTE     = "paste";
+       public static final String KEY_TOOL_BOLD      = "bold";
+       public static final String KEY_TOOL_ITALIC    = "italic";
+       public static final String KEY_TOOL_UNDERLINE = "underline";
+       public static final String KEY_TOOL_STRIKE    = "strike";
+       public static final String KEY_TOOL_SUPER     = "superscript";
+       public static final String KEY_TOOL_SUB       = "subscript";
+       public static final String KEY_TOOL_ULIST     = "ulist";
+       public static final String KEY_TOOL_OLIST     = "olist";
+       public static final String KEY_TOOL_CLEAR     = "clearformats";
+       public static final String KEY_TOOL_ANCHOR    = "anchor";
+       public static final String KEY_TOOL_SOURCE    = "viewsource";
+       public static final String KEY_TOOL_STYLES    = "styleselect";
+
+       // Menu & Tool Key Arrays
+       private static Hashtable htMenus = new Hashtable();
+       private static Hashtable htTools = new Hashtable();
+
+       private final String appName = "Ekit";
+       private final String menuDialog = "..."; /* text to append to a MenuItem label when menu item opens a dialog */
+
+       private final boolean useFormIndicator = true; /* Creates a highlighted background on a new FORM so that it may be more easily edited */
+       private final String clrFormIndicator = "#cccccc";
+
+       // System Clipboard Settings
+       private java.awt.datatransfer.Clipboard sysClipboard;
+       private SecurityManager secManager;
+
+       /* Variables */
+       private int iSplitPos = 0;
+
+       private boolean exclusiveEdit = true;
+
+       private String lastSearchFindTerm     = null;
+       private String lastSearchReplaceTerm  = null;
+       private boolean lastSearchCaseSetting = false;
+       private boolean lastSearchTopSetting  = false;
+
+       private File currentFile = null;
+
+       private int indent = 0;
+       private final int indentStep = 4;
+
+       // File extensions for MutableFilter
+       private final String[] extsHTML = { "html", "htm", "shtml" };
+       private final String[] extsCSS  = { "css" };
+       private final String[] extsIMG  = { "gif", "jpg", "jpeg", "png" };
+       private final String[] extsRTF  = { "rtf" };
+       private final String[] extsB64  = { "b64" };
+       private final String[] extsSer  = { "ser" };
+
+       /* Spell Checker Settings */
+       private static String dictFile;
+       private SpellChecker spellCheck = null;
+       private JSpellDialog spellDialog;
+
+       /* Servlet Settings */
+       private String ServletURL = null;
+       private String TreePilotSystemID = "";
+       private String ImageDir = "";
+       private static ResourceBundle TreePilotProperties;
+
+       /** Master Constructor
+         * @param sDocument         [String]  A text or HTML document to load in the editor upon startup.
+         * @param sStyleSheet       [String]  A CSS stylesheet to load in the editor upon startup.
+         * @param sRawDocument      [String]  A document encoded as a String to load in the editor upon startup.
+         * @param urlStyleSheet     [URL]     A URL reference to the CSS style sheet.
+         * @param showViewSource    [boolean] Specifies whether or not to show the View Source window on startup.
+         * @param showMenuIcons     [boolean] Specifies whether or not to show icon pictures in menus.
+         * @param editModeExclusive [boolean] Specifies whether or not to use exclusive edit mode (recommended on).
+         * @param sLanguage         [String]  The language portion of the Internationalization Locale to run Ekit in.
+         * @param sCountry          [String]  The country portion of the Internationalization Locale to run Ekit in.
+         * @param base64            [boolean] Specifies whether the raw document is Base64 encoded or not.
+         * @param debugMode         [boolean] Specifies whether to show the Debug menu or not.
+         */
+       public EkitCore(String sDocument, String sStyleSheet, String sRawDocument, URL urlStyleSheet, boolean showViewSource, boolean showMenuIcons, boolean editModeExclusive, String sLanguage, String sCountry, boolean base64, boolean debugMode)
+       {
+               super();
+
+               exclusiveEdit = editModeExclusive;
+
+               frameHandler = new Frame();
+
+               // Determine if system clipboard is available
+               secManager = System.getSecurityManager();
+               if(secManager != null)
+               {
+                       try
+                       {
+                               secManager.checkSystemClipboardAccess();
+                               sysClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+                       }
+                       catch (SecurityException se)
+                       {
+                               sysClipboard = null;
+                       }
+               }
+
+               /* Localize for language */
+               Translatrix.setBundleName("com.hexidec.ekit.LanguageResources");
+               Locale baseLocale = (Locale)null;
+               if(sLanguage != null && sCountry != null)
+               {
+                       baseLocale = new Locale(sLanguage, sCountry);
+               }
+               Translatrix.setLocale(baseLocale);
+
+               /* Load TreePilot properties */
+               try
+               {
+                       TreePilotProperties = ResourceBundle.getBundle("com.hexidec.ekit.TreePilot");
+               }
+               catch(MissingResourceException mre)
+               {
+                       logException("MissingResourceException while loading treepilot file", mre);
+               }
+
+               /* Create the editor kit, document, and stylesheet */
+               jtpMain = new JTextPane();
+               htmlKit = new ExtendedHTMLEditorKit();
+               htmlDoc = (ExtendedHTMLDocument)(htmlKit.createDefaultDocument());
+               styleSheet = htmlDoc.getStyleSheet();
+               htmlKit.setDefaultCursor(new Cursor(Cursor.TEXT_CURSOR));
+
+               /* Set up the text pane */
+               jtpMain.setEditorKit(htmlKit);
+               jtpMain.setDocument(htmlDoc);
+               jtpMain.setMargin(new Insets(4, 4, 4, 4));
+               jtpMain.addKeyListener(this);
+
+               /* Create the source text area */
+               jtpSource = new JTextPane();
+               jtpSource.setBackground(new Color(212, 212, 212));
+               jtpSource.setSelectionColor(new Color(255, 192, 192));
+               jtpSource.setText(jtpMain.getText());
+               jtpSource.getDocument().addDocumentListener(this);
+
+               /* Add CaretListener for tracking caret location events */
+               jtpMain.addCaretListener(new CaretListener()
+               {
+                       public void caretUpdate(CaretEvent ce)
+                       {
+                               handleCaretPositionChange(ce);
+                       }
+               });
+
+               /* Set up the undo features */
+               undoMngr = new UndoManager();
+               undoAction = new UndoAction();
+               redoAction = new RedoAction();
+               jtpMain.getDocument().addUndoableEditListener(new CustomUndoableEditListener());
+
+               /* Insert raw document, if exists */
+               if(sRawDocument != null && sRawDocument.length() > 0)
+               {
+                       if(base64)
+                       {
+                               jtpMain.setText(Base64Codec.decode(sRawDocument));
+                       }
+                       else
+                       {
+                               jtpMain.setText(sRawDocument);
+                       }
+               }
+               jtpMain.setCaretPosition(0);
+               jtpMain.getDocument().addDocumentListener(this);
+
+               /* Import CSS from reference, if exists */
+               if(urlStyleSheet != null)
+               {
+                       try
+                       {
+                               String currDocText = jtpMain.getText();
+                               htmlDoc = (ExtendedHTMLDocument)(htmlKit.createDefaultDocument());
+                               styleSheet = htmlDoc.getStyleSheet();
+                               BufferedReader br = new BufferedReader(new InputStreamReader(urlStyleSheet.openStream()));
+                               styleSheet.loadRules(br, urlStyleSheet);
+                               br.close();
+                               htmlDoc = new ExtendedHTMLDocument(styleSheet);
+                               registerDocument(htmlDoc);
+                               jtpMain.setText(currDocText);
+                               jtpSource.setText(jtpMain.getText());
+                       }
+                       catch(Exception e)
+                       {
+                               e.printStackTrace(System.out);
+                       }
+               }
+
+               /* Preload the specified HTML document, if exists */
+               if(sDocument != null)
+               {
+                       File defHTML = new File(sDocument);
+                       if(defHTML.exists())
+                       {
+                               try
+                               {
+                                       openDocument(defHTML);
+                               }
+                               catch(Exception e)
+                               {
+                                       logException("Exception in preloading HTML document", e);
+                               }
+                       }
+               }
+
+               /* Preload the specified CSS document, if exists */
+               if(sStyleSheet != null)
+               {
+                       File defCSS = new File(sStyleSheet);
+                       if(defCSS.exists())
+                       {
+                               try
+                               {
+                                       openStyleSheet(defCSS);
+                               }
+                               catch(Exception e)
+                               {
+                                       logException("Exception in preloading CSS stylesheet", e);
+                               }
+                       }
+               }
+
+               /* Collect the actions that the JTextPane is naturally aware of */
+               Hashtable actions = new Hashtable();
+               Action[] actionsArray = jtpMain.getActions();
+               for(int i = 0; i < actionsArray.length; i++)
+               {
+                       Action a = actionsArray[i];
+                       actions.put(a.getValue(Action.NAME), a);
+               }
+
+               /* Create shared actions */
+               actionFontBold        = new StyledEditorKit.BoldAction();
+               actionFontItalic      = new StyledEditorKit.ItalicAction();
+               actionFontUnderline   = new StyledEditorKit.UnderlineAction();
+               actionFontStrike      = new FormatAction(this, Translatrix.getTranslationString("FontStrike"), HTML.Tag.STRIKE);
+               actionFontSuperscript = new FormatAction(this, Translatrix.getTranslationString("FontSuperscript"), HTML.Tag.SUP);
+               actionFontSubscript   = new FormatAction(this, Translatrix.getTranslationString("FontSubscript"), HTML.Tag.SUB);
+               actionListUnordered   = new ListAutomationAction(this, Translatrix.getTranslationString("ListUnordered"), HTML.Tag.UL);
+               actionListOrdered     = new ListAutomationAction(this, Translatrix.getTranslationString("ListOrdered"), HTML.Tag.OL);
+               Hashtable customAttr = new Hashtable();
+               customAttr.put("face","");
+               actionSelectFont      = new CustomAction(this, Translatrix.getTranslationString("FontSelect") + menuDialog, HTML.Tag.FONT, customAttr);
+               actionClearFormat     = new CustomAction(this, Translatrix.getTranslationString("FormatClear"), new HTML.UnknownTag(""));
+               actionInsertAnchor    = new CustomAction(this, Translatrix.getTranslationString("InsertAnchor") + menuDialog, HTML.Tag.A);
+
+               /* Build the menus */
+               /* FILE Menu */
+               jMenuFile              = new JMenu(Translatrix.getTranslationString("File"));
+               htMenus.put(KEY_MENU_FILE, jMenuFile);
+               JMenuItem jmiNew       = new JMenuItem(Translatrix.getTranslationString("NewDocument"));                     jmiNew.setActionCommand("newdoc");        jmiNew.addActionListener(this);      jmiNew.setAccelerator(KeyStroke.getKeyStroke('N', java.awt.Event.CTRL_MASK, false));      if(showMenuIcons) { jmiNew.setIcon(getEkitIcon("New")); }; jMenuFile.add(jmiNew);
+               JMenuItem jmiOpenHTML  = new JMenuItem(Translatrix.getTranslationString("OpenDocument") + menuDialog);       jmiOpenHTML.setActionCommand("openhtml"); jmiOpenHTML.addActionListener(this); jmiOpenHTML.setAccelerator(KeyStroke.getKeyStroke('O', java.awt.Event.CTRL_MASK, false)); if(showMenuIcons) { jmiOpenHTML.setIcon(getEkitIcon("Open")); }; jMenuFile.add(jmiOpenHTML);
+               JMenuItem jmiOpenCSS   = new JMenuItem(Translatrix.getTranslationString("OpenStyle") + menuDialog);          jmiOpenCSS.setActionCommand("opencss");   jmiOpenCSS.addActionListener(this);  jMenuFile.add(jmiOpenCSS);
+               JMenuItem jmiOpenB64   = new JMenuItem(Translatrix.getTranslationString("OpenBase64Document") + menuDialog); jmiOpenB64.setActionCommand("openb64");   jmiOpenB64.addActionListener(this);  jMenuFile.add(jmiOpenB64);
+               jMenuFile.addSeparator();
+               JMenuItem jmiSave      = new JMenuItem(Translatrix.getTranslationString("Save"));                  jmiSave.setActionCommand("save");         jmiSave.addActionListener(this);     jmiSave.setAccelerator(KeyStroke.getKeyStroke('S', java.awt.Event.CTRL_MASK, false)); if(showMenuIcons) { jmiSave.setIcon(getEkitIcon("Save")); }; jMenuFile.add(jmiSave);
+               JMenuItem jmiSaveAs    = new JMenuItem(Translatrix.getTranslationString("SaveAs") + menuDialog);   jmiSaveAs.setActionCommand("saveas");     jmiSaveAs.addActionListener(this);   jMenuFile.add(jmiSaveAs);
+               JMenuItem jmiSaveBody  = new JMenuItem(Translatrix.getTranslationString("SaveBody") + menuDialog); jmiSaveBody.setActionCommand("savebody"); jmiSaveBody.addActionListener(this); jMenuFile.add(jmiSaveBody);
+               JMenuItem jmiSaveRTF   = new JMenuItem(Translatrix.getTranslationString("SaveRTF") + menuDialog);  jmiSaveRTF.setActionCommand("savertf");   jmiSaveRTF.addActionListener(this);  jMenuFile.add(jmiSaveRTF);
+               JMenuItem jmiSaveB64   = new JMenuItem(Translatrix.getTranslationString("SaveB64") + menuDialog);  jmiSaveB64.setActionCommand("saveb64");   jmiSaveB64.addActionListener(this);  jMenuFile.add(jmiSaveB64);
+               jMenuFile.addSeparator();
+               JMenuItem jmiSerialOut = new JMenuItem(Translatrix.getTranslationString("Serialize") + menuDialog);   jmiSerialOut.setActionCommand("serialize");  jmiSerialOut.addActionListener(this); jMenuFile.add(jmiSerialOut);
+               JMenuItem jmiSerialIn  = new JMenuItem(Translatrix.getTranslationString("ReadFromSer") + menuDialog); jmiSerialIn.setActionCommand("readfromser"); jmiSerialIn.addActionListener(this);  jMenuFile.add(jmiSerialIn);
+               jMenuFile.addSeparator();
+               JMenuItem jmiExit      = new JMenuItem(Translatrix.getTranslationString("Exit")); jmiExit.setActionCommand("exit"); jmiExit.addActionListener(this); jMenuFile.add(jmiExit);
+
+               /* EDIT Menu */
+               jMenuEdit            = new JMenu(Translatrix.getTranslationString("Edit"));
+               htMenus.put(KEY_MENU_EDIT, jMenuEdit);
+               if(sysClipboard != null)
+               {
+                       // System Clipboard versions of menu commands
+                       JMenuItem jmiCut     = new JMenuItem(Translatrix.getTranslationString("Cut"));   jmiCut.setActionCommand("textcut");     jmiCut.addActionListener(this);   jmiCut.setAccelerator(KeyStroke.getKeyStroke('X', java.awt.Event.CTRL_MASK, false));   if(showMenuIcons) { jmiCut.setIcon(getEkitIcon("Cut")); }     jMenuEdit.add(jmiCut);
+                       JMenuItem jmiCopy    = new JMenuItem(Translatrix.getTranslationString("Copy"));  jmiCopy.setActionCommand("textcopy");   jmiCopy.addActionListener(this);  jmiCopy.setAccelerator(KeyStroke.getKeyStroke('C', java.awt.Event.CTRL_MASK, false));  if(showMenuIcons) { jmiCopy.setIcon(getEkitIcon("Copy")); }   jMenuEdit.add(jmiCopy);
+                       JMenuItem jmiPaste   = new JMenuItem(Translatrix.getTranslationString("Paste")); jmiPaste.setActionCommand("textpaste"); jmiPaste.addActionListener(this); jmiPaste.setAccelerator(KeyStroke.getKeyStroke('V', java.awt.Event.CTRL_MASK, false)); if(showMenuIcons) { jmiPaste.setIcon(getEkitIcon("Paste")); } jMenuEdit.add(jmiPaste);
+               }
+               else
+               {
+                       // DefaultEditorKit versions of menu commands
+                       JMenuItem jmiCut     = new JMenuItem(new DefaultEditorKit.CutAction());   jmiCut.setText(Translatrix.getTranslationString("Cut"));     jmiCut.setAccelerator(KeyStroke.getKeyStroke('X', java.awt.Event.CTRL_MASK, false));   if(showMenuIcons) { jmiCut.setIcon(getEkitIcon("Cut")); }     jMenuEdit.add(jmiCut);
+                       JMenuItem jmiCopy    = new JMenuItem(new DefaultEditorKit.CopyAction());  jmiCopy.setText(Translatrix.getTranslationString("Copy"));   jmiCopy.setAccelerator(KeyStroke.getKeyStroke('C', java.awt.Event.CTRL_MASK, false));  if(showMenuIcons) { jmiCopy.setIcon(getEkitIcon("Copy")); }   jMenuEdit.add(jmiCopy);
+                       JMenuItem jmiPaste   = new JMenuItem(new DefaultEditorKit.PasteAction()); jmiPaste.setText(Translatrix.getTranslationString("Paste")); jmiPaste.setAccelerator(KeyStroke.getKeyStroke('V', java.awt.Event.CTRL_MASK, false)); if(showMenuIcons) { jmiPaste.setIcon(getEkitIcon("Paste")); } jMenuEdit.add(jmiPaste);
+               }
+               jMenuEdit.addSeparator();
+               JMenuItem jmiUndo    = new JMenuItem(undoAction); jmiUndo.setAccelerator(KeyStroke.getKeyStroke('Z', java.awt.Event.CTRL_MASK, false)); jMenuEdit.add(jmiUndo);
+               JMenuItem jmiRedo    = new JMenuItem(redoAction); jmiRedo.setAccelerator(KeyStroke.getKeyStroke('Y', java.awt.Event.CTRL_MASK, false)); jMenuEdit.add(jmiRedo);
+               jMenuEdit.addSeparator();
+               JMenuItem jmiSelAll  = new JMenuItem((Action)actions.get(DefaultEditorKit.selectAllAction));       jmiSelAll.setText(Translatrix.getTranslationString("SelectAll"));        jmiSelAll.setAccelerator(KeyStroke.getKeyStroke('A', java.awt.Event.CTRL_MASK, false)); jMenuEdit.add(jmiSelAll);
+               JMenuItem jmiSelPara = new JMenuItem((Action)actions.get(DefaultEditorKit.selectParagraphAction)); jmiSelPara.setText(Translatrix.getTranslationString("SelectParagraph")); jMenuEdit.add(jmiSelPara);
+               JMenuItem jmiSelLine = new JMenuItem((Action)actions.get(DefaultEditorKit.selectLineAction));      jmiSelLine.setText(Translatrix.getTranslationString("SelectLine"));      jMenuEdit.add(jmiSelLine);
+               JMenuItem jmiSelWord = new JMenuItem((Action)actions.get(DefaultEditorKit.selectWordAction));      jmiSelWord.setText(Translatrix.getTranslationString("SelectWord"));      jMenuEdit.add(jmiSelWord);
+
+               /* VIEW Menu */
+               jMenuView        = new JMenu(Translatrix.getTranslationString("View"));
+               htMenus.put(KEY_MENU_VIEW, jMenuView);
+               jcbmiViewToolbar = new JCheckBoxMenuItem(Translatrix.getTranslationString("ViewToolbar"), false); jcbmiViewToolbar.setActionCommand("toggletoolbar"); jcbmiViewToolbar.addActionListener(this); jMenuView.add(jcbmiViewToolbar);
+               jcbmiViewSource  = new JCheckBoxMenuItem(Translatrix.getTranslationString("ViewSource"), false);  jcbmiViewSource.setActionCommand("viewsource");     jcbmiViewSource.addActionListener(this);  jMenuView.add(jcbmiViewSource);
+
+               /* FONT Menu */
+               jMenuFont              = new JMenu(Translatrix.getTranslationString("Font"));
+               htMenus.put(KEY_MENU_FONT, jMenuFont);
+               JMenuItem jmiBold      = new JMenuItem(actionFontBold);      jmiBold.setText(Translatrix.getTranslationString("FontBold"));           jmiBold.setAccelerator(KeyStroke.getKeyStroke('B', java.awt.Event.CTRL_MASK, false));      if(showMenuIcons) { jmiBold.setIcon(getEkitIcon("Bold")); }           jMenuFont.add(jmiBold);
+               JMenuItem jmiItalic    = new JMenuItem(actionFontItalic);    jmiItalic.setText(Translatrix.getTranslationString("FontItalic"));       jmiItalic.setAccelerator(KeyStroke.getKeyStroke('I', java.awt.Event.CTRL_MASK, false));    if(showMenuIcons) { jmiItalic.setIcon(getEkitIcon("Italic")); }       jMenuFont.add(jmiItalic);
+               JMenuItem jmiUnderline = new JMenuItem(actionFontUnderline); jmiUnderline.setText(Translatrix.getTranslationString("FontUnderline")); jmiUnderline.setAccelerator(KeyStroke.getKeyStroke('U', java.awt.Event.CTRL_MASK, false)); if(showMenuIcons) { jmiUnderline.setIcon(getEkitIcon("Underline")); } jMenuFont.add(jmiUnderline);
+               JMenuItem jmiStrike    = new JMenuItem(actionFontStrike);    jmiStrike.setText(Translatrix.getTranslationString("FontStrike"));                                                                                                  if(showMenuIcons) { jmiStrike.setIcon(getEkitIcon("Strike")); }       jMenuFont.add(jmiStrike);
+               jMenuFont.addSeparator();
+               jMenuFont.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("FormatBig"), HTML.Tag.BIG)));
+               jMenuFont.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("FormatSmall"), HTML.Tag.SMALL)));
+               JMenu jMenuFontSize = new JMenu(Translatrix.getTranslationString("FontSize"));
+                       String fontSizeKey = "size";
+                       customAttr = new Hashtable(); customAttr.put(fontSizeKey,"1");
+                       jMenuFontSize.add(new JMenuItem(new CustomAction(this, Translatrix.getTranslationString("FontSize1"), HTML.Tag.FONT, customAttr)));
+                       customAttr = new Hashtable(); customAttr.put(fontSizeKey,"2");
+                       jMenuFontSize.add(new JMenuItem(new CustomAction(this, Translatrix.getTranslationString("FontSize2"), HTML.Tag.FONT, customAttr)));
+                       customAttr = new Hashtable(); customAttr.put(fontSizeKey,"3");
+                       jMenuFontSize.add(new JMenuItem(new CustomAction(this, Translatrix.getTranslationString("FontSize3"), HTML.Tag.FONT, customAttr)));
+                       customAttr = new Hashtable(); customAttr.put(fontSizeKey,"4");
+                       jMenuFontSize.add(new JMenuItem(new CustomAction(this, Translatrix.getTranslationString("FontSize4"), HTML.Tag.FONT, customAttr)));
+                       customAttr = new Hashtable(); customAttr.put(fontSizeKey,"5");
+                       jMenuFontSize.add(new JMenuItem(new CustomAction(this, Translatrix.getTranslationString("FontSize5"), HTML.Tag.FONT, customAttr)));
+                       customAttr = new Hashtable(); customAttr.put(fontSizeKey,"6");
+                       jMenuFontSize.add(new JMenuItem(new CustomAction(this, Translatrix.getTranslationString("FontSize6"), HTML.Tag.FONT, customAttr)));
+                       customAttr = new Hashtable(); customAttr.put(fontSizeKey,"7");
+                       jMenuFontSize.add(new JMenuItem(new CustomAction(this, Translatrix.getTranslationString("FontSize7"), HTML.Tag.FONT, customAttr)));
+               jMenuFont.add(jMenuFontSize);
+               jMenuFont.addSeparator();
+               JMenuItem jmiSupscript = new JMenuItem(actionFontSuperscript); if(showMenuIcons) { jmiSupscript.setIcon(getEkitIcon("Super")); } jMenuFont.add(jmiSupscript);
+               JMenuItem jmiSubscript = new JMenuItem(actionFontSubscript);   if(showMenuIcons) { jmiSubscript.setIcon(getEkitIcon("Sub")); }   jMenuFont.add(jmiSubscript);
+               jMenuFont.addSeparator();
+               JMenuItem jmiSerif      = new JMenuItem((Action)actions.get("font-family-Serif"));      jmiSerif.setText(Translatrix.getTranslationString("FontSerif"));           jMenuFont.add(jmiSerif);
+               JMenuItem jmiSansSerif  = new JMenuItem((Action)actions.get("font-family-SansSerif"));  jmiSansSerif.setText(Translatrix.getTranslationString("FontSansserif"));   jMenuFont.add(jmiSansSerif);
+               JMenuItem jmiMonospaced = new JMenuItem((Action)actions.get("font-family-Monospaced")); jmiMonospaced.setText(Translatrix.getTranslationString("FontMonospaced")); jMenuFont.add(jmiMonospaced);
+               JMenuItem jmiSelectFont = new JMenuItem(actionSelectFont);                                                                                                         jMenuFont.add(jmiSelectFont);
+               jMenuFont.addSeparator();
+               JMenu jMenuFontColor = new JMenu(Translatrix.getTranslationString("Color"));
+                       customAttr = new Hashtable(); customAttr.put("color","black");
+                       jMenuFontColor.add(new JMenuItem(new CustomAction(this, Translatrix.getTranslationString("CustomColor") + menuDialog, HTML.Tag.FONT, customAttr)));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorAqua"),    new Color(  0,255,255))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorBlack"),   new Color(  0,  0,  0))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorBlue"),    new Color(  0,  0,255))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorFuschia"), new Color(255,  0,255))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorGray"),    new Color(128,128,128))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorGreen"),   new Color(  0,128,  0))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorLime"),    new Color(  0,255,  0))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorMaroon"),  new Color(128,  0,  0))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorNavy"),    new Color(  0,  0,128))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorOlive"),   new Color(128,128,  0))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorPurple"),  new Color(128,  0,128))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorRed"),     new Color(255,  0,  0))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorSilver"),  new Color(192,192,192))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorTeal"),    new Color(  0,128,128))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorWhite"),   new Color(255,255,255))));
+                       jMenuFontColor.add(new JMenuItem(new StyledEditorKit.ForegroundAction(Translatrix.getTranslationString("ColorYellow"),  new Color(255,255,  0))));
+               jMenuFont.add(jMenuFontColor);
+
+               /* FORMAT Menu */
+               jMenuFormat            = new JMenu(Translatrix.getTranslationString("Format"));
+               htMenus.put(KEY_MENU_FORMAT, jMenuFormat);
+               JMenu jMenuFormatAlign = new JMenu(Translatrix.getTranslationString("Align"));
+                       jMenuFormatAlign.add(new JMenuItem(new StyledEditorKit.AlignmentAction(Translatrix.getTranslationString("AlignLeft"), StyleConstants.ALIGN_LEFT)));
+                       jMenuFormatAlign.add(new JMenuItem(new StyledEditorKit.AlignmentAction(Translatrix.getTranslationString("AlignCenter"), StyleConstants.ALIGN_CENTER)));
+                       jMenuFormatAlign.add(new JMenuItem(new StyledEditorKit.AlignmentAction(Translatrix.getTranslationString("AlignRight"), StyleConstants.ALIGN_RIGHT)));
+                       jMenuFormatAlign.add(new JMenuItem(new StyledEditorKit.AlignmentAction(Translatrix.getTranslationString("AlignJustified"), StyleConstants.ALIGN_JUSTIFIED)));
+               jMenuFormat.add(jMenuFormatAlign);
+               jMenuFormat.addSeparator();
+               JMenu jMenuFormatHeading = new JMenu(Translatrix.getTranslationString("Heading"));
+                       jMenuFormatHeading.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("Heading1"), HTML.Tag.H1)));
+                       jMenuFormatHeading.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("Heading2"), HTML.Tag.H2)));
+                       jMenuFormatHeading.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("Heading3"), HTML.Tag.H3)));
+                       jMenuFormatHeading.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("Heading4"), HTML.Tag.H4)));
+                       jMenuFormatHeading.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("Heading5"), HTML.Tag.H5)));
+                       jMenuFormatHeading.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("Heading6"), HTML.Tag.H6)));
+               jMenuFormat.add(jMenuFormatHeading);
+               jMenuFormat.addSeparator();
+               JMenuItem jmiUList = new JMenuItem(actionListUnordered); if(showMenuIcons) { jmiUList.setIcon(getEkitIcon("UList")); } jMenuFormat.add(jmiUList);
+               JMenuItem jmiOList = new JMenuItem(actionListOrdered);   if(showMenuIcons) { jmiOList.setIcon(getEkitIcon("OList")); } jMenuFormat.add(jmiOList);
+               jMenuFormat.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("ListItem"), HTML.Tag.LI)));
+               jMenuFormat.addSeparator();
+               jMenuFormat.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("FormatBlockquote"), HTML.Tag.BLOCKQUOTE)));
+               jMenuFormat.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("FormatPre"), HTML.Tag.PRE)));
+               jMenuFormat.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("FormatStrong"), HTML.Tag.STRONG)));
+               jMenuFormat.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("FormatEmphasis"), HTML.Tag.EM)));
+               jMenuFormat.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("FormatTT"), HTML.Tag.TT)));
+               jMenuFormat.add(new JMenuItem(new FormatAction(this, Translatrix.getTranslationString("FormatSpan"), HTML.Tag.SPAN)));
+               jMenuFormat.addSeparator();
+               JMenuItem jmiClearStyles = new JMenuItem(actionClearFormat); if(showMenuIcons) { jmiClearStyles.setIcon(getEkitIcon("ClearFormat")); }; jMenuFormat.add(jmiClearStyles);
+
+               /* INSERT Menu */
+               jMenuInsert              = new JMenu(Translatrix.getTranslationString("Insert"));
+               htMenus.put(KEY_MENU_INSERT, jMenuInsert);
+               jMenuInsert.add(new JMenuItem(actionInsertAnchor));
+               JMenuItem jmiBreak       = new JMenuItem(Translatrix.getTranslationString("InsertBreak"));                    jmiBreak.setActionCommand("insertbreak"); jmiBreak.addActionListener(this); jmiBreak.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, java.awt.Event.SHIFT_MASK, false)); jMenuInsert.add(jmiBreak);
+               JMenuItem jmiNBSP        = new JMenuItem(Translatrix.getTranslationString("InsertNBSP"));                     jmiNBSP.setActionCommand("insertnbsp");   jmiNBSP.addActionListener(this);  jMenuInsert.add(jmiNBSP);
+               JMenuItem jmiHRule       = new JMenuItem((Action)actions.get("InsertHR"));                                    jmiHRule.setText(Translatrix.getTranslationString("InsertHorizontalRule")); jMenuInsert.add(jmiHRule);
+               jMenuInsert.addSeparator();
+               JMenuItem jmiImageLocal  = new JMenuItem(Translatrix.getTranslationString("InsertLocalImage") + menuDialog);  jmiImageLocal.setActionCommand("insertlocalimage"); jmiImageLocal.addActionListener(this); jMenuInsert.add(jmiImageLocal);
+               JMenuItem jmiImageServer = new JMenuItem(Translatrix.getTranslationString("InsertServerImage") + menuDialog); jmiImageServer.setActionCommand("insertserverimage"); jmiImageServer.addActionListener(this); jMenuInsert.add(jmiImageServer);
+
+               /* TABLE Menu */
+               jMenuTable              = new JMenu(Translatrix.getTranslationString("Table"));
+               htMenus.put(KEY_MENU_TABLE, jMenuTable);
+               JMenuItem jmiTable       = new JMenuItem(Translatrix.getTranslationString("InsertTable") + menuDialog); jmiTable.setActionCommand("inserttable");             jmiTable.addActionListener(this);       jMenuTable.add(jmiTable);
+               jMenuTable.addSeparator();
+               JMenuItem jmiTableRow    = new JMenuItem(Translatrix.getTranslationString("InsertTableRow"));           jmiTableRow.setActionCommand("inserttablerow");       jmiTableRow.addActionListener(this);    jMenuTable.add(jmiTableRow);
+               JMenuItem jmiTableCol    = new JMenuItem(Translatrix.getTranslationString("InsertTableColumn"));        jmiTableCol.setActionCommand("inserttablecolumn");    jmiTableCol.addActionListener(this);    jMenuTable.add(jmiTableCol);
+               jMenuTable.addSeparator();
+               JMenuItem jmiTableRowDel = new JMenuItem(Translatrix.getTranslationString("DeleteTableRow"));           jmiTableRowDel.setActionCommand("deletetablerow");    jmiTableRowDel.addActionListener(this); jMenuTable.add(jmiTableRowDel);
+               JMenuItem jmiTableColDel = new JMenuItem(Translatrix.getTranslationString("DeleteTableColumn"));        jmiTableColDel.setActionCommand("deletetablecolumn"); jmiTableColDel.addActionListener(this); jMenuTable.add(jmiTableColDel);
+
+               /* FORMS Menu */
+               jMenuForms                    = new JMenu(Translatrix.getTranslationString("Forms"));
+               htMenus.put(KEY_MENU_FORMS, jMenuForms);
+               JMenuItem jmiFormInsertForm   = new JMenuItem(Translatrix.getTranslationString("FormInsertForm")); jmiFormInsertForm.setActionCommand("insertform");     jmiFormInsertForm.addActionListener(this); jMenuForms.add(jmiFormInsertForm);
+               jMenuForms.addSeparator();
+               JMenuItem jmiFormTextfield    = new JMenuItem(Translatrix.getTranslationString("FormTextfield"));  jmiFormTextfield.setActionCommand("inserttextfield"); jmiFormTextfield.addActionListener(this);  jMenuForms.add(jmiFormTextfield);
+               JMenuItem jmiFormTextarea     = new JMenuItem(Translatrix.getTranslationString("FormTextarea"));   jmiFormTextarea.setActionCommand("inserttextarea");   jmiFormTextarea.addActionListener(this);   jMenuForms.add(jmiFormTextarea);
+               JMenuItem jmiFormCheckbox     = new JMenuItem(Translatrix.getTranslationString("FormCheckbox"));   jmiFormCheckbox.setActionCommand("insertcheckbox");   jmiFormCheckbox.addActionListener(this);   jMenuForms.add(jmiFormCheckbox);
+               JMenuItem jmiFormRadio        = new JMenuItem(Translatrix.getTranslationString("FormRadio"));      jmiFormRadio.setActionCommand("insertradiobutton");   jmiFormRadio.addActionListener(this);      jMenuForms.add(jmiFormRadio);
+               JMenuItem jmiFormPassword     = new JMenuItem(Translatrix.getTranslationString("FormPassword"));   jmiFormPassword.setActionCommand("insertpassword");   jmiFormPassword.addActionListener(this);   jMenuForms.add(jmiFormPassword);
+               jMenuForms.addSeparator();
+               JMenuItem jmiFormButton       = new JMenuItem(Translatrix.getTranslationString("FormButton"));       jmiFormButton.setActionCommand("insertbutton");             jmiFormButton.addActionListener(this);       jMenuForms.add(jmiFormButton);
+               JMenuItem jmiFormButtonSubmit = new JMenuItem(Translatrix.getTranslationString("FormButtonSubmit")); jmiFormButtonSubmit.setActionCommand("insertbuttonsubmit"); jmiFormButtonSubmit.addActionListener(this); jMenuForms.add(jmiFormButtonSubmit);
+               JMenuItem jmiFormButtonReset  = new JMenuItem(Translatrix.getTranslationString("FormButtonReset"));  jmiFormButtonReset.setActionCommand("insertbuttonreset");   jmiFormButtonReset.addActionListener(this);  jMenuForms.add(jmiFormButtonReset);
+
+               /* SEARCH Menu */
+               jMenuSearch            = new JMenu(Translatrix.getTranslationString("Search"));
+               htMenus.put(KEY_MENU_SEARCH, jMenuSearch);
+               JMenuItem jmiFind      = new JMenuItem(Translatrix.getTranslationString("SearchFind"));      jmiFind.setActionCommand("find");           jmiFind.addActionListener(this);      jmiFind.setAccelerator(KeyStroke.getKeyStroke('F', java.awt.Event.CTRL_MASK, false));      jMenuSearch.add(jmiFind);
+               JMenuItem jmiFindAgain = new JMenuItem(Translatrix.getTranslationString("SearchFindAgain")); jmiFindAgain.setActionCommand("findagain"); jmiFindAgain.addActionListener(this); jmiFindAgain.setAccelerator(KeyStroke.getKeyStroke('G', java.awt.Event.CTRL_MASK, false)); jMenuSearch.add(jmiFindAgain);
+               JMenuItem jmiReplace   = new JMenuItem(Translatrix.getTranslationString("SearchReplace"));   jmiReplace.setActionCommand("replace");     jmiReplace.addActionListener(this);   jmiReplace.setAccelerator(KeyStroke.getKeyStroke('R', java.awt.Event.CTRL_MASK, false));   jMenuSearch.add(jmiReplace);
+
+               /* TOOLS Menu */
+               jMenuTools = new JMenu(Translatrix.getTranslationString("Tools"));
+               htMenus.put(KEY_MENU_TOOLS, jMenuTools);
+               JMenuItem jmiSpellcheck = new JMenuItem(Translatrix.getTranslationString("ToolSpellcheck")); jmiSpellcheck.setActionCommand("spellcheck"); jmiSpellcheck.addActionListener(this); jMenuTools.add(jmiSpellcheck);
+
+               /* HELP Menu */
+               jMenuHelp = new JMenu(Translatrix.getTranslationString("Help"));
+               htMenus.put(KEY_MENU_HELP, jMenuHelp);
+               JMenuItem jmiAbout = new JMenuItem(Translatrix.getTranslationString("About")); jmiAbout.setActionCommand("helpabout"); jmiAbout.addActionListener(this); jMenuHelp.add(jmiAbout);
+
+               /* DEBUG Menu */
+               jMenuDebug           = new JMenu(Translatrix.getTranslationString("Debug"));
+               htMenus.put(KEY_MENU_DEBUG, jMenuDebug);
+               JMenuItem jmiDesc    = new JMenuItem(Translatrix.getTranslationString("DescribeDoc")); jmiDesc.setActionCommand("describe");       jmiDesc.addActionListener(this);    jMenuDebug.add(jmiDesc);
+               JMenuItem jmiDescCSS = new JMenuItem(Translatrix.getTranslationString("DescribeCSS")); jmiDescCSS.setActionCommand("describecss"); jmiDescCSS.addActionListener(this); jMenuDebug.add(jmiDescCSS);
+               JMenuItem jmiTag     = new JMenuItem(Translatrix.getTranslationString("WhatTags"));    jmiTag.setActionCommand("whattags");        jmiTag.addActionListener(this);     jMenuDebug.add(jmiTag);
+
+               /* Create menubar and add menus */
+               jMenuBar = new JMenuBar();
+               jMenuBar.add(jMenuFile);
+               jMenuBar.add(jMenuEdit);
+               jMenuBar.add(jMenuView);
+               jMenuBar.add(jMenuFont);
+               jMenuBar.add(jMenuFormat);
+               jMenuBar.add(jMenuSearch);
+               jMenuBar.add(jMenuInsert);
+               jMenuBar.add(jMenuTable);
+               jMenuBar.add(jMenuForms);
+               jMenuBar.add(jMenuTools);
+               jMenuBar.add(jMenuHelp);
+               if(debugMode)
+               {
+                       jMenuBar.add(jMenuDebug);
+               }
+
+               /* Create the toolbar */
+               jToolBar = new JToolBar(JToolBar.HORIZONTAL);
+               jToolBar.setFloatable(false);
+               jbtnNewHTML     = new JButtonNoFocus(getEkitIcon("New"));  jbtnNewHTML.setToolTipText(Translatrix.getTranslationString("NewDocument"));   jbtnNewHTML.setActionCommand("newdoc");    jbtnNewHTML.addActionListener(this);  jToolBar.add(jbtnNewHTML);  htTools.put(KEY_TOOL_NEW, jbtnNewHTML);
+               jbtnOpenHTML    = new JButtonNoFocus(getEkitIcon("Open")); jbtnOpenHTML.setToolTipText(Translatrix.getTranslationString("OpenDocument")); jbtnOpenHTML.setActionCommand("openhtml"); jbtnOpenHTML.addActionListener(this); jToolBar.add(jbtnOpenHTML); htTools.put(KEY_TOOL_OPEN, jbtnOpenHTML);
+               jbtnSaveHTML    = new JButtonNoFocus(getEkitIcon("Save")); jbtnSaveHTML.setToolTipText(Translatrix.getTranslationString("SaveDocument")); jbtnSaveHTML.setActionCommand("saveas");   jbtnSaveHTML.addActionListener(this); jToolBar.add(jbtnSaveHTML); htTools.put(KEY_TOOL_SAVE, jbtnSaveHTML);
+               jToolBar.add(new JToolBar.Separator());
+               jbtnCut         = new JButtonNoFocus(new DefaultEditorKit.CutAction());   jbtnCut.setIcon(getEkitIcon("Cut"));     jbtnCut.setText(null);   jbtnCut.setToolTipText(Translatrix.getTranslationString("Cut"));     jToolBar.add(jbtnCut);   htTools.put(KEY_TOOL_CUT, jbtnCut);
+               jbtnCopy        = new JButtonNoFocus(new DefaultEditorKit.CopyAction());  jbtnCopy.setIcon(getEkitIcon("Copy"));   jbtnCopy.setText(null);  jbtnCopy.setToolTipText(Translatrix.getTranslationString("Copy"));   jToolBar.add(jbtnCopy);  htTools.put(KEY_TOOL_COPY, jbtnCopy);
+               jbtnPaste       = new JButtonNoFocus(new DefaultEditorKit.PasteAction()); jbtnPaste.setIcon(getEkitIcon("Paste")); jbtnPaste.setText(null); jbtnPaste.setToolTipText(Translatrix.getTranslationString("Paste")); jToolBar.add(jbtnPaste); htTools.put(KEY_TOOL_PASTE, jbtnPaste);
+               jToolBar.add(new JToolBar.Separator());
+               jbtnBold        = new JButtonNoFocus(actionFontBold);        jbtnBold.setIcon(getEkitIcon("Bold"));               jbtnBold.setText(null);        jbtnBold.setToolTipText(Translatrix.getTranslationString("FontBold"));                 jToolBar.add(jbtnBold);        htTools.put(KEY_TOOL_BOLD, jbtnBold);
+               jbtnItalic      = new JButtonNoFocus(actionFontItalic);      jbtnItalic.setIcon(getEkitIcon("Italic"));           jbtnItalic.setText(null);      jbtnItalic.setToolTipText(Translatrix.getTranslationString("FontItalic"));             jToolBar.add(jbtnItalic);      htTools.put(KEY_TOOL_ITALIC, jbtnItalic);
+               jbtnUnderline   = new JButtonNoFocus(actionFontUnderline);   jbtnUnderline.setIcon(getEkitIcon("Underline"));     jbtnUnderline.setText(null);   jbtnUnderline.setToolTipText(Translatrix.getTranslationString("FontUnderline"));       jToolBar.add(jbtnUnderline);   htTools.put(KEY_TOOL_UNDERLINE, jbtnUnderline);
+               jbtnStrike      = new JButtonNoFocus(actionFontStrike);      jbtnStrike.setIcon(getEkitIcon("Strike"));           jbtnStrike.setText(null);      jbtnStrike.setToolTipText(Translatrix.getTranslationString("FontStrike"));             jToolBar.add(jbtnStrike);      htTools.put(KEY_TOOL_STRIKE, jbtnStrike);
+               jbtnSuperscript = new JButtonNoFocus(actionFontSuperscript); jbtnSuperscript.setIcon(getEkitIcon("Super"));       jbtnSuperscript.setText(null); jbtnSuperscript.setToolTipText(Translatrix.getTranslationString("FontSuperscript")); jToolBar.add(jbtnSuperscript);   htTools.put(KEY_TOOL_SUPER, jbtnSuperscript);
+               jbtnSubscript   = new JButtonNoFocus(actionFontSubscript);   jbtnSubscript.setIcon(getEkitIcon("Sub"));           jbtnSubscript.setText(null);   jbtnSubscript.setToolTipText(Translatrix.getTranslationString("FontSubscript"));     jToolBar.add(jbtnSubscript);     htTools.put(KEY_TOOL_SUB, jbtnSubscript);
+               jbtnUList       = new JButtonNoFocus(actionListUnordered);   jbtnUList.setIcon(getEkitIcon("UList"));             jbtnUList.setText(null);       jbtnUList.setToolTipText(Translatrix.getTranslationString("ListUnordered"));           jToolBar.add(jbtnUList);       htTools.put(KEY_TOOL_ULIST, jbtnUList);
+               jbtnOList       = new JButtonNoFocus(actionListOrdered);     jbtnOList.setIcon(getEkitIcon("OList"));             jbtnOList.setText(null);       jbtnOList.setToolTipText(Translatrix.getTranslationString("ListOrdered"));             jToolBar.add(jbtnOList);       htTools.put(KEY_TOOL_OLIST, jbtnOList);
+               jbtnClearFormat = new JButtonNoFocus(actionClearFormat);     jbtnClearFormat.setIcon(getEkitIcon("ClearFormat")); jbtnClearFormat.setText(null); jbtnClearFormat.setToolTipText(Translatrix.getTranslationString("FormatClear"));       jToolBar.add(jbtnClearFormat); htTools.put(KEY_TOOL_CLEAR, jbtnClearFormat);
+               jToolBar.add(new JToolBar.Separator());
+               jbtnAnchor      = new JButtonNoFocus(actionInsertAnchor); jbtnAnchor.setIcon(getEkitIcon("Anchor")); jbtnAnchor.setText(null); jbtnAnchor.setToolTipText(Translatrix.getTranslationString("ToolAnchor")); jToolBar.add(jbtnAnchor); htTools.put(KEY_TOOL_ANCHOR, jbtnAnchor);
+               jToolBar.add(new JToolBar.Separator());
+               jtbtnViewSource = new JToggleButtonNoFocus(getEkitIcon("Source")); jtbtnViewSource.setText(null); jtbtnViewSource.setToolTipText(Translatrix.getTranslationString("ViewSource")); jtbtnViewSource.setActionCommand("viewsource"); jtbtnViewSource.addActionListener(this); jtbtnViewSource.setPreferredSize(jbtnAnchor.getPreferredSize()); jtbtnViewSource.setMinimumSize(jbtnAnchor.getMinimumSize()); jtbtnViewSource.setMaximumSize(jbtnAnchor.getMaximumSize()); jToolBar.add(jtbtnViewSource); htTools.put(KEY_TOOL_SOURCE, jtbtnViewSource);
+               jToolBar.add(new JToolBar.Separator());
+               jcmbStyleSelector = new JComboBoxNoFocus(); jToolBar.add(jcmbStyleSelector); jcmbStyleSelector.setAction(new StylesAction(jcmbStyleSelector)); htTools.put(KEY_TOOL_STYLES, jcmbStyleSelector);
+
+               /* Create the scroll area for the text pane */
+               JScrollPane jspViewport = new JScrollPane(jtpMain);
+               jspViewport.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+               jspViewport.setPreferredSize(new Dimension(400, 400));
+               jspViewport.setMinimumSize(new Dimension(32, 32));
+
+               /* Create the scroll area for the source viewer */
+               jspSource = new JScrollPane(jtpSource);
+               jspSource.setPreferredSize(new Dimension(400, 100));
+               jspSource.setMinimumSize(new Dimension(32, 32));
+
+               jspltDisplay = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+               jspltDisplay.setTopComponent(jspViewport);
+               if(showViewSource)
+               {
+                       jspltDisplay.setBottomComponent(jspSource);
+               }
+               else
+               {
+                       jspltDisplay.setBottomComponent(null);
+               }
+
+               iSplitPos = jspltDisplay.getDividerLocation();
+
+               registerDocumentStyles();
+
+               /* Create spell checker */
+               try
+               {
+                       dictFile = Translatrix.getTranslationString("DictionaryFile");
+                       SpellDictionary dictionary = new SpellDictionary(dictFile); // uses my custom loader in SpellDictionary
+                       spellCheck = new SpellChecker(dictionary);
+                       spellCheck.addSpellCheckListener(this);
+               }
+               catch(Exception e)
+               {
+                       e.printStackTrace();
+               }
+               spellDialog = new JSpellDialog(this.getFrame(), Translatrix.getTranslationString("ToolSpellcheckDialog"), true);
+
+               /* Add the components to the app */
+               this.setLayout(new BorderLayout());
+               this.add(jspltDisplay, BorderLayout.CENTER);
+       }
+
+       /** Common Constructor
+         * @param sDocument         [String]  A text or HTML document to load in the editor upon startup.
+         * @param sStyleSheet       [String]  A CSS stylesheet to load in the editor upon startup.
+         * @param showViewSource    [boolean] Specifies whether or not to show the View Source window on startup.
+         * @param showMenuIcons     [boolean] Specifies whether or not to show icon pictures in menus.
+         * @param editModeExclusive [boolean] Specifies whether or not to use exclusive edit mode (recommended on).
+         * @param sLanguage         [String]  The language portion of the Internationalization Locale to run Ekit in.
+         * @param sCountry          [String]  The country portion of the Internationalization Locale to run Ekit in.
+         */
+       public EkitCore(String sDocument, String sStyleSheet, boolean showViewSource, boolean showMenuIcons, boolean editModeExclusive, String sLanguage, String sCountry, boolean base64)
+       {
+               this(sDocument, sStyleSheet, null, null, showViewSource, showMenuIcons, editModeExclusive, sLanguage, sCountry, base64, false);
+       }
+
+       /** Default Language Constructor
+         * @param sDocument         [String]  A text or HTML document to load in the editor upon startup.
+         * @param sStyleSheet       [String]  A CSS stylesheet to load in the editor upon startup.
+         * @param showViewSource    [boolean] Specifies whether or not to show the View Source window on startup.
+         * @param showMenuIcons     [boolean] Specifies whether or not to show icon pictures in menus.
+         * @param editModeExclusive [boolean] Specifies whether or not to use exclusive edit mode (recommended on).
+         */
+       public EkitCore(String sDocument, String sStyleSheet, boolean showViewSource, boolean showMenuIcons, boolean editModeExclusive, boolean base64)
+       {
+               this(sDocument, sStyleSheet, null, null, showViewSource, showMenuIcons, editModeExclusive, null, null, base64, false);
+       }
+
+       /** Raw/Base64 Document & Style Sheet URL Constructor (Ideal for EkitApplet)
+         * @param sRawDocument      [String]  A document encoded as a String to load in the editor upon startup.
+         * @param sRawDocument      [String]  A document encoded as a String to load in the editor upon startup.
+         * @param showViewSource    [boolean] Specifies whether or not to show the View Source window on startup.
+         * @param showMenuIcons     [boolean] Specifies whether or not to show icon pictures in menus.
+         * @param editModeExclusive [boolean] Specifies whether or not to use exclusive edit mode (recommended on).
+         * @param sLanguage         [String]  The language portion of the Internationalization Locale to run Ekit in.
+         * @param sCountry          [String]  The country portion of the Internationalization Locale to run Ekit in.
+         */
+       public EkitCore(String sRawDocument, URL urlStyleSheet, boolean showViewSource, boolean showMenuIcons, boolean editModeExclusive, String sLanguage, String sCountry, boolean base64)
+       {
+               this(null, null, sRawDocument, urlStyleSheet, showViewSource, showMenuIcons, editModeExclusive, sLanguage, sCountry, base64, false);
+       }
+
+       /** Document Constructor
+         * @param sRawDocument      [String]  A document encoded as a String to load in the editor upon startup.
+         * @param showViewSource    [boolean] Specifies whether or not to show the View Source window on startup.
+         * @param showMenuIcons     [boolean] Specifies whether or not to show icon pictures in menus.
+         * @param editModeExclusive [boolean] Specifies whether or not to use exclusive edit mode (recommended on).
+         * @param sLanguage         [String]  The language portion of the Internationalization Locale to run Ekit in.
+         * @param sCountry          [String]  The country portion of the Internationalization Locale to run Ekit in.
+         */
+       public EkitCore(String sRawDocument, boolean showViewSource, boolean showMenuIcons, boolean editModeExclusive, String sLanguage, String sCountry, boolean base64)
+       {
+               this(null, null, sRawDocument, null, showViewSource, showMenuIcons, editModeExclusive, sLanguage, sCountry, base64, false);
+       }
+
+       /** Default Language & Document Constructor
+         * @param sRawDocument      [String]  A document encoded as a String to load in the editor upon startup.
+         * @param showViewSource    [boolean] Specifies whether or not to show the View Source window on startup.
+         * @param showMenuIcons     [boolean] Specifies whether or not to show icon pictures in menus.
+         * @param editModeExclusive [boolean] Specifies whether or not to use exclusive edit mode (recommended on).
+         */
+       public EkitCore(String sRawDocument, boolean showViewSource, boolean showMenuIcons, boolean editModeExclusive, boolean base64)
+       {
+               this(null, null, sRawDocument, null, showViewSource, showMenuIcons, editModeExclusive, null, null, base64, false);
+       }
+
+       /** Flags & Language Constructor
+         * @param showViewSource    [boolean] Specifies whether or not to show the View Source window on startup.
+         * @param showMenuIcons     [boolean] Specifies whether or not to show icon pictures in menus.
+         * @param editModeExclusive [boolean] Specifies whether or not to use exclusive edit mode (recommended on).
+         * @param sLanguage         [String]  The language portion of the Internationalization Locale to run Ekit in.
+         * @param sCountry          [String]  The country portion of the Internationalization Locale to run Ekit in.
+         */
+       public EkitCore(boolean showViewSource, boolean showMenuIcons, boolean editModeExclusive, String sLanguage, String sCountry)
+       {
+               this(null, null, null, null, showViewSource, showMenuIcons, editModeExclusive, sLanguage, sCountry, false, false);
+       }
+
+       /** Flags Constructor
+         * @param showViewSource    [boolean] Specifies whether or not to show the View Source window on startup.
+         * @param showMenuIcons     [boolean] Specifies whether or not to show icon pictures in menus.
+         * @param editModeExclusive [boolean] Specifies whether or not to use exclusive edit mode (recommended on).
+         */
+       public EkitCore(boolean showViewSource, boolean showMenuIcons, boolean editModeExclusive)
+       {
+               this(null, null, null, null, showViewSource, showMenuIcons, editModeExclusive, null, null, false, false);
+       }
+
+       /** Language & Debug Constructor
+         * @param sLanguage [String]  The language portion of the Internationalization Locale to run Ekit in.
+         * @param sCountry  [String]  The country portion of the Internationalization Locale to run Ekit in.
+         * @param debugMode [boolean] Specifies whether to show the Debug menu or not.
+         */
+       public EkitCore(String sLanguage, String sCountry, boolean debugMode)
+       {
+               this(null, null, null, null, false, true, true, sLanguage, sCountry, false, debugMode);
+       }
+
+       /** Language Constructor
+         * @param sLanguage [String]  The language portion of the Internationalization Locale to run Ekit in.
+         * @param sCountry  [String]  The country portion of the Internationalization Locale to run Ekit in.
+         */
+       public EkitCore(String sLanguage, String sCountry)
+       {
+               this(null, null, null, null, false, true, true, sLanguage, sCountry, false, false);
+       }
+
+       /** Debug Constructor
+         * @param debugMode [boolean] Specifies whether to show the Debug menu or not.
+         */
+       public EkitCore(boolean debugMode)
+       {
+               this(null, null, null, null, false, true, true, null, null, false, debugMode);
+       }
+
+       /** Empty Constructor
+         */
+       public EkitCore()
+       {
+               this(null, null, null, null, false, true, true, null, null, false, false);
+       }
+
+       /* ActionListener method */
+       public void actionPerformed(ActionEvent ae)
+       {
+               try
+               {
+                       String command = ae.getActionCommand();
+                       if(command.equals("newdoc"))
+                       {
+                               SimpleInfoDialog sidAsk = new SimpleInfoDialog(this.getFrame(), "", true, Translatrix.getTranslationString("AskNewDocument"), SimpleInfoDialog.QUESTION);
+                               String decision = sidAsk.getDecisionValue();
+                               if(decision.equals(Translatrix.getTranslationString("DialogAccept")))
+                               {
+                                       if(styleSheet != null)
+                                       {
+                                               htmlDoc = new ExtendedHTMLDocument(styleSheet);
+                                       }
+                                       else
+                                       {
+                                               htmlDoc = (ExtendedHTMLDocument)(htmlKit.createDefaultDocument());
+                                       }
+                                       jtpMain.setText("<HTML><BODY></BODY></HTML>");
+                                       jtpSource.setText(jtpMain.getText());
+                                       registerDocument(htmlDoc);
+                                       currentFile = null;
+                                       updateTitle();
+                               }
+                       }
+                       else if(command.equals("openhtml"))
+                       {
+                               openDocument(null);
+                       }
+                       else if(command.equals("opencss"))
+                       {
+                               openStyleSheet(null);
+                       }
+                       else if(command.equals("openb64"))
+                       {
+                               openDocumentBase64(null);
+                       }
+                       else if(command.equals("save"))
+                       {
+                               writeOut((HTMLDocument)(jtpMain.getDocument()), currentFile);
+                               updateTitle();
+                       }
+                       else if(command.equals("saveas"))
+                       {
+                               writeOut((HTMLDocument)(jtpMain.getDocument()), null);
+                       }
+                       else if(command.equals("savebody"))
+                       {
+                               writeOutFragment((HTMLDocument)(jtpMain.getDocument()),"body");
+                       }
+                       else if(command.equals("savertf"))
+                       {
+                               writeOutRTF((StyledDocument)(jtpMain.getStyledDocument()));
+                       }
+                       else if(command.equals("saveb64"))
+                       {
+                               writeOutBase64(jtpSource.getText());
+                       }
+                       else if(command.equals("textcut"))
+                       {
+                               if(jspSource.isShowing() && jtpSource.hasFocus())
+                               {
+                                       jtpSource.cut();
+                               }
+                               else
+                               {
+                                       jtpMain.cut();
+                               }
+                       }
+                       else if(command.equals("textcopy"))
+                       {
+                               if(jspSource.isShowing() && jtpSource.hasFocus())
+                               {
+                                       jtpSource.copy();
+                               }
+                               else
+                               {
+                                       jtpMain.copy();
+                               }
+                       }
+                       else if(command.equals("textpaste"))
+                       {
+                               if(jspSource.isShowing() && jtpSource.hasFocus())
+                               {
+                                       jtpSource.paste();
+                               }
+                               else
+                               {
+                                       jtpMain.paste();
+                               }
+                       }
+                       else if(command.equals("describe"))
+                       {
+                               System.out.println("------------DOCUMENT------------");
+                               System.out.println("Content Type : " + jtpMain.getContentType());
+                               System.out.println("Editor Kit   : " + jtpMain.getEditorKit());
+                               System.out.println("Doc Tree     :");
+                               System.out.println("");
+                               describeDocument(jtpMain.getStyledDocument());
+                               System.out.println("--------------------------------");
+                               System.out.println("");
+                       }
+                       else if(command.equals("describecss"))
+                       {
+                               System.out.println("-----------STYLESHEET-----------");
+                               System.out.println("Stylesheet Rules");
+                               Enumeration rules = styleSheet.getStyleNames();
+                               while(rules.hasMoreElements())
+                               {
+                                       String ruleName = (String)(rules.nextElement());
+                                       Style styleRule = styleSheet.getStyle(ruleName);
+                                       System.out.println(styleRule.toString());
+                               }
+                               System.out.println("--------------------------------");
+                               System.out.println("");
+                       }
+                       else if(command.equals("whattags"))
+                       {
+                               System.out.println("Caret Position : " + jtpMain.getCaretPosition());
+                               AttributeSet attribSet = jtpMain.getCharacterAttributes();
+                               Enumeration attribs = attribSet.getAttributeNames();
+                               System.out.println("Attributes     : ");
+                               while(attribs.hasMoreElements())
+                               {
+                                       String attribName = attribs.nextElement().toString();
+                                       System.out.println("                 " + attribName + " | " + attribSet.getAttribute(attribName));
+                               }
+                       }
+                       else if(command.equals("toggletoolbar"))
+                       {
+                               jToolBar.setVisible(jcbmiViewToolbar.isSelected());
+                       }
+                       else if(command.equals("viewsource"))
+                       {
+                               toggleSourceWindow();
+                       }
+                       else if(command.equals("serialize"))
+                       {
+                               serializeOut((HTMLDocument)(jtpMain.getDocument()));
+                       }
+                       else if(command.equals("readfromser"))
+                       {
+                               serializeIn();
+                       }
+                       else if(command.equals("inserttable"))
+                       {
+                               String[] fieldNames = { "rows", "cols", "border", "cellspacing", "cellpadding", "width" };
+                               String[] fieldTypes = { "text", "text", "text",   "text",        "text",        "text" };
+                               insertTable((Hashtable)null, fieldNames, fieldTypes);
+                       }
+                       else if(command.equals("inserttablerow"))
+                       {
+                               insertTableRow();
+                       }
+                       else if(command.equals("inserttablecolumn"))
+                       {
+                               insertTableColumn();
+                       }
+                       else if(command.equals("deletetablerow"))
+                       {
+                               deleteTableRow();
+                       }
+                       else if(command.equals("deletetablecolumn"))
+                       {
+                               deleteTableColumn();
+                       }
+                       else if(command.equals("insertbreak"))
+                       {
+                               insertBreak();
+                       }
+                       else if(command.equals("insertlocalimage"))
+                       {
+                               insertLocalImage(null);
+                       }
+                       else if(command.equals("insertserverimage"))
+                       {
+                               insertServerImage();
+                       }
+                       else if(command.equals("insertnbsp"))
+                       {
+                               insertNonbreakingSpace();
+                       }
+                       else if(command.equals("insertform"))
+                       {
+                               String[] fieldNames  = { "name", "method",   "enctype" };
+                               String[] fieldTypes  = { "text", "combo",    "text" };
+                               String[] fieldValues = { "",     "POST,GET", "text" };
+                               insertFormElement(HTML.Tag.FORM, "form", (Hashtable)null, fieldNames, fieldTypes, fieldValues, true);
+                       }
+                       else if(command.equals("inserttextfield"))
+                       {
+                               Hashtable htAttribs = new Hashtable();
+                               htAttribs.put("type", "text");
+                               String[] fieldNames = { "name", "value", "size", "maxlength" };
+                               String[] fieldTypes = { "text", "text",  "text", "text" };
+                               insertFormElement(HTML.Tag.INPUT, "input", htAttribs, fieldNames, fieldTypes, false);
+                       }
+                       else if(command.equals("inserttextarea"))
+                       {
+                               String[] fieldNames = { "name", "rows", "cols" };
+                               String[] fieldTypes = { "text", "text", "text" };
+                               insertFormElement(HTML.Tag.TEXTAREA, "textarea", (Hashtable)null, fieldNames, fieldTypes, true);
+                       }
+                       else if(command.equals("insertcheckbox"))
+                       {
+                               Hashtable htAttribs = new Hashtable();
+                               htAttribs.put("type", "checkbox");
+                               String[] fieldNames = { "name", "checked" };
+                               String[] fieldTypes = { "text", "bool" };
+                               insertFormElement(HTML.Tag.INPUT, "input", htAttribs, fieldNames, fieldTypes, false);
+                       }
+                       else if(command.equals("insertradiobutton"))
+                       {
+                               Hashtable htAttribs = new Hashtable();
+                               htAttribs.put("type", "radio");
+                               String[] fieldNames = { "name", "checked" };
+                               String[] fieldTypes = { "text", "bool" };
+                               insertFormElement(HTML.Tag.INPUT, "input", htAttribs, fieldNames, fieldTypes, false);
+                       }
+                       else if(command.equals("insertpassword"))
+                       {
+                               Hashtable htAttribs = new Hashtable();
+                               htAttribs.put("type", "password");
+                               String[] fieldNames = { "name", "value", "size", "maxlength" };
+                               String[] fieldTypes = { "text", "text",  "text", "text" };
+                               insertFormElement(HTML.Tag.INPUT, "input", htAttribs, fieldNames, fieldTypes, false);
+                       }
+                       else if(command.equals("insertbutton"))
+                       {
+                               Hashtable htAttribs = new Hashtable();
+                               htAttribs.put("type", "button");
+                               String[] fieldNames = { "name", "value" };
+                               String[] fieldTypes = { "text", "text" };
+                               insertFormElement(HTML.Tag.INPUT, "input", htAttribs, fieldNames, fieldTypes, false);
+                       }
+                       else if(command.equals("insertbuttonsubmit"))
+                       {
+                               Hashtable htAttribs = new Hashtable();
+                               htAttribs.put("type", "submit");
+                               String[] fieldNames = { "name", "value" };
+                               String[] fieldTypes = { "text", "text" };
+                               insertFormElement(HTML.Tag.INPUT, "input", htAttribs, fieldNames, fieldTypes, false);
+                       }
+                       else if(command.equals("insertbuttonreset"))
+                       {
+                               Hashtable htAttribs = new Hashtable();
+                               htAttribs.put("type", "reset");
+                               String[] fieldNames = { "name", "value" };
+                               String[] fieldTypes = { "text", "text" };
+                               insertFormElement(HTML.Tag.INPUT, "input", htAttribs, fieldNames, fieldTypes, false);
+                       }
+                       else if(command.equals("find"))
+                       {
+                               doSearch((String)null, (String)null, false, lastSearchCaseSetting, lastSearchTopSetting);
+                       }
+                       else if(command.equals("findagain"))
+                       {
+                               doSearch(lastSearchFindTerm, (String)null, false, lastSearchCaseSetting, false);
+                       }
+                       else if(command.equals("replace"))
+                       {
+                               doSearch((String)null, (String)null, true, lastSearchCaseSetting, lastSearchTopSetting);
+                       }
+                       else if(command.equals("exit"))
+                       {
+                               this.dispose();
+                       }
+                       else if(command.equals("helpabout"))
+                       {
+                               SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("About"), true, Translatrix.getTranslationString("AboutMessage"), SimpleInfoDialog.INFO);
+                       }
+                       else if(command.equals("spellcheck"))
+                       {
+                               spellCheck.checkSpelling(new DocumentWordTokenizer(jtpMain.getDocument()));
+                       }
+               }
+               catch(IOException ioe)
+               {
+                       logException("IOException in actionPerformed method", ioe);
+                       SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorIOException"), SimpleInfoDialog.ERROR);
+               }
+               catch(BadLocationException ble)
+               {
+                       logException("BadLocationException in actionPerformed method", ble);
+                       SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorBadLocationException"), SimpleInfoDialog.ERROR);
+               }
+               catch(NumberFormatException nfe)
+               {
+                       logException("NumberFormatException in actionPerformed method", nfe);
+                       SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorNumberFormatException"), SimpleInfoDialog.ERROR);
+               }
+               catch(ClassNotFoundException cnfe)
+               {
+                       logException("ClassNotFound Exception in actionPerformed method", cnfe);
+                       SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorClassNotFoundException "), SimpleInfoDialog.ERROR);
+               }
+               catch(RuntimeException re)
+               {
+                       logException("RuntimeException in actionPerformed method", re);
+                       SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorRuntimeException"), SimpleInfoDialog.ERROR);
+               }
+       }
+
+       /* KeyListener methods */
+       public void keyTyped(KeyEvent ke)
+       {
+               Element elem;
+               String selectedText;
+               int pos = this.getCaretPosition();
+               int repos = -1;
+               if(ke.getKeyChar() == KeyEvent.VK_BACK_SPACE)
+               {
+                       try
+                       {
+                               if(pos > 0)
+                               {
+                                       if((selectedText = jtpMain.getSelectedText()) != null)
+                                       {
+                                               htmlUtilities.delete();
+                                               return;
+                                       }
+                                       else
+                                       {
+                                               int sOffset = htmlDoc.getParagraphElement(pos).getStartOffset();
+                                               if(sOffset == jtpMain.getSelectionStart())
+                                               {
+                                                       boolean content = true;
+                                                       if(htmlUtilities.checkParentsTag(HTML.Tag.LI))
+                                                       {
+                                                               elem = htmlUtilities.getListItemParent();
+                                                               content = false;
+                                                               int so = elem.getStartOffset();
+                                                               int eo = elem.getEndOffset();
+                                                               if(so + 1 < eo)
+                                                               {
+                                                                       char[] temp = jtpMain.getText(so, eo - so).toCharArray();
+                                                                       for(int i=0; i < temp.length; i++)
+                                                                       {
+                                                                               if(!(new Character(temp[i])).isWhitespace(temp[i]))
+                                                                               {
+                                                                                       content = true;
+                                                                               }
+                                                                       }
+                                                               }
+                                                               if(!content)
+                                                               {
+                                                                       Element listElement = elem.getParentElement();
+                                                                       htmlUtilities.removeTag(elem, true);
+                                                                       this.setCaretPosition(sOffset - 1);
+                                                                       return;
+                                                               }
+                                                               else
+                                                               {
+                                                                       jtpMain.setCaretPosition(jtpMain.getCaretPosition() - 1);
+                                                                       jtpMain.moveCaretPosition(jtpMain.getCaretPosition() - 2);
+                                                                       jtpMain.replaceSelection("");
+                                                                       return;
+                                                               }
+                                                       }
+                                                       else if(htmlUtilities.checkParentsTag(HTML.Tag.TABLE))
+                                                       {
+                                                               jtpMain.setCaretPosition(jtpMain.getCaretPosition() - 1);
+                                                               ke.consume();
+                                                               return;
+                                                       }
+                                               }
+                                               jtpMain.replaceSelection("");
+                                               return;
+                                       }
+                               }
+                       }
+                       catch (BadLocationException ble)
+                       {
+                               logException("BadLocationException in keyTyped method", ble);
+                               SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorBadLocationException"), SimpleInfoDialog.ERROR);
+                       }
+                       catch (IOException ioe)
+                       {
+                               logException("IOException in keyTyped method", ioe);
+                               SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorIOException"), SimpleInfoDialog.ERROR);
+                       }
+               }
+               else if(ke.getKeyChar() == KeyEvent.VK_ENTER)
+               {
+                       try
+                       {
+                               if(htmlUtilities.checkParentsTag(HTML.Tag.UL) == true | htmlUtilities.checkParentsTag(HTML.Tag.OL) == true)
+                               {
+                                       elem = htmlUtilities.getListItemParent();
+                                       int so = elem.getStartOffset();
+                                       int eo = elem.getEndOffset();
+                                       char[] temp = this.getTextPane().getText(so,eo-so).toCharArray();
+                                       boolean content = false;
+                                       for(int i=0;i<temp.length;i++)
+                                       {
+                                               if(!(new Character(temp[i])).isWhitespace(temp[i]))
+                                               {
+                                                       content = true;
+                                               }
+                                       }
+                                       if(content)
+                                       {
+                                               int end = -1;
+                                               int j = temp.length;
+                                               do
+                                               {
+                                                       j--;
+                                                       if(new Character(temp[j]).isLetterOrDigit(temp[j]))
+                                                       {
+                                                               end = j;
+                                                       }
+                                               } while (end == -1 && j >= 0);
+                                               j = end;
+                                               do
+                                               {
+                                                       j++;
+                                                       if(!new Character(temp[j]).isSpaceChar(temp[j]))
+                                                       {
+                                                               repos = j - end -1;
+                                                       }
+                                               } while (repos == -1 && j < temp.length);
+                                               if(repos == -1)
+                                               {
+                                                       repos = 0;
+                                               }
+                                       }
+                                       if(elem.getStartOffset() == elem.getEndOffset() || !content)
+                                       {
+                                               manageListElement(elem);
+                                       }
+                                       else
+                                       {
+                                               if(this.getCaretPosition() + 1 == elem.getEndOffset())
+                                               {
+                                                       insertListStyle(elem);
+                                                       this.setCaretPosition(pos - repos);
+                                               }
+                                               else
+                                               {
+                                                       int caret = this.getCaretPosition();
+                                                       String tempString = this.getTextPane().getText(caret, eo - caret);
+                                                       this.getTextPane().select(caret, eo - 1);
+                                                       this.getTextPane().replaceSelection("");
+                                                       htmlUtilities.insertListElement(tempString);
+                                                       Element newLi = htmlUtilities.getListItemParent();
+                                                       this.setCaretPosition(newLi.getEndOffset() - 1);
+                                               }
+                                       }
+                               }
+                       }
+                       catch (BadLocationException ble)
+                       {
+                               logException("BadLocationException in keyTyped method", ble);
+                               SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorBadLocationException"), SimpleInfoDialog.ERROR);
+                       }
+                       catch (IOException ioe)
+                       {
+                               logException("IOException in keyTyped method", ioe);
+                               SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorIOException"), SimpleInfoDialog.ERROR);
+                       }
+               }
+       }
+       public void keyPressed(KeyEvent e) {}
+       public void keyReleased(KeyEvent e) {}
+
+       public void insertListStyle(Element element)
+       throws BadLocationException,IOException
+       {
+               if(element.getParentElement().getName() == "ol")
+               {
+                       actionListOrdered.actionPerformed(new ActionEvent(new Object(), 0, "newListPoint"));
+               }
+               else
+               {
+                       actionListUnordered.actionPerformed(new ActionEvent(new Object(), 0, "newListPoint"));
+               }
+       }
+
+       /* DocumentListener methods */
+       public void changedUpdate(DocumentEvent de)     { handleDocumentChange(de); }
+       public void insertUpdate(DocumentEvent de)      { handleDocumentChange(de); }
+       public void removeUpdate(DocumentEvent de)      { handleDocumentChange(de); }
+       public void handleDocumentChange(DocumentEvent de)
+       {
+               if(!exclusiveEdit)
+               {
+                       if(jspSource.isShowing())
+                       {
+                               if(de.getDocument() instanceof HTMLDocument || de.getDocument() instanceof ExtendedHTMLDocument)
+                               {
+                                       jtpSource.getDocument().removeDocumentListener(this);
+                                       jtpSource.setText(jtpMain.getText());
+                                       jtpSource.getDocument().addDocumentListener(this);
+                               }
+                               else if(de.getDocument() instanceof PlainDocument || de.getDocument() instanceof DefaultStyledDocument)
+                               {
+                                       jtpMain.getDocument().removeDocumentListener(this);
+                                       jtpMain.setText(jtpSource.getText());
+                                       jtpMain.getDocument().addDocumentListener(this);
+                               }
+                       }
+               }
+       }
+
+       /* SpellCheckListener methods */
+       public void spellingError(SpellCheckEvent event)
+       {
+               spellDialog.show(event);
+       }
+
+       /** Method for setting a document as the current document for the text pane
+         * and re-registering the controls and settings for it
+         */
+       public void registerDocument(ExtendedHTMLDocument htmlDoc)
+       {
+               jtpMain.setDocument(htmlDoc);
+               jtpMain.getDocument().addUndoableEditListener(new CustomUndoableEditListener());
+               jtpMain.getDocument().addDocumentListener(this);
+               purgeUndos();
+               registerDocumentStyles();
+       }
+
+       /** Method for locating the available CSS style for the document and adding
+         * them to the styles selector
+         */
+       public void registerDocumentStyles()
+       {
+               if(jcmbStyleSelector == null || htmlDoc == null)
+               {
+                       return;
+               }
+               jcmbStyleSelector.setEnabled(false);
+               jcmbStyleSelector.removeAllItems();
+               jcmbStyleSelector.addItem(Translatrix.getTranslationString("NoCSSStyle"));
+               for(Enumeration e = htmlDoc.getStyleNames(); e.hasMoreElements();)
+               {
+                       String name = (String) e.nextElement();
+                       if(name.length() > 0 && name.charAt(0) == '.')
+                       {
+                               jcmbStyleSelector.addItem(name.substring(1));
+                       }
+               }
+               jcmbStyleSelector.setEnabled(true);
+       }
+
+       /** Method for inserting an HTML Table
+         */
+       private void insertTable(Hashtable attribs, String[] fieldNames, String[] fieldTypes)
+       throws IOException, BadLocationException, RuntimeException, NumberFormatException
+       {
+               int caretPos = jtpMain.getCaretPosition();
+               StringBuffer compositeElement = new StringBuffer("<TABLE");
+               if(attribs != null && attribs.size() > 0)
+               {
+                       Enumeration attribEntries = attribs.keys();
+                       while(attribEntries.hasMoreElements())
+                       {
+                               Object entryKey   = attribEntries.nextElement();
+                               Object entryValue = attribs.get(entryKey);
+                               if(entryValue != null && entryValue != "")
+                               {
+                                       compositeElement.append(" " + entryKey + "=" + '"' + entryValue + '"');
+                               }
+                       }
+               }
+               int rows = 0;
+               int cols = 0;
+               if(fieldNames != null && fieldNames.length > 0)
+               {
+                       PropertiesDialog propertiesDialog = new PropertiesDialog(this.getFrame(), fieldNames, fieldTypes, Translatrix.getTranslationString("FormDialogTitle"), true);
+                       propertiesDialog.show();
+                       String decision = propertiesDialog.getDecisionValue();
+                       if(decision.equals(Translatrix.getTranslationString("DialogCancel")))
+                       {
+                               propertiesDialog.dispose();
+                               propertiesDialog = null;
+                               return;
+                       }
+                       else
+                       {
+                               for(int iter = 0; iter < fieldNames.length; iter++)
+                               {
+                                       String fieldName = fieldNames[iter];
+                                       String propValue = propertiesDialog.getFieldValue(fieldName);
+                                       if(propValue != null && propValue != "" && propValue.length() > 0)
+                                       {
+                                               if(fieldName.equals("rows"))
+                                               {
+                                                       rows = Integer.parseInt(propValue);
+                                               }
+                                               else if(fieldName.equals("cols"))
+                                               {
+                                                       cols = Integer.parseInt(propValue);
+                                               }
+                                               else
+                                               {
+                                                       compositeElement.append(" " + fieldName + "=" + '"' + propValue + '"');
+                                               }
+                                       }
+                               }
+                       }
+                       propertiesDialog.dispose();
+                       propertiesDialog = null;
+               }
+               compositeElement.append(">");
+               for(int i = 0; i < rows; i++)
+               {
+                       compositeElement.append("<TR>");
+                       for(int j = 0; j < cols; j++)
+                       {
+                               compositeElement.append("<TD></TD>");
+                       }
+                       compositeElement.append("</TR>");
+               }
+               compositeElement.append("</TABLE><P>&nbsp;<P>");
+               htmlKit.insertHTML(htmlDoc, caretPos, compositeElement.toString(), 0, 0, HTML.Tag.TABLE);
+               jtpMain.setCaretPosition(caretPos + 1);
+               refreshOnUpdate();
+       }
+
+       /** Method for inserting a row into an HTML Table
+         */
+       private void insertTableRow()
+       {
+               int caretPos = jtpMain.getCaretPosition();
+               Element element = htmlDoc.getCharacterElement(jtpMain.getCaretPosition());
+               Element elementParent = element.getParentElement();
+               int startPoint  = -1;
+               int columnCount = -1;
+               while(elementParent != null && !elementParent.getName().equals("body"))
+               {
+                       if(elementParent.getName().equals("tr"))
+                       {
+                               startPoint  = elementParent.getStartOffset();
+                               columnCount = elementParent.getElementCount();
+                               break;
+                       }
+                       else
+                       {
+                               elementParent = elementParent.getParentElement();
+                       }
+               }
+               if(startPoint > -1 && columnCount > -1)
+               {
+                       jtpMain.setCaretPosition(startPoint);
+                       StringBuffer sRow = new StringBuffer();
+                       sRow.append("<TR>");
+                       for(int i = 0; i < columnCount; i++)
+                       {
+                               sRow.append("<TD></TD>");
+                       }
+                       sRow.append("</TR>");
+                       ActionEvent actionEvent = new ActionEvent(jtpMain, 0, "insertTableRow");
+                       new HTMLEditorKit.InsertHTMLTextAction("insertTableRow", sRow.toString(), HTML.Tag.TABLE, HTML.Tag.TR).actionPerformed(actionEvent);
+                       refreshOnUpdate();
+                       jtpMain.setCaretPosition(caretPos);
+               }
+       }
+
+       /** Method for inserting a column into an HTML Table
+         */
+       private void insertTableColumn()
+       {
+               int caretPos = jtpMain.getCaretPosition();
+               Element element = htmlDoc.getCharacterElement(jtpMain.getCaretPosition());
+               Element elementParent = element.getParentElement();
+               int startPoint = -1;
+               int rowCount   = -1;
+               int cellOffset =  0;
+               while(elementParent != null && !elementParent.getName().equals("body"))
+               {
+                       if(elementParent.getName().equals("table"))
+                       {
+                               startPoint = elementParent.getStartOffset();
+                               rowCount   = elementParent.getElementCount();
+                               break;
+                       }
+                       else if(elementParent.getName().equals("tr"))
+                       {
+                               int rowStart = elementParent.getStartOffset();
+                               int rowCells = elementParent.getElementCount();
+                               for(int i = 0; i < rowCells; i++)
+                               {
+                                       Element currentCell = elementParent.getElement(i);
+                                       if(jtpMain.getCaretPosition() >= currentCell.getStartOffset() && jtpMain.getCaretPosition() <= currentCell.getEndOffset())
+                                       {
+                                               cellOffset = i;
+                                       }
+                               }
+                               elementParent = elementParent.getParentElement();
+                       }
+                       else
+                       {
+                               elementParent = elementParent.getParentElement();
+                       }
+               }
+               if(startPoint > -1 && rowCount > -1)
+               {
+                       jtpMain.setCaretPosition(startPoint);
+                       String sCell = "<TD></TD>";
+                       ActionEvent actionEvent = new ActionEvent(jtpMain, 0, "insertTableCell");
+                       for(int i = 0; i < rowCount; i++)
+                       {
+                               Element row = elementParent.getElement(i);
+                               Element whichCell = row.getElement(cellOffset);
+                               jtpMain.setCaretPosition(whichCell.getStartOffset());
+                               new HTMLEditorKit.InsertHTMLTextAction("insertTableCell", sCell, HTML.Tag.TR, HTML.Tag.TD, HTML.Tag.TH, HTML.Tag.TD).actionPerformed(actionEvent);
+                       }
+                       refreshOnUpdate();
+                       jtpMain.setCaretPosition(caretPos);
+               }
+       }
+
+       /** Method for inserting a cell into an HTML Table
+         */
+       private void insertTableCell()
+       {
+               String sCell = "<TD></TD>";
+               ActionEvent actionEvent = new ActionEvent(jtpMain, 0, "insertTableCell");
+               new HTMLEditorKit.InsertHTMLTextAction("insertTableCell", sCell, HTML.Tag.TR, HTML.Tag.TD, HTML.Tag.TH, HTML.Tag.TD).actionPerformed(actionEvent);
+               refreshOnUpdate();
+       }
+
+       /** Method for deleting a row from an HTML Table
+         */
+       private void deleteTableRow()
+       throws BadLocationException
+       {
+               int caretPos = jtpMain.getCaretPosition();
+               Element element = htmlDoc.getCharacterElement(jtpMain.getCaretPosition());
+               Element elementParent = element.getParentElement();
+               int startPoint = -1;
+               int endPoint   = -1;
+               while(elementParent != null && !elementParent.getName().equals("body"))
+               {
+                       if(elementParent.getName().equals("tr"))
+                       {
+                               startPoint = elementParent.getStartOffset();
+                               endPoint   = elementParent.getEndOffset();
+                               break;
+                       }
+                       else
+                       {
+                               elementParent = elementParent.getParentElement();
+                       }
+               }
+               if(startPoint > -1 && endPoint > startPoint)
+               {
+                       htmlDoc.remove(startPoint, endPoint - startPoint);
+                       jtpMain.setDocument(htmlDoc);
+                       registerDocument(htmlDoc);
+                       refreshOnUpdate();
+                       if(caretPos >= htmlDoc.getLength())
+                       {
+                               caretPos = htmlDoc.getLength() - 1;
+                       }
+                       jtpMain.setCaretPosition(caretPos);
+               }
+       }
+
+       /** Method for deleting a column from an HTML Table
+         */
+       private void deleteTableColumn()
+       throws BadLocationException
+       {
+               int caretPos = jtpMain.getCaretPosition();
+               Element element       = htmlDoc.getCharacterElement(jtpMain.getCaretPosition());
+               Element elementParent = element.getParentElement();
+               Element elementCell   = (Element)null;
+               Element elementRow    = (Element)null;
+               Element elementTable  = (Element)null;
+               // Locate the table, row, and cell location of the cursor
+               while(elementParent != null && !elementParent.getName().equals("body"))
+               {
+                       if(elementParent.getName().equals("td"))
+                       {
+                               elementCell = elementParent;
+                       }
+                       else if(elementParent.getName().equals("tr"))
+                       {
+                               elementRow = elementParent;
+                       }
+                       else if(elementParent.getName().equals("table"))
+                       {
+                               elementTable = elementParent;
+                       }
+                       elementParent = elementParent.getParentElement();
+               }
+               int whichColumn = -1;
+               if(elementCell != null && elementRow != null && elementTable != null)
+               {
+                       // Find the column the cursor is in
+                       for(int i = 0; i < elementRow.getElementCount(); i++)
+                       {
+                               if(elementCell == elementRow.getElement(i))
+                               {
+                                       whichColumn = i;
+                               }
+                       }
+                       if(whichColumn > -1)
+                       {
+                               // Iterate through the table rows, deleting cells from the indicated column
+                               for(int i = 0; i < elementTable.getElementCount(); i++)
+                               {
+                                       elementRow  = elementTable.getElement(i);
+                                       elementCell = (elementRow.getElementCount() > whichColumn ? elementRow.getElement(whichColumn) : elementRow.getElement(elementRow.getElementCount() - 1));
+                                       int columnCellStart = elementCell.getStartOffset();
+                                       int columnCellEnd   = elementCell.getEndOffset();
+                                       htmlDoc.remove(columnCellStart, columnCellEnd - columnCellStart);
+                               }
+                               jtpMain.setDocument(htmlDoc);
+                               registerDocument(htmlDoc);
+                               refreshOnUpdate();
+                               if(caretPos >= htmlDoc.getLength())
+                               {
+                                       caretPos = htmlDoc.getLength() - 1;
+                               }
+                               jtpMain.setCaretPosition(caretPos);
+                       }
+               }
+       }
+
+       /** Method for inserting a break (BR) element
+         */
+       private void insertBreak()
+       throws IOException, BadLocationException, RuntimeException
+       {
+               int caretPos = jtpMain.getCaretPosition();
+               htmlKit.insertHTML(htmlDoc, caretPos, "<BR>", 0, 0, HTML.Tag.BR);
+               jtpMain.setCaretPosition(caretPos + 1);
+       }
+
+       /** Method for inserting a non-breaking space (&nbsp;)
+         */
+       private void insertNonbreakingSpace()
+       throws IOException, BadLocationException, RuntimeException
+       {
+               int caretPos = jtpMain.getCaretPosition();
+               htmlDoc.insertString(caretPos, "\240", jtpMain.getInputAttributes());
+               jtpMain.setCaretPosition(caretPos + 1);
+       }
+
+       /** Method for inserting a form element
+         */
+       private void insertFormElement(HTML.Tag baseTag, String baseElement, Hashtable attribs, String[] fieldNames, String[] fieldTypes, String[] fieldValues, boolean hasClosingTag)
+       throws IOException, BadLocationException, RuntimeException
+       {
+               int caretPos = jtpMain.getCaretPosition();
+               StringBuffer compositeElement = new StringBuffer("<" + baseElement);
+               if(attribs != null && attribs.size() > 0)
+               {
+                       Enumeration attribEntries = attribs.keys();
+                       while(attribEntries.hasMoreElements())
+                       {
+                               Object entryKey   = attribEntries.nextElement();
+                               Object entryValue = attribs.get(entryKey);
+                               if(entryValue != null && entryValue != "")
+                               {
+                                       compositeElement.append(" " + entryKey + "=" + '"' + entryValue + '"');
+                               }
+                       }
+               }
+               if(fieldNames != null && fieldNames.length > 0)
+               {
+                       PropertiesDialog propertiesDialog = new PropertiesDialog(this.getFrame(), fieldNames, fieldTypes, fieldValues, Translatrix.getTranslationString("FormDialogTitle"), true);
+                       propertiesDialog.show();
+                       String decision = propertiesDialog.getDecisionValue();
+                       if(decision.equals(Translatrix.getTranslationString("DialogCancel")))
+                       {
+                               propertiesDialog.dispose();
+                               propertiesDialog = null;
+                               return;
+                       }
+                       else
+                       {
+                               for(int iter = 0; iter < fieldNames.length; iter++)
+                               {
+                                       String fieldName = fieldNames[iter];
+                                       String propValue = propertiesDialog.getFieldValue(fieldName);
+                                       if(propValue != null && propValue.length() > 0)
+                                       {
+                                               if(fieldName.equals("checked"))
+                                               {
+                                                       if(propValue.equals("true"))
+                                                       {
+                                                               compositeElement.append(" " + fieldName + "=" + '"' + propValue + '"');
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       compositeElement.append(" " + fieldName + "=" + '"' + propValue + '"');
+                                               }
+                                       }
+                               }
+                       }
+                       propertiesDialog.dispose();
+                       propertiesDialog = null;
+               }
+               // --- Convenience for editing, this makes the FORM visible
+               if(useFormIndicator && baseElement.equals("form"))
+               {
+                       compositeElement.append(" bgcolor=" + '"' + clrFormIndicator + '"');
+               }
+               // --- END
+               compositeElement.append(">");
+               if(hasClosingTag)
+               {
+                       compositeElement.append("</" + baseElement + ">");
+               }
+               if(baseTag == HTML.Tag.FORM)
+               {
+                       compositeElement.append("<P>&nbsp;</P>");
+               }
+               htmlKit.insertHTML(htmlDoc, caretPos, compositeElement.toString(), 0, 0, baseTag);
+               // jtpMain.setCaretPosition(caretPos + 1);
+               refreshOnUpdate();
+       }
+
+       /** Alternate method call for inserting a form element
+         */
+       private void insertFormElement(HTML.Tag baseTag, String baseElement, Hashtable attribs, String[] fieldNames, String[] fieldTypes, boolean hasClosingTag)
+       throws IOException, BadLocationException, RuntimeException
+       {
+               insertFormElement(baseTag, baseElement, attribs, fieldNames, fieldTypes, new String[fieldNames.length], hasClosingTag);
+       }
+
+       /** Method that handles initial list insertion and deletion
+         */
+       public void manageListElement(Element element)
+       {
+               Element h = htmlUtilities.getListItemParent();
+               Element listElement = h.getParentElement();
+               if(h != null)
+               {
+                       htmlUtilities.removeTag(h, true);
+               }
+       }
+
+       /** Method to initiate a find/replace operation
+         */
+       private void doSearch(String searchFindTerm, String searchReplaceTerm, boolean bIsFindReplace, boolean bCaseSensitive, boolean bStartAtTop)
+       {
+               boolean bReplaceAll = false;
+               JTextPane searchPane = jtpMain;
+               if(jspSource.isShowing() || jtpSource.hasFocus())
+               {
+                       searchPane = jtpSource;
+               }
+               if(searchFindTerm == null || (bIsFindReplace && searchReplaceTerm == null))
+               {
+                       SearchDialog sdSearchInput = new SearchDialog(this.getFrame(), Translatrix.getTranslationString("SearchDialogTitle"), true, bIsFindReplace, bCaseSensitive, bStartAtTop);
+                       searchFindTerm    = sdSearchInput.getFindTerm();
+                       searchReplaceTerm = sdSearchInput.getReplaceTerm();
+                       bCaseSensitive    = sdSearchInput.getCaseSensitive();
+                       bStartAtTop       = sdSearchInput.getStartAtTop();
+                       bReplaceAll       = sdSearchInput.getReplaceAll();
+               }
+               if(searchFindTerm != null && (!bIsFindReplace || searchReplaceTerm != null))
+               {
+                       if(bReplaceAll)
+                       {
+                               int results = findText(searchFindTerm, searchReplaceTerm, bCaseSensitive, 0);
+                               int findOffset = 0;
+                               if(results > -1)
+                               {
+                                       while(results > -1)
+                                       {
+                                               findOffset = findOffset + searchReplaceTerm.length();
+                                               results    = findText(searchFindTerm, searchReplaceTerm, bCaseSensitive, findOffset);
+                                       }
+                               }
+                               else
+                               {
+                                       SimpleInfoDialog sidWarn = new SimpleInfoDialog(this.getFrame(), "", true, Translatrix.getTranslationString("ErrorNoOccurencesFound") + ":\n" + searchFindTerm, SimpleInfoDialog.WARNING);
+                               }
+                       }
+                       else
+                       {
+                               int results = findText(searchFindTerm, searchReplaceTerm, bCaseSensitive, (bStartAtTop ? 0 : searchPane.getCaretPosition()));
+                               if(results == -1)
+                               {
+                                       SimpleInfoDialog sidWarn = new SimpleInfoDialog(this.getFrame(), "", true, Translatrix.getTranslationString("ErrorNoMatchFound") + ":\n" + searchFindTerm, SimpleInfoDialog.WARNING);
+                               }
+                       }
+                       lastSearchFindTerm    = new String(searchFindTerm);
+                       if(searchReplaceTerm != null)
+                       {
+                               lastSearchReplaceTerm = new String(searchReplaceTerm);
+                       }
+                       else
+                       {
+                               lastSearchReplaceTerm = (String)null;
+                       }
+                       lastSearchCaseSetting = bCaseSensitive;
+                       lastSearchTopSetting  = bStartAtTop;
+               }
+       }
+
+       /** Method for finding (and optionally replacing) a string in the text
+         */
+       private int findText(String findTerm, String replaceTerm, boolean bCaseSenstive, int iOffset)
+       {
+               JTextPane jtpFindSource;
+               if(jspSource.isShowing() || jtpSource.hasFocus())
+               {
+                       jtpFindSource = jtpSource;
+               }
+               else
+               {
+                       jtpFindSource = jtpMain;
+               }
+               int searchPlace = -1;
+               try
+               {
+                       Document baseDocument = jtpFindSource.getDocument();
+                       searchPlace =
+                               (bCaseSenstive ?
+                                       baseDocument.getText(0, baseDocument.getLength()).indexOf(findTerm, iOffset) :
+                                       baseDocument.getText(0, baseDocument.getLength()).toLowerCase().indexOf(findTerm.toLowerCase(), iOffset)
+                               );
+                       if(searchPlace > -1)
+                       {
+                               if(replaceTerm != null)
+                               {
+                                       AttributeSet attribs = null;
+                                       if(baseDocument instanceof HTMLDocument)
+                                       {
+                                               Element element = ((HTMLDocument)baseDocument).getCharacterElement(searchPlace);
+                                               attribs = element.getAttributes();
+                                       }
+                                       baseDocument.remove(searchPlace, findTerm.length());
+                                       baseDocument.insertString(searchPlace, replaceTerm, attribs);
+                                       jtpFindSource.setCaretPosition(searchPlace + replaceTerm.length());
+                                       jtpFindSource.requestFocus();
+                                       jtpFindSource.select(searchPlace, searchPlace + replaceTerm.length());
+                               }
+                               else
+                               {
+                                       jtpFindSource.setCaretPosition(searchPlace + findTerm.length());
+                                       jtpFindSource.requestFocus();
+                                       jtpFindSource.select(searchPlace, searchPlace + findTerm.length());
+                               }
+                       }
+               }
+               catch(BadLocationException ble)
+               {
+                       logException("BadLocationException in actionPerformed method", ble);
+                       SimpleInfoDialog sidAbout = new SimpleInfoDialog(this.getFrame(), Translatrix.getTranslationString("Error"), true, Translatrix.getTranslationString("ErrorBadLocationException"), SimpleInfoDialog.ERROR);
+               }
+               return searchPlace;
+       }
+
+       /** Method for inserting an image from a file
+         */
+       private void insertLocalImage(File whatImage)
+       throws IOException, BadLocationException, RuntimeException
+       {
+               if(whatImage == null)
+               {
+                       whatImage = getImageFromChooser(".", extsIMG, Translatrix.getTranslationString("FiletypeIMG"));
+               }
+               if(whatImage != null)
+               {
+                       int caretPos = jtpMain.getCaretPosition();
+                       htmlKit.insertHTML(htmlDoc, caretPos, "<IMG SRC=\"" + whatImage + "\">", 0, 0, HTML.Tag.IMG);
+                       jtpMain.setCaretPosition(caretPos + 1);
+                       refreshOnUpdate();
+               }
+       }
+
+       /** Method for inserting an image from a server
+         */
+       private void insertServerImage()
+       throws BadLocationException
+       {
+               if(ServletURL != null)
+               {
+                       try
+                       {
+                               URL theServlet = new URL(ServletURL + "?GetImages=" + TreePilotSystemID + "&ImageExtensions=" + TreePilotProperties.getString("ValidImageExtensions"));
+                               URLConnection conn = theServlet.openConnection();
+                               ObjectInputStream in = new ObjectInputStream(conn.getInputStream());
+                               String[] imageList = (String[]) in.readObject();
+                               int caretPos = jtpMain.getCaretPosition();
+                               ImageDialog imageDialog = new ImageDialog(this, ImageDir + TreePilotSystemID, imageList, "Image Chooser", true);
+                               String selectedImage = imageDialog.getSelectedImage();
+                               imageDialog.dispose();
+                               if(selectedImage != null  && !selectedImage.equals(""))
+                               {
+                                       htmlKit.insertHTML(htmlDoc, caretPos, selectedImage, 0, 0, HTML.Tag.IMG);
+                                       jtpMain.setCaretPosition(caretPos + 1);
+                               }
+                               jtpMain.requestFocus();
+                               in.close();
+                       }
+                       catch (MalformedURLException mue)
+                       {
+                               System.err.println("MalFormedURLException during insertImage " + mue);
+                       }
+                       catch (IOException ie)
+                       {
+                               System.err.println("IOException during insertImage " + ie);
+                       }
+                       catch (ClassNotFoundException cnfe)
+                       {
+                               System.err.println("ClassNotFoundException during insertImage" + cnfe);
+                       }
+               }
+       }
+
+       /** Method for inserting an image
+         */
+       public String insertFile()
+       {
+               String selectedFile = null;
+               if(ServletURL != null)
+               {
+                       try
+                       {
+                               URL theServlet = new URL(ServletURL + "?GetFiles=" + TreePilotSystemID + "&FileExtensions=" + TreePilotProperties.getString("ValidFileExtensions"));
+                               URLConnection conn = theServlet.openConnection();
+                               ObjectInputStream in = new ObjectInputStream(conn.getInputStream());
+                               String[] fileList = (String[]) in.readObject();
+                               FileDialog fileDialog = new FileDialog(this, ImageDir + TreePilotSystemID, fileList, "File Chooser", true);
+                               selectedFile = fileDialog.getSelectedFile();
+                               fileDialog.dispose();
+                               in.close();
+                       }
+                       catch (MalformedURLException mue)
+                       {
+                               System.err.println("MalFormedURLException during insertFile " + mue);
+                       }
+                       catch (IOException ie)
+                       {
+                               System.err.println("IOException during insertFile " + ie);
+                       }
+                       catch (ClassNotFoundException cnfe)
+                       {
+                               System.err.println("ClassNotFoundException during insertFile" + cnfe);
+                       }
+               }
+               return selectedFile;
+       }
+
+       /** Method for saving text as a complete HTML document
+         */
+       private void writeOut(HTMLDocument doc, File whatFile)
+       throws IOException, BadLocationException
+       {
+               if(whatFile == null)
+               {
+                       whatFile = getFileFromChooser(".", JFileChooser.SAVE_DIALOG, extsHTML, Translatrix.getTranslationString("FiletypeHTML"));
+               }
+               if(whatFile != null)
+               {
+                       FileWriter fw = new FileWriter(whatFile);
+                       htmlKit.write(fw, doc, 0, doc.getLength());
+                       fw.flush();
+                       fw.close();
+                       currentFile = whatFile;
+                       updateTitle();
+               }
+               refreshOnUpdate();
+       }
+
+       /** Method for saving text as an HTML fragment
+         */
+       private void writeOutFragment(HTMLDocument doc, String containingTag)
+       throws IOException, BadLocationException
+       {
+               File whatFile = getFileFromChooser(".", JFileChooser.SAVE_DIALOG, extsHTML, Translatrix.getTranslationString("FiletypeHTML"));
+               if(whatFile != null)
+               {
+                       FileWriter fw = new FileWriter(whatFile);
+//                     Element eleBody = locateElementInDocument((StyledDocument)doc, containingTag);
+//                     htmlKit.write(fw, doc, eleBody.getStartOffset(), eleBody.getEndOffset());
+                       String docTextCase = jtpSource.getText().toLowerCase();
+                       int tagStart       = docTextCase.indexOf("<" + containingTag.toLowerCase());
+                       int tagStartClose  = docTextCase.indexOf(">", tagStart) + 1;
+                       String closeTag    = "</" + containingTag.toLowerCase() + ">";
+                       int tagEndOpen     = docTextCase.indexOf(closeTag);
+                       if(tagStartClose < 0) { tagStartClose = 0; }
+                       if(tagEndOpen < 0 || tagEndOpen > docTextCase.length()) { tagEndOpen = docTextCase.length(); }
+                       String bodyText = jtpSource.getText().substring(tagStartClose, tagEndOpen);
+                       fw.write(bodyText, 0, bodyText.length());
+                       fw.flush();
+                       fw.close();
+               }
+               refreshOnUpdate();
+       }
+
+       /** Method for saving text as an RTF document
+         */
+       private void writeOutRTF(StyledDocument doc)
+       throws IOException, BadLocationException
+       {
+               File whatFile = getFileFromChooser(".", JFileChooser.SAVE_DIALOG, extsRTF, Translatrix.getTranslationString("FiletypeRTF"));
+               if(whatFile != null)
+               {
+                       FileOutputStream fos = new FileOutputStream(whatFile);
+                       RTFEditorKit rtfKit = new RTFEditorKit();
+                       rtfKit.write(fos, doc, 0, doc.getLength());
+                       fos.flush();
+                       fos.close();
+               }
+               refreshOnUpdate();
+       }
+
+       /** Method for saving text as a Base64 encoded document
+         */
+       private void writeOutBase64(String text)
+       throws IOException, BadLocationException
+       {
+               File whatFile = getFileFromChooser(".", JFileChooser.SAVE_DIALOG, extsB64, Translatrix.getTranslationString("FiletypeB64"));
+               if(whatFile != null)
+               {
+                       String base64text = Base64Codec.encode(text);
+                       FileWriter fw = new FileWriter(whatFile);
+                       fw.write(base64text, 0, base64text.length());
+                       fw.flush();
+                       fw.close();
+               }
+               refreshOnUpdate();
+       }
+
+       /** Method to invoke loading HTML into the app
+         */
+       private void openDocument(File whatFile)
+       throws IOException, BadLocationException
+       {
+               if(whatFile == null)
+               {
+                       whatFile = getFileFromChooser(".", JFileChooser.OPEN_DIALOG, extsHTML, Translatrix.getTranslationString("FiletypeHTML"));
+               }
+               if(whatFile != null)
+               {
+                       try
+                       {
+                               loadDocument(whatFile, null);
+                       }
+                       catch(ChangedCharSetException ccse)
+                       {
+                               String charsetType = ccse.getCharSetSpec().toLowerCase();
+                               int pos = charsetType.indexOf("charset");
+                               if(pos == -1)
+                               {
+                                       throw ccse;
+                               }
+                               while(pos < charsetType.length() && charsetType.charAt(pos) != '=')
+                               {
+                                       pos++;
+                               }
+                               pos++; // Places file cursor past the equals sign (=)
+                               String whatEncoding = charsetType.substring(pos).trim();
+                               loadDocument(whatFile, whatEncoding);
+                       }
+               }
+               refreshOnUpdate();
+       }
+
+       /** Method for loading HTML document into the app, including document encoding setting
+         */
+       private void loadDocument(File whatFile, String whatEncoding)
+       throws IOException, BadLocationException
+       {
+               Reader r = null;
+               htmlDoc = (ExtendedHTMLDocument)(htmlKit.createDefaultDocument());
+               try
+               {
+                       if(whatEncoding == null)
+                       {
+                               r = new InputStreamReader(new FileInputStream(whatFile));
+                       }
+                       else
+                       {
+                               r = new InputStreamReader(new FileInputStream(whatFile), whatEncoding);
+                               htmlDoc.putProperty("IgnoreCharsetDirective", new Boolean(true));
+                       }
+                       htmlKit.read(r, htmlDoc, 0);
+                       r.close();
+                       registerDocument(htmlDoc);
+                       jtpSource.setText(jtpMain.getText());
+                       currentFile = whatFile;
+                       updateTitle();
+               }
+               finally
+               {
+                       if(r != null)
+                       {
+                               r.close();
+                       }
+               }
+       }
+
+       /** Method for loading a Base64 encoded document
+         */
+       private void openDocumentBase64(File whatFile)
+       throws IOException, BadLocationException
+       {
+               if(whatFile == null)
+               {
+                       whatFile = getFileFromChooser(".", JFileChooser.OPEN_DIALOG, extsB64, Translatrix.getTranslationString("FiletypeB64"));
+               }
+               if(whatFile != null)
+               {
+                       FileReader fr = new FileReader(whatFile);
+                       int nextChar = 0;
+                       StringBuffer encodedText = new StringBuffer();
+                       try
+                       {
+                               while((nextChar = fr.read()) != -1)
+                               {
+                                       encodedText.append((char)nextChar);
+                               }
+                               fr.close();
+                               jtpSource.setText(Base64Codec.decode(encodedText.toString()));
+                               jtpMain.setText(jtpSource.getText());
+                               registerDocument((ExtendedHTMLDocument)(jtpMain.getDocument()));
+                       }
+                       finally
+                       {
+                               if(fr != null)
+                               {
+                                       fr.close();
+                               }
+                       }
+               }
+       }
+
+       /** Method for loading a Stylesheet into the app
+         */
+       private void openStyleSheet(File fileCSS)
+       throws IOException
+       {
+               if(fileCSS == null)
+               {
+                       fileCSS = getFileFromChooser(".", JFileChooser.OPEN_DIALOG, extsCSS, Translatrix.getTranslationString("FiletypeCSS"));
+               }
+               if(fileCSS != null)
+               {
+                       String currDocText = jtpMain.getText();
+                       htmlDoc = (ExtendedHTMLDocument)(htmlKit.createDefaultDocument());
+                       styleSheet = htmlDoc.getStyleSheet();
+                       URL cssUrl = fileCSS.toURL();
+                       InputStream is = cssUrl.openStream();
+                       BufferedReader br = new BufferedReader(new InputStreamReader(is));
+                       styleSheet.loadRules(br, cssUrl);
+                       br.close();
+                       htmlDoc = new ExtendedHTMLDocument(styleSheet);
+                       registerDocument(htmlDoc);
+                       jtpMain.setText(currDocText);
+                       jtpSource.setText(jtpMain.getText());
+               }
+               refreshOnUpdate();
+       }
+
+       /** Method for serializing the document out to a file
+         */
+       public void serializeOut(HTMLDocument doc)
+       throws IOException
+       {
+               File whatFile = getFileFromChooser(".", JFileChooser.SAVE_DIALOG, extsSer, Translatrix.getTranslationString("FiletypeSer"));
+               if(whatFile != null)
+               {
+                       ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(whatFile));
+                       oos.writeObject(doc);
+                       oos.flush();
+                       oos.close();
+               }
+               refreshOnUpdate();
+       }
+
+       /** Method for reading in a serialized document from a file
+         */
+       public void serializeIn()
+       throws IOException, ClassNotFoundException
+       {
+               File whatFile = getFileFromChooser(".", JFileChooser.OPEN_DIALOG, extsSer, Translatrix.getTranslationString("FiletypeSer"));
+               if(whatFile != null)
+               {
+                       ObjectInputStream ois = new ObjectInputStream(new FileInputStream(whatFile));
+                       htmlDoc = (ExtendedHTMLDocument)(ois.readObject());
+                       ois.close();
+                       registerDocument(htmlDoc);
+                       validate();
+               }
+               refreshOnUpdate();
+       }
+
+       /** Method for obtaining a File for input/output using a JFileChooser dialog
+         */
+       private File getFileFromChooser(String startDir, int dialogType, String[] exts, String desc)
+       {
+               JFileChooser jfileDialog = new JFileChooser(startDir);
+               jfileDialog.setDialogType(dialogType);
+               jfileDialog.setFileFilter(new MutableFilter(exts, desc));
+               int optionSelected = JFileChooser.CANCEL_OPTION;
+               if(dialogType == JFileChooser.OPEN_DIALOG)
+               {
+                       optionSelected = jfileDialog.showOpenDialog(this);
+               }
+               else if(dialogType == JFileChooser.SAVE_DIALOG)
+               {
+                       optionSelected = jfileDialog.showSaveDialog(this);
+               }
+               else // default to an OPEN_DIALOG
+               {
+                       optionSelected = jfileDialog.showOpenDialog(this);
+               }
+               if(optionSelected == JFileChooser.APPROVE_OPTION)
+               {
+                       return jfileDialog.getSelectedFile();
+               }
+               return (File)null;
+       }
+
+       /** Method for obtaining an Image for input using a custom JFileChooser dialog
+         */
+       private File getImageFromChooser(String startDir, String[] exts, String desc)
+       {
+               ImageFileChooser jImageDialog = new ImageFileChooser(startDir);
+               jImageDialog.setDialogType(JFileChooser.CUSTOM_DIALOG);
+               jImageDialog.setFileFilter(new MutableFilter(exts, desc));
+               jImageDialog.setDialogTitle(Translatrix.getTranslationString("ImageDialogTitle"));
+               int optionSelected = JFileChooser.CANCEL_OPTION;
+               optionSelected = jImageDialog.showDialog(this, Translatrix.getTranslationString("Insert"));
+               if(optionSelected == JFileChooser.APPROVE_OPTION)
+               {
+                       return jImageDialog.getSelectedFile();
+               }
+               return (File)null;
+       }
+
+       /** Method for describing the node hierarchy of the document
+         */
+       private void describeDocument(StyledDocument doc)
+       {
+               Element[] elements = doc.getRootElements();
+               for(int i = 0; i < elements.length; i++)
+               {
+                       indent = indentStep;
+                       for(int j = 0; j < indent; j++) { System.out.print(" "); }
+                       System.out.print(elements[i]);
+                       traverseElement(elements[i]);
+                       System.out.println("");
+               }
+       }
+
+       /** Traverses nodes for the describing method
+         */
+       private void traverseElement(Element element)
+       {
+               indent += indentStep;
+               for(int i = 0; i < element.getElementCount(); i++)
+               {
+                       for(int j = 0; j < indent; j++) { System.out.print(" "); }
+                       System.out.print(element.getElement(i));
+                       traverseElement(element.getElement(i));
+               }
+               indent -= indentStep;
+       }
+
+       /** Method to locate a node element by name
+         */
+       private Element locateElementInDocument(StyledDocument doc, String elementName)
+       {
+               Element[] elements = doc.getRootElements();
+               for(int i = 0; i < elements.length; i++)
+               {
+                       if(elements[i].getName().equalsIgnoreCase(elementName))
+                       {
+                               return elements[i];
+                       }
+                       else
+                       {
+                               Element rtnElement = locateChildElementInDocument(elements[i], elementName);
+                               if(rtnElement != null)
+                               {
+                                       return rtnElement;
+                               }
+                       }
+               }
+               return (Element)null;
+       }
+
+       /** Traverses nodes for the locating method
+         */
+       private Element locateChildElementInDocument(Element element, String elementName)
+       {
+               for(int i = 0; i < element.getElementCount(); i++)
+               {
+                       if(element.getElement(i).getName().equalsIgnoreCase(elementName))
+                       {
+                               return element.getElement(i);
+                       }
+               }
+               return (Element)null;
+       }
+
+       /** Convenience method for obtaining the WYSIWYG JTextPane
+         */
+       public JTextPane getTextPane()
+       {
+               return jtpMain;
+       }
+
+       /** Convenience method for obtaining the Source JTextPane
+         */
+       public JTextPane getSourcePane()
+       {
+               return jtpSource;
+       }
+
+       /** Convenience method for obtaining the application as a Frame
+         */
+       public Frame getFrame()
+       {
+               return frameHandler;
+       }
+
+       /** Convenience method for setting the parent Frame
+         */
+       public void setFrame(Frame parentFrame)
+       {
+               frameHandler = parentFrame;
+       }
+
+       /** Convenience method for obtaining the pre-generated menu bar
+         */
+       public JMenuBar getMenuBar()
+       {
+               return jMenuBar;
+       }
+
+       /** Convenience method for obtaining a custom menu bar
+         */
+       public JMenuBar getCustomMenuBar(Vector vcMenus)
+       {
+               jMenuBar = new JMenuBar();
+               for(int i = 0; i < vcMenus.size(); i++)
+               {
+                       String menuToAdd = ((String)(vcMenus.elementAt(i))).toLowerCase();
+                       if(htMenus.containsKey(menuToAdd))
+                       {
+                               jMenuBar.add((JMenu)(htMenus.get(menuToAdd)));
+                       }
+               }
+               return jMenuBar;
+       }
+
+       /** Convenience method for obtaining the pre-generated toolbar
+         */
+       public JToolBar getToolBar(boolean isShowing)
+       {
+               jcbmiViewToolbar.setState(isShowing);
+               return jToolBar;
+       }
+
+       /** Convenience method for obtaining the pre-generated toolbar
+         */
+       public JToolBar getCustomToolBar(Vector vcTools, boolean isShowing)
+       {
+               jcbmiViewToolbar.setState(isShowing);
+               jToolBar = new JToolBar(JToolBar.HORIZONTAL);
+               jToolBar.setFloatable(false);
+               for(int i = 0; i < vcTools.size(); i++)
+               {
+                       String toolToAdd = ((String)(vcTools.elementAt(i))).toLowerCase();
+                       if(toolToAdd.equals(KEY_TOOL_SEP))
+                       {
+                               jToolBar.add(new JToolBar.Separator());
+                       }
+                       else if(htTools.containsKey(toolToAdd))
+                       {
+                               if(htTools.get(toolToAdd) instanceof JButtonNoFocus)
+                               {
+                                       jToolBar.add((JButtonNoFocus)(htTools.get(toolToAdd)));
+                               }
+                               else if(htTools.get(toolToAdd) instanceof JToggleButtonNoFocus)
+                               {
+                                       jToolBar.add((JToggleButtonNoFocus)(htTools.get(toolToAdd)));
+                               }
+                               else if(htTools.get(toolToAdd) instanceof JComboBoxNoFocus)
+                               {
+                                       jToolBar.add((JComboBoxNoFocus)(htTools.get(toolToAdd)));
+                               }
+                               else
+                               {
+                                       jToolBar.add((JComponent)(htTools.get(toolToAdd)));
+                               }
+                       }
+               }
+               return jToolBar;
+       }
+
+       /** Convenience method for obtaining the current file handle
+         */
+       public File getCurrentFile()
+       {
+               return currentFile;
+       }
+
+       /** Convenience method for obtaining the application name
+         */
+       public String getAppName()
+       {
+               return appName;
+       }
+
+       /** Convenience method for obtaining the document text
+         */
+       public String getDocumentText()
+       {
+               return jtpMain.getText();
+       }
+
+       /** Convenience method for obtaining the document text
+         * contained within a tag pair
+         */
+       public String getDocumentSubText(String tagBlock)
+       {
+               return getSubText(tagBlock);
+       }
+
+       /** Method for extracting the text within a tag
+         */
+       private String getSubText(String containingTag)
+       {
+               jtpSource.setText(jtpMain.getText());
+               String docTextCase = jtpSource.getText().toLowerCase();
+               int tagStart       = docTextCase.indexOf("<" + containingTag.toLowerCase());
+               int tagStartClose  = docTextCase.indexOf(">", tagStart) + 1;
+               String closeTag    = "</" + containingTag.toLowerCase() + ">";
+               int tagEndOpen     = docTextCase.indexOf(closeTag);
+               if(tagStartClose < 0) { tagStartClose = 0; }
+               if(tagEndOpen < 0 || tagEndOpen > docTextCase.length()) { tagEndOpen = docTextCase.length(); }
+               return jtpSource.getText().substring(tagStartClose, tagEndOpen);
+       }
+
+       /** Convenience method for obtaining the document text
+               * contained within the BODY tags (a common request)
+         */
+       public String getDocumentBody()
+       {
+               return getSubText("body");
+       }
+
+       /** Convenience method for setting the document text
+         */
+       public void setDocumentText(String sText)
+       {
+               jtpMain.setText(sText);
+               ((HTMLEditorKit)(jtpMain.getEditorKit())).setDefaultCursor(new Cursor(Cursor.TEXT_CURSOR));
+               jtpSource.setText(jtpMain.getText());
+               ((HTMLEditorKit)(jtpSource.getEditorKit())).setDefaultCursor(new Cursor(Cursor.TEXT_CURSOR));
+       }
+
+       /** Convenience method for obtaining the document text
+         */
+       private void updateTitle()
+       {
+               frameHandler.setTitle(appName + (currentFile == null ? "" : " - " + currentFile.getName()));
+       }
+
+       /** Convenience method for clearing out the UndoManager
+         */
+       public void purgeUndos()
+       {
+               if(undoMngr != null)
+               {
+                       undoMngr.discardAllEdits();
+                       undoAction.updateUndoState();
+                       redoAction.updateRedoState();
+               }
+       }
+
+       /** Convenience method for refreshing and displaying changes
+         */
+       public void refreshOnUpdate()
+       {
+               jtpMain.setText(jtpMain.getText());
+               jtpSource.setText(jtpMain.getText());
+               purgeUndos();
+               this.repaint();
+       }
+
+       /** Convenience method for deallocating the app resources
+         */
+       public void dispose()
+       {
+               frameHandler.dispose();
+               spellCheck.dispose();
+               spellCheck = null;
+               spellDialog = null;
+               System.exit(0);
+       }
+
+       /** Convenience method for fetching icon images from jar file
+         */
+       private ImageIcon getEkitIcon(String iconName)
+       {
+               return new ImageIcon(Toolkit.getDefaultToolkit().getImage(getClass().getResource("icons/" + iconName + "HK.gif")));
+       }
+
+       /** Convenience method for outputting exceptions
+         */
+       private void logException(String internalMessage, Exception e)
+       {
+               System.err.println(internalMessage);
+               e.printStackTrace(System.err);
+       }
+
+       /** Convenience method for toggling source window visibility
+         */
+       private void toggleSourceWindow()
+       {
+               if(!(jspSource.isShowing()))
+               {
+                       jtpSource.setText(jtpMain.getText());
+                       jspltDisplay.setRightComponent(jspSource);
+                       if(exclusiveEdit)
+                       {
+                               jspltDisplay.setDividerLocation(0);
+                               jspltDisplay.setEnabled(false);
+                       }
+                       else
+                       {
+                               jspltDisplay.setDividerLocation(iSplitPos);
+                               jspltDisplay.setEnabled(true);
+                       }
+               }
+               else
+               {
+                       jtpMain.setText(jtpSource.getText());
+                       iSplitPos = jspltDisplay.getDividerLocation();
+                       jspltDisplay.remove(jspSource);
+                       jtpMain.requestFocus();
+               }
+               this.validate();
+               jcbmiViewSource.setSelected(jspSource.isShowing());
+               jtbtnViewSource.setSelected(jspSource.isShowing());
+       }
+
+       /** Searches the specified element for CLASS attribute setting
+         */
+       private String findStyle(Element element)
+       {
+               AttributeSet as = element.getAttributes();
+               if(as == null)
+               {
+                       return null;
+               }
+               Object val = as.getAttribute(HTML.Attribute.CLASS);
+               if(val != null && (val instanceof String))
+               {
+                       return (String)val;
+               }
+               for(Enumeration e = as.getAttributeNames(); e.hasMoreElements();)
+               {
+                       Object key = e.nextElement();
+                       if(key instanceof HTML.Tag)
+                       {
+                               AttributeSet eas = (AttributeSet)(as.getAttribute(key));
+                               if(eas != null)
+                               {
+                                       val = eas.getAttribute(HTML.Attribute.CLASS);
+                                       if(val != null)
+                                       {
+                                               return (String)val;
+                                       }
+                               }
+                       }
+
+               }
+               return null;
+       }
+
+       /** Handles caret tracking and related events, such as displaying the current style
+         * of the text under the caret
+         */
+       private void handleCaretPositionChange(CaretEvent ce)
+       {
+               int caretPos = ce.getDot();
+               Element element = htmlDoc.getCharacterElement(caretPos);
+/*
+---- TAG EXPLICATOR CODE -------------------------------------------
+               javax.swing.text.ElementIterator ei = new javax.swing.text.ElementIterator(htmlDoc);
+               Element ele;
+               while((ele = ei.next()) != null)
+               {
+                       System.out.println("ELEMENT : " + ele.getName());
+               }
+               System.out.println("ELEMENT:" + element.getName());
+               Element elementParent = element.getParentElement();
+               System.out.println("ATTRS:");
+               AttributeSet attribs = elementParent.getAttributes();
+               for(Enumeration eAttrs = attribs.getAttributeNames(); eAttrs.hasMoreElements();)
+               {
+                       System.out.println("  " + eAttrs.nextElement().toString());
+               }
+               while(elementParent != null && !elementParent.getName().equals("body"))
+               {
+                       String parentName = elementParent.getName();
+                       System.out.println("PARENT:" + parentName);
+                       System.out.println("ATTRS:");
+                       attribs = elementParent.getAttributes();
+                       for(Enumeration eAttr = attribs.getAttributeNames(); eAttr.hasMoreElements();)
+                       {
+                               System.out.println("  " + eAttr.nextElement().toString());
+                       }
+                       elementParent = elementParent.getParentElement();
+               }
+---- END -------------------------------------------
+*/
+               if(element == null)
+               {
+                       return;
+               }
+               String style = null;
+               Vector vcStyles = new Vector();
+               while(element != null)
+               {
+                       if(style == null)
+                       {
+                               style = findStyle(element);
+                       }
+                       vcStyles.add(element);
+                       element = element.getParentElement();
+               }
+               int stylefound = -1;
+               if(style != null)
+               {
+                       for(int i = 0; i < jcmbStyleSelector.getItemCount(); i++)
+                       {
+                               String in = (String)(jcmbStyleSelector.getItemAt(i));
+                               if(in.equalsIgnoreCase(style))
+                               {
+                                       stylefound = i;
+                                       break;
+                               }
+                       }
+               }
+               if(stylefound > -1)
+               {
+                       Action ac = jcmbStyleSelector.getAction();
+                       ac.setEnabled(false);
+                       jcmbStyleSelector.setSelectedIndex(stylefound);
+                       ac.setEnabled(true);
+               }
+               else
+               {
+                       jcmbStyleSelector.setSelectedIndex(0);
+               }
+       }
+
+       /** Server-side image handling methods
+         */
+       protected void setServletURL(String url)
+       {
+               ServletURL = url;
+       }
+
+       protected void setImageDir(String sysDir)
+       {
+               ImageDir = sysDir;
+       }
+
+       public void setTreePilotSystemID(String theSystem)
+       {
+               TreePilotSystemID = theSystem;
+       }
+
+       /** Utility methods
+         */
+       public ExtendedHTMLDocument getExtendedHtmlDoc()
+       {
+               return (ExtendedHTMLDocument)htmlDoc;
+       }
+
+       public int getCaretPosition()
+       {
+               return jtpMain.getCaretPosition();
+       }
+
+       public void setCaretPosition(int newPositon)
+       {
+               boolean end = true;
+               do
+               {
+                       end = true;
+                       try
+                       {
+                               jtpMain.setCaretPosition(newPositon);
+                       }
+                       catch (IllegalArgumentException iae)
+                       {
+                               end = false;
+                               newPositon--;
+                       }
+               } while(!end && newPositon >= 0);
+       }
+
+/* Inner Classes --------------------------------------------- */
+
+       /** Class for implementing Undo as an autonomous action
+         */
+       class UndoAction extends AbstractAction
+       {
+               public UndoAction()
+               {
+                       super(Translatrix.getTranslationString("Undo"));
+                       setEnabled(false);
+               }
+
+               public void actionPerformed(ActionEvent e)
+               {
+                       try
+                       {
+                               undoMngr.undo();
+                       }
+                       catch(CannotUndoException ex)
+                       {
+                               ex.printStackTrace();
+                       }
+                       updateUndoState();
+                       redoAction.updateRedoState();
+               }
+
+               protected void updateUndoState()
+               {
+                       if(undoMngr.canUndo())
+                       {
+                               setEnabled(true);
+                               putValue(Action.NAME, undoMngr.getUndoPresentationName());
+                       }
+                       else
+                       {
+                               setEnabled(false);
+                               putValue(Action.NAME, Translatrix.getTranslationString("Undo"));
+                       }
+               }
+       }
+
+       /** Class for implementing Redo as an autonomous action
+         */
+       class RedoAction extends AbstractAction
+       {
+               public RedoAction()
+               {
+                       super(Translatrix.getTranslationString("Redo"));
+                       setEnabled(false);
+               }
+
+               public void actionPerformed(ActionEvent e)
+               {
+                       try
+                       {
+                               undoMngr.redo();
+                       }
+                       catch(CannotUndoException ex)
+                       {
+                               ex.printStackTrace();
+                       }
+                       updateRedoState();
+                       undoAction.updateUndoState();
+               }
+
+               protected void updateRedoState()
+               {
+                       if(undoMngr.canRedo())
+                       {
+                               setEnabled(true);
+                               putValue(Action.NAME, undoMngr.getRedoPresentationName());
+                       }
+                       else
+                       {
+                               setEnabled(false);
+                               putValue(Action.NAME, Translatrix.getTranslationString("Redo"));
+                       }
+               }
+       }
+
+       /** Class for implementing the Undo listener to handle the Undo and Redo actions
+         */
+       class CustomUndoableEditListener implements UndoableEditListener
+       {
+               public void undoableEditHappened(UndoableEditEvent uee)
+               {
+                       undoMngr.addEdit(uee.getEdit());
+                       undoAction.updateUndoState();
+                       redoAction.updateRedoState();
+               }
+       }
+
+}