[pLog-svn] r2349 - in plog/trunk/js: . editor xinha xinha/examples xinha/images xinha/lang xinha/plugins xinha/plugins/ContextMenu xinha/plugins/ContextMenu/lang xinha/plugins/EnterParagraphs xinha/plugins/FullScreen xinha/plugins/FullScreen/lang xinha/popups xinha/skins xinha/skins/blue-look xinha/skins/blue-metallic xinha/skins/green-look xinha/skins/inditreuse xinha/skins/titan xinha/skins/xp-blue xinha/skins/xp-green

mark at devel.plogworld.net mark at devel.plogworld.net
Wed Jul 20 05:55:48 GMT 2005


Author: mark
Date: 2005-07-20 05:55:47 +0000 (Wed, 20 Jul 2005)
New Revision: 2349

Added:
   plog/trunk/js/xinha/
   plog/trunk/js/xinha/dialog.js
   plog/trunk/js/xinha/examples/
   plog/trunk/js/xinha/examples/custom.css
   plog/trunk/js/xinha/examples/dynamic.css
   plog/trunk/js/xinha/examples/full_example-body.html
   plog/trunk/js/xinha/examples/full_example-menu.html
   plog/trunk/js/xinha/examples/full_example.css
   plog/trunk/js/xinha/examples/full_example.html
   plog/trunk/js/xinha/examples/full_example.js
   plog/trunk/js/xinha/examples/stylist.css
   plog/trunk/js/xinha/examples/testbed.html
   plog/trunk/js/xinha/htmlarea-plog-resourcelist.js
   plog/trunk/js/xinha/htmlarea-plog.js
   plog/trunk/js/xinha/htmlarea.css
   plog/trunk/js/xinha/htmlarea.js
   plog/trunk/js/xinha/images/
   plog/trunk/js/xinha/images/ed_about.gif
   plog/trunk/js/xinha/images/ed_align.gif
   plog/trunk/js/xinha/images/ed_align_center.gif
   plog/trunk/js/xinha/images/ed_align_justify.gif
   plog/trunk/js/xinha/images/ed_align_left.gif
   plog/trunk/js/xinha/images/ed_align_right.gif
   plog/trunk/js/xinha/images/ed_blank.gif
   plog/trunk/js/xinha/images/ed_buttons_main.gif
   plog/trunk/js/xinha/images/ed_charmap.gif
   plog/trunk/js/xinha/images/ed_clearfonts.gif
   plog/trunk/js/xinha/images/ed_color_bg.gif
   plog/trunk/js/xinha/images/ed_color_fg.gif
   plog/trunk/js/xinha/images/ed_copy.gif
   plog/trunk/js/xinha/images/ed_custom.gif
   plog/trunk/js/xinha/images/ed_cut.gif
   plog/trunk/js/xinha/images/ed_delete.gif
   plog/trunk/js/xinha/images/ed_format_bold.gif
   plog/trunk/js/xinha/images/ed_format_italic.gif
   plog/trunk/js/xinha/images/ed_format_strike.gif
   plog/trunk/js/xinha/images/ed_format_sub.gif
   plog/trunk/js/xinha/images/ed_format_sup.gif
   plog/trunk/js/xinha/images/ed_format_underline.gif
   plog/trunk/js/xinha/images/ed_help.gif
   plog/trunk/js/xinha/images/ed_hr.gif
   plog/trunk/js/xinha/images/ed_html.gif
   plog/trunk/js/xinha/images/ed_image.gif
   plog/trunk/js/xinha/images/ed_indent_less.gif
   plog/trunk/js/xinha/images/ed_indent_more.gif
   plog/trunk/js/xinha/images/ed_killword.gif
   plog/trunk/js/xinha/images/ed_left_to_right.gif
   plog/trunk/js/xinha/images/ed_link.gif
   plog/trunk/js/xinha/images/ed_list_bullet.gif
   plog/trunk/js/xinha/images/ed_list_num.gif
   plog/trunk/js/xinha/images/ed_overwrite.gif
   plog/trunk/js/xinha/images/ed_paste.gif
   plog/trunk/js/xinha/images/ed_print.gif
   plog/trunk/js/xinha/images/ed_redo.gif
   plog/trunk/js/xinha/images/ed_resource.gif
   plog/trunk/js/xinha/images/ed_right_to_left.gif
   plog/trunk/js/xinha/images/ed_rmformat.gif
   plog/trunk/js/xinha/images/ed_save.gif
   plog/trunk/js/xinha/images/ed_save.png
   plog/trunk/js/xinha/images/ed_saveas.gif
   plog/trunk/js/xinha/images/ed_selectall.gif
   plog/trunk/js/xinha/images/ed_show_border.gif
   plog/trunk/js/xinha/images/ed_splitblock.gif
   plog/trunk/js/xinha/images/ed_splitcel.gif
   plog/trunk/js/xinha/images/ed_undo.gif
   plog/trunk/js/xinha/images/ed_word_cleaner.gif
   plog/trunk/js/xinha/images/fullscreen_maximize.gif
   plog/trunk/js/xinha/images/fullscreen_minimize.gif
   plog/trunk/js/xinha/images/insert_table.gif
   plog/trunk/js/xinha/images/insertfilelink.gif
   plog/trunk/js/xinha/images/insertmacro.png
   plog/trunk/js/xinha/images/tidy.gif
   plog/trunk/js/xinha/images/toggle_borders.gif
   plog/trunk/js/xinha/inline-dialog.js
   plog/trunk/js/xinha/lang/
   plog/trunk/js/xinha/lang/b5.js
   plog/trunk/js/xinha/lang/ch.js
   plog/trunk/js/xinha/lang/cz.js
   plog/trunk/js/xinha/lang/da.js
   plog/trunk/js/xinha/lang/de.js
   plog/trunk/js/xinha/lang/ee.js
   plog/trunk/js/xinha/lang/el.js
   plog/trunk/js/xinha/lang/es.js
   plog/trunk/js/xinha/lang/fi.js
   plog/trunk/js/xinha/lang/fr.js
   plog/trunk/js/xinha/lang/gb.js
   plog/trunk/js/xinha/lang/he.js
   plog/trunk/js/xinha/lang/hu.js
   plog/trunk/js/xinha/lang/it.js
   plog/trunk/js/xinha/lang/ja.js
   plog/trunk/js/xinha/lang/lt.js
   plog/trunk/js/xinha/lang/lv.js
   plog/trunk/js/xinha/lang/nb.js
   plog/trunk/js/xinha/lang/nl.js
   plog/trunk/js/xinha/lang/no.js
   plog/trunk/js/xinha/lang/pl.js
   plog/trunk/js/xinha/lang/pt_br.js
   plog/trunk/js/xinha/lang/ro.js
   plog/trunk/js/xinha/lang/ru.js
   plog/trunk/js/xinha/lang/se.js
   plog/trunk/js/xinha/lang/si.js
   plog/trunk/js/xinha/lang/vn.js
   plog/trunk/js/xinha/license.txt
   plog/trunk/js/xinha/panel-dialog.js
   plog/trunk/js/xinha/plugins/
   plog/trunk/js/xinha/plugins/ContextMenu/
   plog/trunk/js/xinha/plugins/ContextMenu/1.pl
   plog/trunk/js/xinha/plugins/ContextMenu/context-menu.js
   plog/trunk/js/xinha/plugins/ContextMenu/lang/
   plog/trunk/js/xinha/plugins/ContextMenu/lang/de.js
   plog/trunk/js/xinha/plugins/ContextMenu/lang/el.js
   plog/trunk/js/xinha/plugins/ContextMenu/lang/fr.js
   plog/trunk/js/xinha/plugins/ContextMenu/lang/he.js
   plog/trunk/js/xinha/plugins/ContextMenu/lang/nl.js
   plog/trunk/js/xinha/plugins/ContextMenu/lang/no.js
   plog/trunk/js/xinha/plugins/ContextMenu/menu.css
   plog/trunk/js/xinha/plugins/EnterParagraphs/
   plog/trunk/js/xinha/plugins/EnterParagraphs/enter-paragraphs.js
   plog/trunk/js/xinha/plugins/EnterParagraphs/lang/
   plog/trunk/js/xinha/plugins/FullScreen/
   plog/trunk/js/xinha/plugins/FullScreen/full-screen.js
   plog/trunk/js/xinha/plugins/FullScreen/lang/
   plog/trunk/js/xinha/plugins/FullScreen/lang/de.js
   plog/trunk/js/xinha/plugins/FullScreen/lang/fr.js
   plog/trunk/js/xinha/plugins/FullScreen/lang/no.js
   plog/trunk/js/xinha/popupdiv.js
   plog/trunk/js/xinha/popups/
   plog/trunk/js/xinha/popups/about.html
   plog/trunk/js/xinha/popups/blank.html
   plog/trunk/js/xinha/popups/color_picker.js
   plog/trunk/js/xinha/popups/custom2.html
   plog/trunk/js/xinha/popups/editor_help.html
   plog/trunk/js/xinha/popups/insert_image.html
   plog/trunk/js/xinha/popups/insert_table.html
   plog/trunk/js/xinha/popups/link.html
   plog/trunk/js/xinha/popups/old_insert_image.html
   plog/trunk/js/xinha/popups/popup.css
   plog/trunk/js/xinha/popups/popup.js
   plog/trunk/js/xinha/popups/select_color.html
   plog/trunk/js/xinha/popupwin.js
   plog/trunk/js/xinha/skins/
   plog/trunk/js/xinha/skins/blue-look/
   plog/trunk/js/xinha/skins/blue-look/button-background.png
   plog/trunk/js/xinha/skins/blue-look/separator.gif
   plog/trunk/js/xinha/skins/blue-look/skin.css
   plog/trunk/js/xinha/skins/blue-metallic/
   plog/trunk/js/xinha/skins/blue-metallic/button-background.png
   plog/trunk/js/xinha/skins/blue-metallic/separator.gif
   plog/trunk/js/xinha/skins/blue-metallic/skin.css
   plog/trunk/js/xinha/skins/green-look/
   plog/trunk/js/xinha/skins/green-look/button-background.gif
   plog/trunk/js/xinha/skins/green-look/button-background.png
   plog/trunk/js/xinha/skins/green-look/separator.gif
   plog/trunk/js/xinha/skins/green-look/skin.css
   plog/trunk/js/xinha/skins/inditreuse/
   plog/trunk/js/xinha/skins/inditreuse/README
   plog/trunk/js/xinha/skins/inditreuse/back.png
   plog/trunk/js/xinha/skins/inditreuse/button-background.png
   plog/trunk/js/xinha/skins/inditreuse/hover.png
   plog/trunk/js/xinha/skins/inditreuse/selected.png
   plog/trunk/js/xinha/skins/inditreuse/separator.png
   plog/trunk/js/xinha/skins/inditreuse/skin.css
   plog/trunk/js/xinha/skins/titan/
   plog/trunk/js/xinha/skins/titan/README
   plog/trunk/js/xinha/skins/titan/back.png
   plog/trunk/js/xinha/skins/titan/button-background.png
   plog/trunk/js/xinha/skins/titan/hover.png
   plog/trunk/js/xinha/skins/titan/selected.png
   plog/trunk/js/xinha/skins/titan/separator.png
   plog/trunk/js/xinha/skins/titan/skin.css
   plog/trunk/js/xinha/skins/xp-blue/
   plog/trunk/js/xinha/skins/xp-blue/back.png
   plog/trunk/js/xinha/skins/xp-blue/button-background.png
   plog/trunk/js/xinha/skins/xp-blue/hover.png
   plog/trunk/js/xinha/skins/xp-blue/selected.png
   plog/trunk/js/xinha/skins/xp-blue/separator.png
   plog/trunk/js/xinha/skins/xp-blue/skin.css
   plog/trunk/js/xinha/skins/xp-green/
   plog/trunk/js/xinha/skins/xp-green/back.png
   plog/trunk/js/xinha/skins/xp-green/button-background.png
   plog/trunk/js/xinha/skins/xp-green/hover.png
   plog/trunk/js/xinha/skins/xp-green/selected.png
   plog/trunk/js/xinha/skins/xp-green/separator.png
   plog/trunk/js/xinha/skins/xp-green/skin.css
Removed:
   plog/trunk/js/htmlarea/
Modified:
   plog/trunk/js/editor/plogeditor.js
Log:
Replace Htmlarea with Xinha.

Modified: plog/trunk/js/editor/plogeditor.js
===================================================================
--- plog/trunk/js/editor/plogeditor.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/editor/plogeditor.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -51,7 +51,7 @@
 /**
  * please change this if your icons are somewhere else!
  */
-var baseImageFolder = 'js/htmlarea/images/';
+var baseImageFolder = 'js/xinha/images/';
 
 /**
  * represents a button from our toolbar

Added: plog/trunk/js/xinha/dialog.js
===================================================================
--- plog/trunk/js/xinha/dialog.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/dialog.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,76 @@
+// htmlArea v3.0 - Copyright (c) 2003-2004 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003-2004
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: dialog.js 183 2005-05-20 06:11:44Z gogo $
+
+// Though "Dialog" looks like an object, it isn't really an object.  Instead
+// it's just namespace for protecting global symbols.
+
+function Dialog(url, action, init) {
+	if (typeof init == "undefined") {
+		init = window;	// pass this window object by default
+	}
+	Dialog._geckoOpenModal(url, action, init);
+};
+
+Dialog._parentEvent = function(ev) {
+	setTimeout( function() { if (Dialog._modal && !Dialog._modal.closed) { Dialog._modal.focus() } }, 50);
+	if (Dialog._modal && !Dialog._modal.closed) {
+		HTMLArea._stopEvent(ev);
+	}
+};
+
+
+// should be a function, the return handler of the currently opened dialog.
+Dialog._return = null;
+
+// constant, the currently opened dialog
+Dialog._modal = null;
+
+// the dialog will read it's args from this variable
+Dialog._arguments = null;
+
+Dialog._geckoOpenModal = function(url, action, init) {
+	var dlg = window.open(url, "hadialog",
+			      "toolbar=no,menubar=no,personalbar=no,width=10,height=10," +
+			      "scrollbars=no,resizable=yes,modal=yes,dependable=yes");
+	Dialog._modal = dlg;
+	Dialog._arguments = init;
+
+	// capture some window's events
+	function capwin(w) {
+		HTMLArea._addEvent(w, "click", Dialog._parentEvent);
+		HTMLArea._addEvent(w, "mousedown", Dialog._parentEvent);
+		HTMLArea._addEvent(w, "focus", Dialog._parentEvent);
+	};
+	// release the captured events
+	function relwin(w) {
+		HTMLArea._removeEvent(w, "click", Dialog._parentEvent);
+		HTMLArea._removeEvent(w, "mousedown", Dialog._parentEvent);
+		HTMLArea._removeEvent(w, "focus", Dialog._parentEvent);
+	};
+	capwin(window);
+	// capture other frames, note the exception trapping, this is because
+  // we are not permitted to add events to frames outside of the current
+  // window's domain.
+	for (var i = 0; i < window.frames.length; i++) {try { capwin(window.frames[i]); } catch(e) { } };
+	// make up a function to be called when the Dialog ends.
+	Dialog._return = function (val) {
+		if (val && action) {
+			action(val);
+		}
+		relwin(window);
+		// capture other frames
+		for (var i = 0; i < window.frames.length; i++) { try { relwin(window.frames[i]); } catch(e) { } };
+		Dialog._modal = null;
+	};
+  Dialog._modal.focus();
+};

Added: plog/trunk/js/xinha/examples/custom.css
===================================================================
--- plog/trunk/js/xinha/examples/custom.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/custom.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,40 @@
+  /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  CSS plugin example CSS file.  This file is used by full_example.js
+    --  when the CSS plugin is included in an auto-generated example.
+    --  @TODO Make this CSS more useful.
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/custom.css $
+    --  $LastChangedDate: 2005-02-19 12:10:03 +0800 (Sat, 19 Feb 2005) $
+    --  $LastChangedRevision: 14 $
+    --  $LastChangedBy: gogo $
+    --------------------------------------------------------------------------*/
+
+body { background-color: #234; color: #dd8; font-family: tahoma; font-size: 12px; }
+
+a:link, a:visited { color: #8cf; }
+a:hover { color: #ff8; }
+
+h1 { background-color: #456; color: #ff8; padding: 2px 5px; border: 1px solid; border-color: #678 #012 #012 #678; }
+
+/* syntax highlighting (used by the first combo defined for the CSS plugin) */
+
+pre { margin: 0px 1em; padding: 5px 1em; background-color: #000; border: 1px dotted #02d; border-left: 2px solid #04f; }
+.code { color: #f5deb3; }
+.string { color: #00ffff; }
+.comment { color: #8fbc8f; }
+.variable-name { color: #fa8072; }
+.type { color: #90ee90; font-weight: bold; }
+.reference { color: #ee82ee; }
+.preprocessor { color: #faf; }
+.keyword { color: #ffffff; font-weight: bold; }
+.function-name { color: #ace; }
+.html-tag { font-weight: bold; }
+.html-helper-italic { font-style: italic; }
+.warning { color: #ffa500; font-weight: bold; }
+.html-helper-bold { font-weight: bold; }
+
+/* info combo */
+
+.quote { font-style: italic; color: #ee9; }
+.highlight { background-color: yellow; color: #000; }
+.deprecated { text-decoration: line-through; color: #aaa; }

Added: plog/trunk/js/xinha/examples/dynamic.css
===================================================================
--- plog/trunk/js/xinha/examples/dynamic.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/dynamic.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,56 @@
+  /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  DynamicCSS plugin example CSS file.  Used by full_example.js
+    --  when the DynamicCSS plugin is included in an auto-generated example.
+    --  @TODO Make this CSS more useful.
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/dynamic.css $
+    --  $LastChangedDate: 2005-02-19 12:10:03 +0800 (Sat, 19 Feb 2005) $
+    --  $LastChangedRevision: 14 $
+    --  $LastChangedBy: gogo $
+    --------------------------------------------------------------------------*/
+
+p {
+  FONT-FAMILY: Arial, Helvetica;
+  FONT-SIZE: 9pt;
+  FONT-WEIGHT: normal;
+  COLOR: #000000;
+}
+
+p.p1 {
+  FONT-FAMILY: Arial, Helvetica;
+  FONT-SIZE: 11pt;
+  FONT-WEIGHT: normal;
+  COLOR: #000000;
+}
+
+p.p2 {
+  FONT-FAMILY: Arial, Helvetica;
+  FONT-SIZE: 13pt;
+  FONT-WEIGHT: normal;
+  COLOR: #000000;
+}
+
+div {
+  FONT-FAMILY: Arial, Helvetica;
+  FONT-SIZE: 9pt;
+  FONT-WEIGHT: bold;
+  COLOR: #000000;
+}
+
+div.div1 {
+  FONT-FAMILY: Arial, Helvetica;
+  FONT-SIZE: 11pt;
+  FONT-WEIGHT: bold;
+  COLOR: #000000;
+}
+
+div.div2 {
+  FONT-FAMILY: Arial, Helvetica;
+  FONT-SIZE: 13pt;
+  FONT-WEIGHT: bold;
+  COLOR: #000000;
+}
+
+.quote { font-style: italic; color: #ee9; }
+.highlight { background-color: yellow; color: #000; }
+.deprecated { text-decoration: line-through; color: #aaa; }

Added: plog/trunk/js/xinha/examples/full_example-body.html
===================================================================
--- plog/trunk/js/xinha/examples/full_example-body.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/full_example-body.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,185 @@
+<!DOCTYPE BHTML PUBLIC "-//BC//DTD BHTML 3.2 Final//EN">
+<html>
+<head>
+
+  <!--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  Xinha example usage.  This file shows how a developer might make use of
+    --  Xinha, it forms the primary example file for the entire Xinha project.
+    --  This file can be copied and used as a template for development by the
+    --  end developer who should simply removed the area indicated at the bottom
+    --  of the file to remove the auto-example-generating code and allow for the
+    --  use of the file as a boilerplate.
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/full_example-body.html $
+    --  $LastChangedDate: 2005-07-19 14:23:58 +0800 (Tue, 19 Jul 2005) $
+    --  $LastChangedRevision: 277 $
+    --  $LastChangedBy: gogo $
+    --------------------------------------------------------------------------->
+
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>Example of Xinha</title>
+  <link rel="stylesheet" href="full_example.css" />
+
+  <script type="text/javascript">
+    // You must set _editor_url to the URL (including trailing slash) where
+    // where xinha is installed, it's highly recommended to use an absolute URL
+    //  eg: _editor_url = "/path/to/xinha/";
+    // You may try a relative URL if you wish]
+    //  eg: _editor_url = "../";
+    // in this example we do a little regular expression to find the absolute path.
+    _editor_url  = document.location.href.replace(/examples\/full_example-body\.html.*/, '')
+    _editor_lang = "en";      // And the language we need to use in the editor.
+  </script>
+
+  <!-- Load up the actual editor core -->
+  <script type="text/javascript" src="../htmlarea.js"></script>
+
+  <script type="text/javascript">
+    xinha_editors = null;
+    xinha_init    = null;
+    xinha_config  = null;
+    xinha_plugins = null;
+
+    // This contains the names of textareas we will make into Xinha editors
+    xinha_init = xinha_init ? xinha_init : function()
+    {
+      /** STEP 1 ***************************************************************
+       * First, what are the plugins you will be using in the editors on this
+       * page.  List all the plugins you will need, even if not all the editors
+       * will use all the plugins.
+       ************************************************************************/
+
+      xinha_plugins = xinha_plugins ? xinha_plugins :
+      [
+       'CharacterMap',
+       'ContextMenu',
+       'FullScreen',
+       'ListType',
+       'SpellChecker',
+       'Stylist',
+       'SuperClean',
+       'TableOperations'
+      ];
+
+             // THIS BIT OF JAVASCRIPT LOADS THE PLUGINS, NO TOUCHING  :)
+             if(!HTMLArea.loadPlugins(xinha_plugins, xinha_init)) return;
+
+      /** STEP 2 ***************************************************************
+       * Now, what are the names of the textareas you will be turning into
+       * editors?
+       ************************************************************************/
+
+      xinha_editors = xinha_editors ? xinha_editors :
+      [
+        'myTextArea',
+        'anotherOne'
+      ];
+
+      /** STEP 3 ***************************************************************
+       * We create a default configuration to be used by all the editors.
+       * If you wish to configure some of the editors differently this will be
+       * done in step 5.
+       *
+       * If you want to modify the default config you might do something like this.
+       *
+       *   xinha_config = new HTMLArea.Config();
+       *   xinha_config.width  = '640px';
+       *   xinha_config.height = '420px';
+       *
+       *************************************************************************/
+
+       xinha_config = xinha_config ? xinha_config() : new HTMLArea.Config();
+
+      /** STEP 4 ***************************************************************
+       * We first create editors for the textareas.
+       *
+       * You can do this in two ways, either
+       *
+       *   xinha_editors   = HTMLArea.makeEditors(xinha_editors, xinha_config, xinha_plugins);
+       *
+       * if you want all the editor objects to use the same set of plugins, OR;
+       *
+       *   xinha_editors = HTMLArea.makeEditors(xinha_editors, xinha_config);
+       *   xinha_editors['myTextArea'].registerPlugins(['Stylist','FullScreen']);
+       *   xinha_editors['anotherOne'].registerPlugins(['CSS','SuperClean']);
+       *
+       * if you want to use a different set of plugins for one or more of the
+       * editors.
+       ************************************************************************/
+
+      xinha_editors   = HTMLArea.makeEditors(xinha_editors, xinha_config, xinha_plugins);
+
+      /** STEP 5 ***************************************************************
+       * If you want to change the configuration variables of any of the
+       * editors,  this is the place to do that, for example you might want to
+       * change the width and height of one of the editors, like this...
+       *
+       *   xinha_editors.myTextArea.config.width  = '640px';
+       *   xinha_editors.myTextArea.config.height = '480px';
+       *
+       ************************************************************************/
+
+
+      /** STEP 6 ***************************************************************
+       * Finally we "start" the editors, this turns the textareas into
+       * Xinha editors.
+       ************************************************************************/
+
+      HTMLArea.startEditors(xinha_editors);
+    }
+
+    window.onload = xinha_init;
+  </script>
+  <!--link type="text/css" rel="alternate stylesheet" title="blue-look" href="../skins/blue-look/skin.css" />
+  <link type="text/css" rel="alternate stylesheet" title="green-look" href="../skins/green-look/skin.css" />
+  <link type="text/css" rel="alternate stylesheet" title="xp-blue" href="../skins/xp-blue/skin.css" />
+  <link type="text/css" rel="alternate stylesheet" title="xp-green" href="../skins/xp-green/skin.css" />
+  <link type="text/css" rel="alternate stylesheet" title="inditreuse" href="../skins/inditreuse/skin.css" />
+  <link type="text/css" rel="alternate stylesheet" title="blue-metallic" href="../skins/blue-metallic/skin.css" /-->
+</head>
+
+<body>
+
+  <form id="editors_here">
+    <textarea id="myTextArea" name="myTextArea" rows="10" cols="80" style="width:100%"></textarea>
+    <textarea id="anotherOne" name="anotherOne" rows="10" cols="80" style="width:100%"></textarea>
+  </form>
+
+
+  <!----------------------------------------------------------------------------
+    -                            !! IMPORTANT !!
+    -  The html and javascript below is the code used to create the example page.
+    -  It renders a lot of the above unused because it pre-fills xinha_editors,
+    -  xinha_config and xinha_plugins for you, and creates new textareas in place
+    -  of the ones above. The items above are not used while the example is being
+    -  used!
+    -
+    -  If you are going to take the code in this file to form the basis of your
+    -  own, then leave out this marked area.
+    --------------------------------------------------------------------------->
+
+        <div id="lipsum" style="display:none">
+          <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+          Aliquam et tellus vitae justo varius placerat. Suspendisse iaculis
+          velit semper dolor. Donec gravida tincidunt mi. Curabitur tristique
+          ante elementum turpis. Aliquam nisl. Nulla posuere neque non
+          tellus. Morbi vel nibh. Cum sociis natoque penatibus et magnis dis
+          parturient montes, nascetur ridiculus mus. Nam nec wisi. In wisi.
+          Curabitur pharetra bibendum lectus.</p>
+
+          <ul>
+            <li> Phasellus et massa sed diam viverra semper.  </li>
+            <li> Mauris tincidunt felis in odio.              </li>
+            <li> Nulla placerat nunc ut pede.                 </li>
+            <li> Vivamus ultrices mi sit amet urna.           </li>
+            <li> Quisque sed augue quis nunc laoreet volutpat.</li>
+            <li> Nunc sit amet metus in tortor semper mattis. </li>
+          </ul>
+        </div>
+        <script src="full_example.js"></script>
+
+  <!--------------------------------------------------------------------------->
+
+
+</body>
+</html>

Added: plog/trunk/js/xinha/examples/full_example-menu.html
===================================================================
--- plog/trunk/js/xinha/examples/full_example-menu.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/full_example-menu.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,179 @@
+<html>
+<head>
+
+  <!--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  Xinha example menu.  This file is used by full_example.html within a
+    --  frame to provide a menu for generating example editors using
+    --  full_example-body.html, and full_example.js.
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/full_example-menu.html $
+    --  $LastChangedDate: 2005-06-22 21:09:42 +0800 (Wed, 22 Jun 2005) $
+    --  $LastChangedRevision: 238 $
+    --  $LastChangedBy: gocher $
+    --------------------------------------------------------------------------->
+
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>Example of Xinha</title>
+  <link rel="stylesheet" href="full_example.css" />
+  <style type="text/css">
+    form, p {margin: 0px; padding: 0px;}
+    label { display:block;}
+  </style>
+</head>
+
+<body>
+  <h1>Xinha Examples</h1>
+
+  <p>
+    Select from the options below and click the Show Example button.
+  </p>
+
+  <form action="full_example-body.html" target="body">
+    <fieldset>
+      <legend>Plugins</legend>
+      <label>
+        <input type="checkbox" name="plugins" value="CSS"  /> CSS
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="DynamicCSS"  /> DynamicCSS
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="FullPage"  /> FullPage
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="FullScreen" checked /> FullScreen
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="CharacterMap" checked /> CharacterMap
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="ContextMenu" checked /> ContextMenu
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="ListType" checked /> ListType
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="Stylist" checked /> Stylist
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="TableOperations" checked /> TableOperations
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="InsertAnchor" checked /> InsertAnchor
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="FindReplace" checked /> FindReplace
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="DoubleClick" /> DoubleClick
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="CharCounter" /> CharCounter
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="InsertWords" /> InsertWords
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="Abbreviation" /> Abbreviation
+      </label>
+
+      <label>
+	          <input type="checkbox" name="plugins" value="FormOperations" /> FormOperations
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="LangMarks" /> LangMarks
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="Equation" /> Equation
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="InsertSmiley" /> InsertSmiley
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="InsertMarquee" /> InsertMarquee
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="QuickTag" /> QuickTag
+      </label>
+      
+      <label>
+        <input type="checkbox" name="plugins" value="EditTag" /> EditTag
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="Forms" /> Forms
+      </label>
+
+      <label>
+        <input type="checkbox" name="plugins" value="Template" /> Template
+      </label>
+
+
+    </fieldset>
+
+    <fieldset>
+      <legend>PHP Plugins</legend>
+      <p>
+        <small>These plugins require PHP in order to run.</small>
+      </p>
+      <label>
+        <input type="checkbox" name="plugins" value="SuperClean"  /> SuperClean
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="SpellChecker" /> SpellChecker
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="HtmlTidy"  /> HtmlTidy
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="Linker"  /> Linker
+      </label>
+      <label>
+        <input type="checkbox" name="plugins" value="ImageManager"  /> ImageManager
+      </label>
+    </fieldset>
+
+    <fieldset>
+      <legend>Settings</legend>
+        <label>
+          Number of Editors: <input type="text" name="num" value="1" style="width:25;" maxlength="2"/>
+        </label>
+        <label>
+          Language: 
+          <select name="lang">
+          <option value="en">English</option>
+          <option value="de">German</option>
+          <option value="fr">French</option>
+          <option value="it">Italian</option>
+          </select>
+        </label>
+        <label>
+          Skin:
+          <select name="skin">
+          <option value="blue-look">blue-look</option>
+          <option value="green-look">green-look</option>
+          <option value="xp-blue">xp-blue</option>
+          <option value="xp-green">xp-green</option>
+          <option value="inditreuse">inditreuse</option>
+          <option value="blue-metallic">blue-metallic</option>
+          </select>
+        </label>
+    </fieldset>
+    <input type="submit" value="Show Example" />
+  </form>
+
+</body>
+</html>

Added: plog/trunk/js/xinha/examples/full_example.css
===================================================================
--- plog/trunk/js/xinha/examples/full_example.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/full_example.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,47 @@
+   /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  Xinha example CSS file.  This is ripped from Trac ;)
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/full_example.css $
+    --  $LastChangedDate: 2005-02-19 12:10:03 +0800 (Sat, 19 Feb 2005) $
+    --  $LastChangedRevision: 14 $
+    --  $LastChangedBy: gogo $
+    --------------------------------------------------------------------------*/
+
+ body {
+   background: #fff;
+   color: #000;
+   margin: 10px;
+  }
+  body, th, td {
+   font: normal 13px verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif;
+  }
+  h1, h2, h3, h4 {
+   font-family: arial,verdana,'Bitstream Vera Sans',helvetica,sans-serif;
+   font-weight: bold;
+   letter-spacing: -0.018em;
+  }
+  h1 { font-size: 21px; margin: .15em 1em 0 0 }
+  h2 { font-size: 16px; margin: 2em 0 .5em; }
+  h3 { font-size: 14px; margin: 1.5em 0 .5em; }
+  hr { border: none;  border-top: 1px solid #ccb; margin: 2em 0; }
+  address { font-style: normal }
+  img { border: none }
+
+  :link, :visited {
+   text-decoration: none;
+   color: #b00;
+   border-bottom: 1px dotted #bbb;
+  }
+  :link:hover, :visited:hover {
+   background-color: #eee;
+   color: #555;
+  }
+  h1 :link, h1 :visited ,h2 :link, h2 :visited, h3 :link, h3 :visited,
+  h4 :link, h4 :visited, h5 :link, h5 :visited, h6 :link, h6 :visited {
+   color: inherit;
+  }
+
+  .area_holder
+  {
+    margin:10px;
+  }
\ No newline at end of file

Added: plog/trunk/js/xinha/examples/full_example.html
===================================================================
--- plog/trunk/js/xinha/examples/full_example.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/full_example.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,16 @@
+<html>
+
+  <!--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  Xinha example frameset.
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/full_example.html $
+    --  $LastChangedDate: 2005-06-02 17:14:41 +0800 (Thu, 02 Jun 2005) $
+    --  $LastChangedRevision: 212 $
+    --  $LastChangedBy: gocher $
+    --------------------------------------------------------------------------->
+
+  <frameset cols="220,*">
+    <frame src="full_example-menu.html" name="menu">
+    <frame src="full_example-body.html" name="body">
+  </frameset>
+</html>

Added: plog/trunk/js/xinha/examples/full_example.js
===================================================================
--- plog/trunk/js/xinha/examples/full_example.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/full_example.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,132 @@
+
+  /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  Xinha example logic.  This javascript is used to auto-generate examples
+    --  as controlled by the options set in full_example-menu.html.  it's called
+    --  from full_example-body.html.
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/full_example.js $
+    --  $LastChangedDate: 2005-06-23 15:01:59 +0800 (Thu, 23 Jun 2005) $
+    --  $LastChangedRevision: 239 $
+    --  $LastChangedBy: gocher $
+    --------------------------------------------------------------------------*/
+
+  var num     = 1;
+  if(window.parent && window.parent != window)
+  {
+    var f = window.parent.menu.document.forms[0];
+    _editor_lang = f.lang.value;
+    _editor_skin = f.skin.value;
+    num = parseInt(f.num.value);
+    if(isNaN(num))
+    {
+      num = 1;
+      f.num.value = 1;
+    }
+    xinha_plugins = [ ];
+    for(var x = 0; x < f.plugins.length; x++)
+    {
+      if(f.plugins[x].checked) xinha_plugins.push(f.plugins[x].value);
+    }
+  }
+
+  xinha_editors = [ ]
+  for(var x = 0; x < num; x++)
+  {
+    var ta = 'myTextarea' + x;
+    xinha_editors.push(ta);
+  }
+
+  xinha_config = function()
+  {
+    var    config = new HTMLArea.Config();
+
+    if(typeof CSS != 'undefined')
+    {
+      config.pageStyle = "@import url(custom.css);";
+    }
+
+    if(typeof Stylist != 'undefined')
+    {
+      // We can load an external stylesheet like this - NOTE : YOU MUST GIVE AN ABSOLUTE URL
+      //  otherwise it won't work!
+      config.stylistLoadStylesheet(document.location.href.replace(/[^\/]*\.html/, 'stylist.css'));
+
+      // Or we can load styles directly
+      config.stylistLoadStyles('p.red_text { color:red }');
+
+      // If you want to provide "friendly" names you can do so like
+      // (you can do this for stylistLoadStylesheet as well)
+      config.stylistLoadStyles('p.pink_text { color:pink }', {'p.pink_text' : 'Pretty Pink'});
+    }
+
+    if(typeof DynamicCSS != 'undefined')
+    {
+      config.pageStyle = "@import url(dynamic.css);";
+    }
+
+    if(typeof InsertWords != 'undefined')
+    {
+      // Register the keyword/replacement list
+      var keywrds1 = new Object();
+      var keywrds2 = new Object();
+
+      keywrds1['-- Dropdown Label --'] = '';
+      keywrds1['onekey'] = 'onevalue';
+      keywrds1['twokey'] = 'twovalue';
+      keywrds1['threekey'] = 'threevalue';
+
+      keywrds2['-- Insert Keyword --'] = '';
+      keywrds2['Username'] = '%user%';
+      keywrds2['Last login date'] = '%last_login%';
+      config.InsertWords = {
+        combos : [ { options: keywrds1, context: "body" },
+               { options: keywrds2, context: "li" } ]
+      }
+
+    }
+
+    return config;
+  }
+
+
+  var f = document.forms[0];
+  f.innerHTML = '';
+
+  var lipsum = document.getElementById('lipsum').innerHTML;
+
+  for(var x = 0; x < num; x++)
+  {
+    var ta = 'myTextarea' + x;
+
+    var div = document.createElement('div');
+    div.className = 'area_holder';
+
+    var txta = document.createElement('textarea');
+    txta.id   = ta;
+    txta.name = ta;
+    txta.value = lipsum;
+    txta.style.width="100%";
+    txta.style.height="420px";
+
+    div.appendChild(txta);
+    f.appendChild(div);
+  }
+  
+  //check submitted values
+  var submit = document.createElement('input');
+  submit.type = "submit";
+  submit.id = "submit";
+  submit.value = "submit";
+  f.appendChild(submit);
+  
+  var _oldSubmitHandler = null;
+  if (document.forms[0].onsubmit != null) {
+    _oldSubmitHandler = document.forms[0].onsubmit;
+  }
+  function frame_onSubmit(){
+    alert(document.getElementById("myTextarea0").value);
+    if (_oldSubmitHandler != null) {
+      _oldSubmitHandler();
+    }
+  }
+  document.forms[0].onsubmit = frame_onSubmit;

Added: plog/trunk/js/xinha/examples/stylist.css
===================================================================
--- plog/trunk/js/xinha/examples/stylist.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/stylist.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,31 @@
+  /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  Stylist plugin example CSS file.  Used by full_example.js
+    --  when the Stylist plugin is included in an auto-generated example.
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/examples/stylist.css $
+    --  $LastChangedDate: 2005-07-19 14:23:58 +0800 (Tue, 19 Jul 2005) $
+    --  $LastChangedRevision: 277 $
+    --  $LastChangedBy: gogo $
+    --------------------------------------------------------------------------*/
+
+.bluetext
+{
+  color:blue;
+}
+
+p.blue_paragraph
+{
+  color:darkblue;
+}
+
+li.green_list_item
+{
+  color:green;
+}
+
+h1.webdings_lvl_1
+{
+  font-family:webdings;
+}
+
+img.polaroid { border:1px solid black; background-color:white; padding:10px; padding-bottom:30px; }
\ No newline at end of file

Added: plog/trunk/js/xinha/examples/testbed.html
===================================================================
--- plog/trunk/js/xinha/examples/testbed.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/examples/testbed.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+
+  <!--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  Xinha example usage.  This file shows how a developer might make use of
+    --  Xinha, it forms the primary example file for the entire Xinha project.
+    --  This file can be copied and used as a template for development by the
+    --  end developer who should simply removed the area indicated at the bottom
+    --  of the file to remove the auto-example-generating code and allow for the
+    --  use of the file as a boilerplate.
+    --
+    --  $HeadURL: svn://gogo@xinha.gogo.co.nz/repository/trunk/examples/full_example-body.html $
+    --  $LastChangedDate: 2005-03-05 21:42:32 +1300 (Sat, 05 Mar 2005) $
+    --  $LastChangedRevision: 35 $
+    --  $LastChangedBy: gogo $
+    --------------------------------------------------------------------------->
+
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>Example of Xinha</title>
+  <link rel="stylesheet" href="full_example.css" />
+
+  <script type="text/javascript">
+    // You must set _editor_url to the URL (including trailing slash) where
+    // where xinha is installed, it's highly recommended to use an absolute URL
+    //  eg: _editor_url = "/path/to/xinha/";
+    // You may try a relative URL if you wish]
+    //  eg: _editor_url = "../";
+    // in this example we do a little regular expression to find the absolute path.
+    _editor_url  = document.location.href.replace(/examples\/.*/, '')
+    _editor_lang = "en";      // And the language we need to use in the editor.
+  </script>
+
+  <!-- Load up the actual editor core -->
+  <script type="text/javascript" src="../htmlarea.js"></script>
+
+  <script type="text/javascript">
+    xinha_editors = null;
+    xinha_init    = null;
+    xinha_config  = null;
+    xinha_plugins = null;
+
+    // This contains the names of textareas we will make into Xinha editors
+    xinha_init = xinha_init ? xinha_init : function()
+    {
+      /** STEP 1 ***************************************************************
+       * First, what are the plugins you will be using in the editors on this
+       * page.  List all the plugins you will need, even if not all the editors
+       * will use all the plugins.
+       ************************************************************************/
+
+      xinha_plugins = xinha_plugins ? xinha_plugins :
+      [
+        
+      ];
+             // THIS BIT OF JAVASCRIPT LOADS THE PLUGINS, NO TOUCHING  :)
+             if(!HTMLArea.loadPlugins(xinha_plugins, xinha_init)) return;
+
+      /** STEP 2 ***************************************************************
+       * Now, what are the names of the textareas you will be turning into
+       * editors?
+       ************************************************************************/
+
+      xinha_editors = xinha_editors ? xinha_editors :
+      [
+        'myTextArea'
+      ];
+
+      /** STEP 3 ***************************************************************
+       * We create a default configuration to be used by all the editors.
+       * If you wish to configure some of the editors differently this will be
+       * done in step 4.
+       *
+       * If you want to modify the default config you might do something like this.
+       *
+       *   xinha_config = new HTMLArea.Config();
+       *   xinha_config.width  = 640;
+       *   xinha_config.height = 420;
+       *
+       *************************************************************************/
+
+       xinha_config = xinha_config ? xinha_config : new HTMLArea.Config();
+/*
+       // We can load an external stylesheet like this - NOTE : YOU MUST GIVE AN ABSOLUTE URL
+      //  otherwise it won't work!
+      xinha_config.stylistLoadStylesheet(document.location.href.replace(/[^\/]*\.html/, 'stylist.css'));
+
+      // Or we can load styles directly
+      xinha_config.stylistLoadStyles('p.red_text { color:red }');
+
+      // If you want to provide "friendly" names you can do so like
+      // (you can do this for stylistLoadStylesheet as well)
+      xinha_config.stylistLoadStyles('p.pink_text { color:pink }', {'p.pink_text' : 'Pretty Pink'});
+*/
+      /** STEP 3 ***************************************************************
+       * We first create editors for the textareas.
+       *
+       * You can do this in two ways, either
+       *
+       *   xinha_editors   = HTMLArea.makeEditors(xinha_editors, xinha_config, xinha_plugins);
+       *
+       * if you want all the editor objects to use the same set of plugins, OR;
+       *
+       *   xinha_editors = HTMLArea.makeEditors(xinha_editors, xinha_config);
+       *   xinha_editors['myTextArea'].registerPlugins(['Stylist','FullScreen']);
+       *   xinha_editors['anotherOne'].registerPlugins(['CSS','SuperClean']);
+       *
+       * if you want to use a different set of plugins for one or more of the
+       * editors.
+       ************************************************************************/
+
+      xinha_editors   = HTMLArea.makeEditors(xinha_editors, xinha_config, xinha_plugins);
+
+      /** STEP 4 ***************************************************************
+       * If you want to change the configuration variables of any of the
+       * editors,  this is the place to do that, for example you might want to
+       * change the width and height of one of the editors, like this...
+       *
+       *   xinha_editors.myTextArea.config.width  = 640;
+       *   xinha_editors.myTextArea.config.height = 480;
+       *
+       ************************************************************************/
+
+
+      /** STEP 5 ***************************************************************
+       * Finally we "start" the editors, this turns the textareas into
+       * Xinha editors.
+       ************************************************************************/
+
+      HTMLArea.startEditors(xinha_editors);
+      window.onload = null;
+    }
+
+    window.onload   = xinha_init;
+    // window.onunload = HTMLArea.collectGarbageForIE;
+  </script>
+</head>
+
+<body>
+
+  <form action="javascript:var x = document.getElementById('editors_here');alert(x.myTextArea.value);" id="editors_here" onsubmit="alert(this.myTextArea.value);">
+    <textarea id="myTextArea" name="myTextArea" style="width:100%;height:320px;">
+      &lt;p&gt;
+        Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+        Aliquam et tellus vitae justo varius placerat. Suspendisse iaculis
+        velit semper dolor. Donec gravida tincidunt mi. Curabitur tristique
+        ante elementum turpis. Aliquam nisl. Nulla posuere neque non
+        tellus. Morbi vel nibh. Cum sociis natoque penatibus et magnis dis
+        parturient montes, nascetur ridiculus mus. Nam nec wisi. In wisi.
+        Curabitur pharetra bibendum lectus.
+      &lt;/p&gt;
+
+      &lt;ul&gt;
+        &lt;li&gt; Phasellus et massa sed diam viverra semper.  &lt;/li&gt;
+        &lt;li&gt; Mauris tincidunt felis in odio.              &lt;/li&gt;
+        &lt;li&gt; Nulla placerat nunc ut pede.                 &lt;/li&gt;
+        &lt;li&gt; Vivamus ultrices mi sit amet urna.           &lt;/li&gt;
+        &lt;li&gt; Quisque sed augue quis nunc laoreet volutpat.&lt;/li&gt;
+        &lt;li&gt; Nunc sit amet metus in tortor semper mattis. &lt;/li&gt;
+      &lt;/ul&gt;
+    </textarea>
+
+    <input type="submit" /> <input type="reset" />
+  </form>
+  <script language="javascript">
+    document.write(document.compatMode);
+  </script>
+  <a href="#" onclick="xinha_editors.myTextArea.hidePanels();">Hide</a>
+  <a href="#" onclick="xinha_editors.myTextArea.showPanels();">Show</a>
+</body>
+</html>
\ No newline at end of file

Added: plog/trunk/js/xinha/htmlarea-plog-resourcelist.js
===================================================================
--- plog/trunk/js/xinha/htmlarea-plog-resourcelist.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/htmlarea-plog-resourcelist.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,141 @@
+function _generateBaseLink( dest, blogId, type, resourceName, resourceDesc, preview )
+{
+    if( type == 2 ) {
+	    if( preview == 1 ) {
+	        htmlCode = plogBaseUrl+'/resserver.php?blogId='+blogId+'&resource='+encodeURIComponent(resourceName)+'&mode=preview';
+	    }
+		else if( preview == 2) {
+			htmlCode = plogBaseUrl+'/resserver.php?blogId='+blogId+'&resource='+encodeURIComponent(resourceName)+'&mode=medium';
+		}
+	    else {
+	        htmlCode = plogBaseUrl+'/resserver.php?blogId='+blogId+'&resource='+encodeURIComponent(resourceName);
+	    }
+    }
+    else {
+	    // if not an image, there is not much we can do
+	    htmlCode = '<a title="'+resourceDesc+'" href="'+plogBaseUrl+'/resserver.php?blogId='+blogId+'&amp;resource='+encodeURIComponent(resourceName)+'">'+resourceName+'</a>';
+    }
+  
+    return htmlCode;
+}
+
+function _generateResourceLink( dest, blogId, type, resourceName, resourceDesc, preview, mimeType, resId )
+{
+    var htmlCode = '';
+    if( type == 1 ) {
+	    // if the resource is an image, check the second parameter to see wether we'd like
+	    // to show the preview with a link to the real size image or the real image
+	    // inlined with the text
+	    if( preview == 1 ) {
+		    htmlCode = '<a id="res_' + resId+ '" href="'+plogBaseUrl+'/resserver.php?blogId='+blogId+'&amp;resource='+encodeURIComponent(resourceName)+'" type="'+mimeType+'">';
+		    htmlCode += '<img style="margin: 5px;" border="0" alt="'+resourceDesc+'" src="'+plogBaseUrl+'/resserver.php?blogId='+blogId+'&amp;resource='+encodeURIComponent(resourceName)+'&amp;mode=preview" />';
+		    htmlCode += '</a>';
+	    }
+		else if ( preview == 2 ) {
+		    htmlCode = '<a id="res_' + resId+ '" href="'+plogBaseUrl+'/resserver.php?blogId='+blogId+'&amp;resource='+encodeURIComponent(resourceName)+'" type="'+mimeType+'">';
+		    htmlCode += '<img style="margin: 5px;" border="0" alt="'+resourceDesc+'" src="'+plogBaseUrl+'/resserver.php?blogId='+blogId+'&amp;resource='+encodeURIComponent(resourceName)+'&amp;mode=medium" />';
+		    htmlCode += '</a>';
+		}
+	    else {
+		    htmlCode = '<img style="margin: 5px;" alt="'+resourceDesc+'" src="'+plogBaseUrl+'/resserver.php?blogId='+blogId+'&amp;resource='+encodeURIComponent(resourceName)+'" />';
+	    }
+    }
+    else {
+	    // if not an image, there is not much we can do
+	    htmlCode = '<a id="res_'+resId+'" title="'+resourceDesc+'" href="'+plogBaseUrl+'/resserver.php?blogId='+blogId+'&amp;resource='+encodeURIComponent(resourceName)+'" type="'+mimeType+'">'+resourceName+'</a>';
+    }
+  
+    return htmlCode;
+
+}
+
+function addResourceLink( dest, reqFormat, blogId, type, resourceName, resourceDesc, preview, mimeType, resId ) 
+{
+    // generate the link
+    var htmlCode = _generateResourceLink( dest, reqFormat, blogId, type, resourceName, resourceDesc, preview, mimeType, resId );
+  
+    // and now send the value to the text area where we are typing the post
+    if( dest == 1 ) {
+	    //parent.opener.document.newPost.postText.value += htmlCode;
+	    addText( parent.opener.document.newPost.postText, htmlCode );
+    }
+    else {
+	    //parent.opener.document.newPost.postExtendedText.value += htmlCode;
+	    addText( parent.opener.document.newPost.postExtendedText, htmlCode );
+    }	
+
+    // finally close this window since we don't need it anymore
+    //window.close();
+}
+
+function _generateAlbumLink( dest, blogId, albumId, albumName, albumDesc ) 
+{
+    var htmlCode = '';
+    
+    // if no other global variable called 'indexPage' is defined, use the
+    // default one
+    if( indexPage == '' )
+        indexPage = 'index.php';
+
+    htmlCode = '<a title="'+albumDesc+'" href="'+plogBaseUrl+'/index.php?op=ViewAlbum&amp;blogId='+blogId+'&amp;albumId='+albumId+'">'+albumName+'</a>';
+	
+    return htmlCode;      
+}
+
+/**
+ * generates and adds a link to an album to the textarea
+ *
+ * @param dest
+ * @param blogId
+ * @param albumId
+ * @param albumName
+ * @param albumDesc
+ */
+function addAlbumLink( dest, blogId, albumId, albumName, albumDesc ) 
+{
+    albumLink = _generateAlbumLink( dest, blogId, albumId, albumName, albumDesc );
+
+    // and now send the value to the text area where we are typing the post
+    if( dest == 1 ) {
+        addText( parent.opener.document.newPost.postText, albumLink );
+    }	
+    else {
+		addText( parent.opener.document.newPost.postExtendedText, albumLink );
+    }
+}
+
+// ------
+//
+// htmlarea-related code
+//
+// -------
+//
+
+function resourceListWindowInit(htmlarea) {
+    // if we use this method, the dialog will be resized to its full size and I don't like that...
+    if( htmlarea ) {
+	    __dlg_init();
+	    window.resizeTo(450,600);
+    }
+}
+
+function addHtmlareaLink(dest, blogId, type, resourceName, resourceDesc, preview, mimeType, resId ) {
+    //var param = _generateResourceLink( dest, blogId, type, resourceName, resourceDesc, preview );
+    param = new Object();
+    param["htmlCode"] = _generateResourceLink( dest, blogId, type, resourceName, resourceDesc, preview, mimeType, resId );
+    __dlg_close(param);
+    return false;
+};
+
+function addHtmlareaAlbumLink( dest, blogId, albumId, albumName, albumDesc ) 
+{
+    param = new Object();
+    param["htmlCode"] = _generateAlbumLink( dest, blogId, albumId, albumName, albumDesc );
+    __dlg_close(param)
+    return false;
+}
+
+function onCancel() {
+    __dlg_close(null);
+    return false;
+};

Added: plog/trunk/js/xinha/htmlarea-plog.js
===================================================================
--- plog/trunk/js/xinha/htmlarea-plog.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/htmlarea-plog.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,98 @@
+/**
+ * This file has all the custom changes made to htmlarea required by plog, such as the 
+ * pop-up window that allows to insert a resource into the textbox. Please make here any other
+ * change needed, do NOT modify htmlarea.js in any way, it'll make things easier for us
+ * when a new version comes out!
+ */
+
+HTMLArea.prototype._plogPopupDialog = function(url, action, init) {
+    Dialog(url, action, init, true);
+};
+
+var postTextEditor = null;
+var postExtendedTextEditor = null;
+
+// If you want to use HTMLArea plugins, you should load the plugin first
+HTMLArea.loadPlugin('ContextMenu');
+
+// this function will get called at body.onload
+function initEditor() {
+
+    // ------------------------------------------------------
+    // Create postText Editor
+    // ------------------------------------------------------
+    postTextEditor = new HTMLArea("postText");
+
+    // Config postText Toolbar
+    postTextEditor.config.registerButton({
+        id: "insertresource",
+        tooltip: "Insert Resource",
+        image: "js/xinha/images/ed_resource.gif",
+        textMode: false,
+        action: insertResource});
+
+    // add our new icon in a place better suited for this task...		
+    postTextEditor.config.toolbar = [
+	    ["popupeditor"],
+	    ["separator","fontname","fontsize","bold","italic","underline","strikethrough"],
+	    ["separator","forecolor","hilitecolor","separator","subscript","superscript","separator","htmlmode"],
+	    ["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"],
+	    ["separator","insertorderedlist","insertunorderedlist","outdent","indent"],
+	    ["separator","inserthorizontalrule","createlink","insertimage","insertresource","inserttable"],
+	    ["separator","killword","removeformat","toggleborders","lefttoright", "righttoleft"]
+    ];  
+    
+    // Config postText Plugins
+    postTextEditor.registerPlugin('ContextMenu');
+
+    // Generate postText Editor
+    setTimeout(function() {postTextEditor.generate();}, 1000); 
+
+    // ------------------------------------------------------
+    // Create postExtendedText Editor
+    // ------------------------------------------------------
+    postExtendedTextEditor = new HTMLArea("postExtendedText");
+
+    // Config postText Toolbar
+    postExtendedTextEditor.config.registerButton({
+        id: "insertresource",
+        tooltip: "Insert Resource",
+        image: "js/xinha/images/ed_resource.gif",
+        textMode: false,
+        action: insertResource});
+
+    // add our new icon in a place better suited for this task...		
+    postExtendedTextEditor.config.toolbar = [
+	    ["popupeditor"],
+	    ["separator","fontname","fontsize","bold","italic","underline","strikethrough"],
+	    ["separator","forecolor","hilitecolor","separator","subscript","superscript","separator","htmlmode"],
+	    ["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"],
+	    ["separator","insertorderedlist","insertunorderedlist","outdent","indent"],
+	    ["separator","inserthorizontalrule","createlink","insertimage","insertresource","inserttable"],
+	    ["separator","killword","removeformat","toggleborders","lefttoright", "righttoleft"]
+    ];    
+    
+    // Config postText Plugins    
+    postExtendedTextEditor.registerPlugin('ContextMenu');
+
+    // Generate postExtendedText Editor
+    setTimeout(function() {postExtendedTextEditor.generate();}, 1000); 
+    
+    return false;
+};
+
+// The method that will insert a resource
+function insertResource(editor, id) {
+	//var editor = this;	// for nested functions
+	editor._plogPopupDialog("admin.php?op=resourceList&mode=1", function(param) {
+		if (!param) {	// user must have pressed Cancel
+			return false;
+		}
+		// otherwise, insert the html code as it came from the dialog window
+		htmlCode = param["htmlCode"];
+		editor.insertHTML( htmlCode );
+	}, null);
+};
+
+// Initialize HTMLArea Editor
+window.onload = initEditor;
\ No newline at end of file

Added: plog/trunk/js/xinha/htmlarea.css
===================================================================
--- plog/trunk/js/xinha/htmlarea.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/htmlarea.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,234 @@
+.htmlarea { background: #fff; margin:2px; }
+
+.htmlarea .toolbar {
+  cursor: default;
+  background: ButtonFace;
+  padding: 3px;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+.htmlarea .toolbar table { margin: 0; font-family: tahoma,verdana,sans-serif; font-size: 11px; }
+.htmlarea .toolbar img { border: none; }
+.htmlarea .toolbar .label { padding: 0px 3px; }
+
+.htmlarea .toolbar .button {
+  background: ButtonFace;
+  color: ButtonText;
+  border: 1px solid ButtonFace;
+  padding: 1px;
+  margin: 0px;
+  width: 18px;
+  height: 18px;
+}
+.htmlarea .toolbar a.button:hover {
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+.htmlarea .toolbar a.buttonDisabled:hover {
+  border-color: ButtonFace;
+}
+.htmlarea .toolbar .buttonActive,
+.htmlarea .toolbar .buttonPressed
+{
+  padding: 2px 0px 0px 2px;
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+.htmlarea .toolbar .buttonPressed {
+  background: ButtonHighlight;
+}
+.htmlarea .toolbar .indicator {
+  padding: 0px 3px;
+  overflow: hidden;
+  width: 20px;
+  text-align: center;
+  cursor: default;
+  border: 1px solid ButtonShadow;
+}
+
+.htmlarea .toolbar .buttonDisabled img {
+  filter: gray() alpha(opacity = 25);
+  -moz-opacity: 0.25;
+}
+
+.htmlarea .toolbar .separator {
+  /*position: relative;*/
+  margin: 3px;
+  border-left: 1px solid ButtonShadow;
+  border-right: 1px solid ButtonHighlight;
+  width: 0px;
+  height: 18px;
+  padding: 0px;
+}
+
+.htmlarea .toolbar .space { width: 5px; }
+
+.htmlarea .toolbar select, .htmlarea .toolbar option { font: 11px Tahoma,Verdana,sans-serif;}
+
+.htmlarea .toolbar select,
+.htmlarea .toolbar select:hover,
+.htmlarea .toolbar select:active { background: FieldFace; color: ButtonText; }
+
+.htmlarea iframe.xinha_iframe, .htmlarea textarea.xinha_textarea
+{
+  border: none; /*1px solid;*/
+}
+
+.htmlarea .statusBar {
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+  padding: 2px 4px;
+  background-color: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+
+.htmlarea .statusBar .statusBarTree a {
+  padding: 2px 5px;
+  color: #00f;
+}
+
+.htmlarea .statusBar .statusBarTree a:visited { color: #00f; }
+.htmlarea .statusBar .statusBarTree a:hover {
+  background-color: Highlight;
+  color: HighlightText;
+  padding: 1px 4px;
+  border: 1px solid HighlightText;
+}
+
+
+/* Hidden DIV popup dialogs (PopupDiv) */
+
+.dialog {
+  color: ButtonText;
+  background: ButtonFace;
+}
+
+.dialog .content { padding: 2px; }
+
+.dialog, .dialog button, .dialog input, .dialog select, .dialog textarea, .dialog table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+
+.dialog table { border-collapse: collapse; }
+
+.dialog .title, .dialog h1
+{
+  background: #008;
+  color: #ff8;
+  border-bottom: 1px solid #000;
+  padding: 1px 0px 2px 5px;
+  font-size: 12px;
+  font-weight: bold;
+  cursor: default;
+}
+.dialog h1 { margin:0px;}
+.dialog .title .button {
+  float: right;
+  border: 1px solid #66a;
+  padding: 0px 1px 0px 2px;
+  margin-right: 1px;
+  color: #fff;
+  text-align: center;
+}
+
+.dialog .title .button-hilite { border-color: #88f; background: #44c; }
+
+.dialog button {
+  width: 5em;
+  padding: 0px;
+}
+
+.dialog .buttonColor {
+  padding: 1px;
+  cursor: default;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.dialog .buttonColor-hilite {
+  border-color: #000;
+}
+
+.dialog .buttonColor .chooser, .dialog .buttonColor .nocolor {
+  height: 0.6em;
+  border: 1px solid;
+  padding: 0px 1em;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+
+.dialog .buttonColor .nocolor { padding: 0px; }
+.dialog .buttonColor .nocolor-hilite { background-color: #fff; color: #f00; }
+
+.dialog .label { text-align: right; width: 6em; }
+.dialog .value input { width: 100%; }
+.dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; }
+
+.dialog legend { font-weight: bold; }
+.dialog fieldset table { margin: 2px 0px; }
+
+.popupdiv {
+  border: 2px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.popupwin {
+  padding: 0px;
+  margin: 0px;
+}
+
+.popupwin .title {
+  background: #fff;
+  color: #000;
+  font-weight: bold;
+  font-size: 120%;
+  padding: 3px 10px;
+  margin-bottom: 10px;
+  border-bottom: 1px solid black;
+  letter-spacing: 2px;
+}
+
+form { margin: 0px; border: none; }
+
+
+/** Panels **/
+.htmlarea .panels.top
+{
+  border-bottom : 1px solid;
+  border-color: ButtonShadow;
+}
+
+.htmlarea .panels.right
+{
+  border-left : 1px solid;
+  border-color: ButtonShadow;
+}
+
+.htmlarea .panels.left
+{
+  border-right : 1px solid;
+  border-color: ButtonShadow;
+}
+
+.htmlarea .panels.bottom
+{
+  border-top : 1px solid;
+  border-color: ButtonShadow;
+}
+
+.htmlarea .panel h1 {
+  background: ButtonFace;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+  margin:   0px;
+  padding:  0px;
+  font-size:100%;
+  font-weight:bold;
+  padding: 2px;
+}
+
+.htmlarea .panels.left  .panel { border-right:none; border-left:none; }
+.htmlarea .panels.left  h1     { border-right:none;  }
+.htmlarea .panels.right .panel { border-right:none; border-left:none; }
+.htmlarea .panels.left  h1     { border-left:none;  }
+.htmlarea { border: 1px solid black; }

Added: plog/trunk/js/xinha/htmlarea.js
===================================================================
--- plog/trunk/js/xinha/htmlarea.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/htmlarea.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,5552 @@
+
+  /*--------------------------------------:noTabs=true:tabSize=2:indentSize=2:--
+    --  Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
+    --
+    --  Use of Xinha is granted by the terms of the htmlArea License (based on
+    --  BSD license)  please read license.txt in this package for details.
+    --
+    --  Xinha was originally based on work by Mihai Bazon which is:
+    --      Copyright (c) 2003-2004 dynarch.com.
+    --      Copyright (c) 2002-2003 interactivetools.com, inc.
+    --      This copyright notice MUST stay intact for use.
+    --
+    --  Developers - Coding Style:
+    --   For the sake of not committing needlessly conflicting changes,
+    --
+    --   * New code to be indented with 2 spaces ("soft tab").
+    --   * New code preferably uses BSD-Style Bracing
+    --      if(foo)
+    --      {
+    --        bar();
+    --      }
+    --   * Don't change brace styles unless you're working on the non BSD-Style
+    --     area (so we don't get spurious changes in line numbering).
+    --   * Don't change indentation unless you're working on the badly indented
+    --     area (so we don't get spurious changes of large blocks of code).
+    --   * Jedit is the recommended editor, a comment of this format should be
+    --     included in the top 10 lines of the file (see the embedded edit mode)
+    --
+    --  $HeadURL: http://svn.xinha.python-hosting.com/trunk/htmlarea.js $
+    --  $LastChangedDate: 2005-07-20 07:16:09 +0800 (Wed, 20 Jul 2005) $
+    --  $LastChangedRevision: 278 $
+    --  $LastChangedBy: gogo $
+    --------------------------------------------------------------------------*/
+
+// -------------------------------------------------------------
+// PLOG HTMLAREA TWEAK
+// Changed by: Mark Wu
+// Date: 2005/07/20
+// Purpose: Base URL and Language setting for pLog
+// -------------------------------------------------------------
+
+var _editor_url = "js/xinha";
+var _editor_lang = "en";
+
+// -------------------------------------------------------------
+
+HTMLArea.version =
+{
+  'Release'   : 'Trunk',
+  'Head'      : '$HeadURL: http://svn.xinha.python-hosting.com/trunk/htmlarea.js $'.replace(/^[^:]*: (.*) \$$/, '$1'),
+  'Date'      : '$LastChangedDate: 2005-07-20 07:16:09 +0800 (Wed, 20 Jul 2005) $'.replace(/^[^:]*: ([0-9-]*) ([0-9:]*) ([+0-9]*) \((.*)\) \$/, '$4 $2 $3'),
+  'Revision'  : '$LastChangedRevision: 278 $'.replace(/^[^:]*: (.*) \$$/, '$1'),
+  'RevisionBy': '$LastChangedBy: gogo $'.replace(/^[^:]*: (.*) \$$/, '$1')
+}
+
+if (typeof _editor_url == "string") {
+  // Leave exactly one backslash at the end of _editor_url
+  _editor_url = _editor_url.replace(/\x2f*$/, '/');
+} else {
+  alert("WARNING: _editor_url is not set!  You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea/', but it can be relative if you prefer.  Further we will try to load the editor files correctly but we'll probably fail.");
+  _editor_url = '';
+}
+
+// make sure we have a language
+if (typeof _editor_lang == "string") {
+  _editor_lang = _editor_lang.toLowerCase();
+} else {
+  _editor_lang = "en";
+}
+
+// skin stylesheet to load
+if (!(typeof _editor_skin == "string")) {
+  _editor_skin = "";
+}
+
+var __htmlareas = [ ];
+
+// browser identification
+HTMLArea.agt = navigator.userAgent.toLowerCase();
+HTMLArea.is_ie	   = ((HTMLArea.agt.indexOf("msie") != -1) && (HTMLArea.agt.indexOf("opera") == -1));
+HTMLArea.is_opera  = (HTMLArea.agt.indexOf("opera") != -1);
+HTMLArea.is_mac	   = (HTMLArea.agt.indexOf("mac") != -1);
+HTMLArea.is_mac_ie = (HTMLArea.is_ie && HTMLArea.is_mac);
+HTMLArea.is_win_ie = (HTMLArea.is_ie && !HTMLArea.is_mac);
+HTMLArea.is_gecko  = (navigator.product == "Gecko");
+
+// Creates a new HTMLArea object.  Tries to replace the textarea with the given
+// ID with it.
+function HTMLArea(textarea, config)
+{
+  if(!textarea) throw("Tried to create HTMLArea without textarea specified.");
+
+  if (HTMLArea.checkSupportedBrowser()) {
+    if (typeof config == "undefined") {
+      this.config = new HTMLArea.Config();
+    } else {
+      this.config = config;
+    }
+    this._htmlArea = null;
+
+    if(typeof textarea != 'object')
+    {
+      textarea = HTMLArea.getElementById('textarea', textarea);
+    }
+    this._textArea = textarea;
+       
+    // Before we modify anything, get the initial textarea size
+    this._initial_ta_size =
+    {
+      w: textarea.style.width ? textarea.style.width   : (textarea.offsetWidth + 'px'),
+      h: textarea.style.height ? textarea.style.height : (textarea.offsetHeight + 'px')
+    }
+
+    this._editMode = "wysiwyg";
+    this.plugins = {};
+    this._timerToolbar = null;
+    this._timerUndo = null;
+    this._undoQueue = new Array(this.config.undoSteps);
+    this._undoPos = -1;
+    this._customUndo = true;
+    this._mdoc = document; // cache the document, we need it in plugins
+    this.doctype = '';
+    this.__htmlarea_id_num = __htmlareas.length;
+    __htmlareas[this.__htmlarea_id_num] = this;
+
+    this._notifyListeners = { };
+
+    // Panels
+    var panels = this._panels =
+    {
+      right:
+      {
+        on: true,
+        container:    document.createElement('td'),
+        panels: [ ]
+      },
+      left:
+      {
+        on: true,
+        container:    document.createElement('td'),
+        panels: [ ]
+      },
+      top:
+      {
+        on: true,
+        container:    document.createElement('td'),
+        panels: [ ]
+      },
+      bottom:
+      {
+        on: true,
+        container:    document.createElement('td'),
+        panels: [ ]
+      }
+    };
+
+    for(var i in panels)
+    {
+      panels[i].div = panels[i].container; // legacy
+      panels[i].container.className = 'panels ' + i;
+      HTMLArea.freeLater(panels[i], 'container');
+      HTMLArea.freeLater(panels[i], 'div');      
+    }
+    HTMLArea.freeLater(this, '_textArea');
+  }
+};
+
+HTMLArea.onload = function(){};
+HTMLArea.init = function() {
+    HTMLArea.onload();
+};
+
+
+// cache some regexps
+HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig;
+HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
+HTMLArea.RE_head    = /<head>((.|\n)*?)<\/head>/i;
+HTMLArea.RE_body    = /<body[^>]*>((.|\n|\r|\t)*?)<\/body>/i;
+HTMLArea.RE_Specials = /([\/\^$*+?.()|{}[\]])/g;
+HTMLArea.RE_email    = /[a-z0-9_]{3,}@[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,})+/i;
+HTMLArea.RE_url      = /(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,}){2,}(:[0-9]+)?(\/\S+)*)/i;
+
+HTMLArea.Config = function () {
+  var cfg = this;
+  this.version = HTMLArea.version.Revision;
+
+  // Width and Height
+  //  you may set these as follows
+  //  width = 'auto'      -- the width of the original textarea will be used
+  //  width = 'toolbar'   -- the width of the toolbar will be used
+  //  width = '<css measure>' -- use any css measurement, eg width = '75%'
+  //
+  //  height = 'auto'     -- the height of the original textarea
+  //  height = '<css measure>' -- any css measurement, eg height = '480px'
+  this.width  = "auto";
+  this.height = "auto";
+
+  // the next parameter specifies whether the toolbar should be included
+  // in the size above, or are extra to it.  If false then it's recommended
+  // to have explicit pixel sizes above (or on your textarea and have auto above)
+  this.sizeIncludesBars = true;
+
+  // the next parameter specifies whether the panels should be included
+  // in the size above, or are extra to it.  If false then it's recommended
+  // to have explicit pixel sizes above (or on your textarea and have auto above)
+  this.sizeIncludesPanels = true;
+
+  // each of the panels has a dimension, for the left/right it's the width
+  // for the top/bottom it's the height.
+  //
+  // WARNING: PANEL DIMENSIONS MUST BE SPECIFIED AS PIXEL WIDTHS
+  this.panel_dimensions =
+  {
+    left:   '200px', // Width
+    right:  '200px',
+    top:    '100px', // Height
+    bottom: '100px'
+  }
+
+  // enable creation of a status bar?
+  this.statusBar = true;
+
+  // intercept ^V and use the HTMLArea paste command
+  // If false, then passes ^V through to browser editor widget
+  this.htmlareaPaste = false;
+
+  this.mozParaHandler = 'best'; // set to 'built-in', 'dirty' or 'best'
+                                // built-in: will (may) use 'br' instead of 'p' tags
+                                // dirty   : will use p and work good enough for the majority of cases,
+                                // best    : works the best, but it's about 12kb worth of javascript
+                                //   and will probably be slower than 'dirty'.  This is the "EnterParagraphs"
+                                //   plugin from "hipikat", rolled in to be part of the core code
+
+  // maximum size of the undo queue
+  this.undoSteps = 20;
+
+  // the time interval at which undo samples are taken
+  this.undoTimeout = 500;	// 1/2 sec.
+
+  // if true then HTMLArea will retrieve the full HTML, starting with the
+  // <HTML> tag.
+  this.fullPage = false;
+
+  // style included in the iframe document
+  this.pageStyle = "";
+
+  // external stylesheets to load (REFERENCE THESE ABSOLUTELY)
+  this.pageStyleSheets = [ ];
+
+  // specify a base href for relative links
+  this.baseHref  = null;
+
+  // we can strip the base href out of relative links to leave them relative, reason for this
+  //   especially if you don't specify a baseHref is that mozilla at least (& IE ?) will prefix
+  //   the baseHref to any relative links to make them absolute, which isn't what you want most the time.
+  this.stripBaseHref = true;
+
+  // and we can strip the url of the editor page from named links (eg <a href="#top">...</a>)
+  //  reason for this is that mozilla at least (and IE ?) prefixes location.href to any
+  //  that don't have a url prefixing them
+  this.stripSelfNamedAnchors = true;
+
+  // sometimes high-ascii in links can cause problems for servers (basically they don't recognise them)
+  //  so you can use this flag to ensure that all characters other than the normal ascii set (actually
+  //  only ! through ~) are escaped in URLs to % codes
+  this.only7BitPrintablesInURLs = true;
+
+  // if you are putting the HTML written in Xinha into an email you might want it to be 7-bit
+  //  characters only.  This config option (off by default) will convert all characters consuming
+  //  more than 7bits into UNICODE decimal entity references (actually it will convert anything
+  //  below <space> (chr 20) except cr, lf and tab and above <tilde> (~, chr 7E))
+  this.sevenBitClean  = false;
+
+  // sometimes we want to be able to replace some string in the html comng in and going out
+  //  so that in the editor we use the "internal" string, and outside and in the source view
+  //  we use the "external" string  this is useful for say making special codes for
+  //  your absolute links, your external string might be some special code, say "{server_url}"
+  //  an you say that the internal represenattion of that should be http://your.server/
+  this.specialReplacements = { }; // { 'external_string' : 'internal_string' }
+
+  // set to true if you want Word code to be cleaned upon Paste
+  this.killWordOnPaste = true;
+
+  // enable the 'Target' field in the Make Link dialog
+  this.makeLinkShowsTarget = true;
+
+  // CharSet of the iframe, default is the charset of the document
+  this.charSet = HTMLArea.is_gecko ? document.characterSet : document.charset;
+
+  // URL-s
+  this.imgURL = "images/";
+  this.popupURL = "popups/";
+  this.helpURL  = _editor_url + "reference.html";
+
+  // remove tags (these have to be a regexp, or null if this functionality is not desired)
+  this.htmlRemoveTags = null;
+
+  // Turning this on will turn all "linebreak" and "separator" items in your toolbar into soft-breaks,
+  // this means that if the items between that item and the next linebreak/separator can
+  // fit on the same line as that which came before then they will, otherwise they will
+  // float down to the next line.
+
+  // If you put a linebreak and separator next to each other, only the separator will
+  // take effect, this allows you to have one toolbar that works for both flowToolbars = true and false
+  // infact the toolbar below has been designed in this way, if flowToolbars is false then it will
+  // create explictly two lines (plus any others made by plugins) breaking at justifyleft, however if
+  // flowToolbars is false and your window is narrow enough then it will create more than one line
+  // even neater, if you resize the window the toolbars will reflow.  Niiiice.
+
+  this.flowToolbars = true;
+
+  /** CUSTOMIZING THE TOOLBAR
+   * -------------------------
+   *
+   * It is recommended that you customize the toolbar contents in an
+   * external file (i.e. the one calling HTMLArea) and leave this one
+   * unchanged.  That's because when we (InteractiveTools.com) release a
+   * new official version, it's less likely that you will have problems
+   * upgrading HTMLArea.
+   */
+  this.toolbar =
+  [
+    ["popupeditor"],
+    ["separator","formatblock","fontname","fontsize","bold","italic","underline","strikethrough"],
+    ["separator","forecolor","hilitecolor","textindicator"],
+    ["separator","subscript","superscript"],
+    ["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"],
+    ["separator","insertorderedlist","insertunorderedlist","outdent","indent"],
+    ["separator","inserthorizontalrule","createlink","insertimage","inserttable"],
+    ["separator","undo","redo","selectall"], (HTMLArea.is_gecko ? [] : ["cut","copy","paste","overwrite","saveas"]),
+    ["separator","killword","removeformat","toggleborders","lefttoright", "righttoleft","separator","htmlmode","about"]
+  ];
+
+
+  this.fontname = {
+    "&mdash; font &mdash;":         '',
+    "Arial":	   'arial,helvetica,sans-serif',
+    "Courier New":	   'courier new,courier,monospace',
+    "Georgia":	   'georgia,times new roman,times,serif',
+    "Tahoma":	   'tahoma,arial,helvetica,sans-serif',
+    "Times New Roman": 'times new roman,times,serif',
+    "Verdana":	   'verdana,arial,helvetica,sans-serif',
+    "impact":	   'impact',
+    "WingDings":	   'wingdings'
+  };
+
+  this.fontsize = {
+    "&mdash; size &mdash;"  : "",
+    "1 (8 pt)" : "1",
+    "2 (10 pt)": "2",
+    "3 (12 pt)": "3",
+    "4 (14 pt)": "4",
+    "5 (18 pt)": "5",
+    "6 (24 pt)": "6",
+    "7 (36 pt)": "7"
+  };
+
+  this.formatblock = {
+    "&mdash; format &mdash;"  : "",
+    "Heading 1": "h1",
+    "Heading 2": "h2",
+    "Heading 3": "h3",
+    "Heading 4": "h4",
+    "Heading 5": "h5",
+    "Heading 6": "h6",
+    "Normal"   : "p",
+    "Address"  : "address",
+    "Formatted": "pre"
+  };
+
+  this.customSelects = {};
+
+  function cut_copy_paste(e, cmd, obj) {
+    e.execCommand(cmd);
+  };
+
+  this.debug = true;
+
+  this.URIs = {
+   "blank": "popups/blank.html",
+   "link": "link.html",
+   "insert_image": "insert_image.html",
+   "insert_table": "insert_table.html",
+   "select_color": "select_color.html",
+   "about": "about.html"
+  };
+
+
+  // ADDING CUSTOM BUTTONS: please read below!
+  // format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]"
+  //    - ID: unique ID for the button.  If the button calls document.execCommand
+  //	    it's wise to give it the same name as the called command.
+  //    - ACTION: function that gets called when the button is clicked.
+  //              it has the following prototype:
+  //                 function(editor, buttonName)
+  //              - editor is the HTMLArea object that triggered the call
+  //              - buttonName is the ID of the clicked button
+  //              These 2 parameters makes it possible for you to use the same
+  //              handler for more HTMLArea objects or for more different buttons.
+  //    - ToolTip: tooltip, will be translated below
+  //    - Icon: path to an icon image file for the button
+  //            OR; you can use an 18x18 block of a larger image by supllying an array
+  //            that has three elemtents, the first is the larger image, the second is the column
+  //            the third is the row.  The ros and columns numbering starts at 0 but there is
+  //            a header row and header column which have numbering to make life easier.
+  //            See images/buttons_main.gif to see how it's done.
+  //    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.
+  this.btnList = {
+    bold:          [ "Bold",   ["ed_buttons_main.gif",3,2], false, function(e) {e.execCommand("bold");} ],
+    italic:        [ "Italic", ["ed_buttons_main.gif",2,2], false, function(e) {e.execCommand("italic");} ],
+    underline:     [ "Underline", ["ed_buttons_main.gif",2,0], false, function(e) {e.execCommand("underline");} ],
+    strikethrough: [ "Strikethrough", ["ed_buttons_main.gif",3,0], false, function(e) {e.execCommand("strikethrough");} ],
+    subscript:     [ "Subscript", ["ed_buttons_main.gif",3,1], false, function(e) {e.execCommand("subscript");} ],
+    superscript:   [ "Superscript", ["ed_buttons_main.gif",2,1], false, function(e) {e.execCommand("superscript");} ],
+
+    justifyleft:   [ "Justify Left", ["ed_buttons_main.gif",0,0], false, function(e) {e.execCommand("justifyleft");} ],
+    justifycenter: [ "Justify Center", ["ed_buttons_main.gif",1,1], false, function(e){e.execCommand("justifycenter");}],
+    justifyright: [ "Justify Right", ["ed_buttons_main.gif",1,0], false, function(e) {e.execCommand("justifyright");} ],
+    justifyfull: [ "Justify Full", ["ed_buttons_main.gif",0,1], false, function(e) {e.execCommand("justifyfull");} ],
+
+
+    orderedlist: [ "Ordered List", ["ed_buttons_main.gif",0,3], false, function(e) {e.execCommand("insertorderedlist");} ],
+    unorderedlist: [ "Bulleted List", ["ed_buttons_main.gif",1,3], false, function(e) {e.execCommand("insertunorderedlist");} ],
+    insertorderedlist: [ "Ordered List", ["ed_buttons_main.gif",0,3], false, function(e) {e.execCommand("insertorderedlist");} ],
+    insertunorderedlist: [ "Bulleted List", ["ed_buttons_main.gif",1,3], false, function(e) {e.execCommand("insertunorderedlist");} ],
+
+    outdent: [ "Decrease Indent", ["ed_buttons_main.gif",1,2], false, function(e) {e.execCommand("outdent");} ],
+    indent: [ "Increase Indent",["ed_buttons_main.gif",0,2], false, function(e) {e.execCommand("indent");} ],
+    forecolor: [ "Font Color", ["ed_buttons_main.gif",3,3], false, function(e) {e.execCommand("forecolor");} ],
+    hilitecolor: [ "Background Color", ["ed_buttons_main.gif",2,3], false, function(e) {e.execCommand("hilitecolor");} ],
+
+    undo: [ "Undoes your last action", ["ed_buttons_main.gif",4,2], false, function(e) {e.execCommand("undo");} ],
+    redo: [ "Redoes your last action", ["ed_buttons_main.gif",5,2], false, function(e) {e.execCommand("redo");} ],
+    cut: [ "Cut selection", ["ed_buttons_main.gif",5,0], false, cut_copy_paste ],
+    copy: [ "Copy selection", ["ed_buttons_main.gif",4,0], false, cut_copy_paste ],
+    paste: [ "Paste from clipboard", ["ed_buttons_main.gif",4,1], false, cut_copy_paste ],
+    selectall: [ "Select all", "ed_selectall.gif", false, function(e) {e.execCommand("selectall");} ],
+
+
+    inserthorizontalrule: [ "Horizontal Rule", ["ed_buttons_main.gif",6,0], false, function(e) {e.execCommand("inserthorizontalrule");} ],
+    createlink: [ "Insert Web Link", ["ed_buttons_main.gif",6,1], false, function(e) {e._createLink();} ],
+    insertimage: [ "Insert/Modify Image", ["ed_buttons_main.gif",6,3], false, function(e) {e.execCommand("insertimage");} ],
+    inserttable: [ "Insert Table", ["ed_buttons_main.gif",6,2], false, function(e) {e.execCommand("inserttable");} ],
+
+
+    htmlmode: [ "Toggle HTML Source", ["ed_buttons_main.gif",7,0], true, function(e) {e.execCommand("htmlmode");} ],
+    toggleborders: [ "Toggle Borders", ["ed_buttons_main.gif",7,2], false, function(e) { e._toggleBorders() } ],
+    print:         [ "Print document", ["ed_buttons_main.gif",8,1], false, function(e) {e._iframe.contentWindow.print();} ],
+    saveas: [ "Save as", "ed_saveas.gif", false, function(e) {e.execCommand("saveas",false,"noname.htm");} ],
+    about: [ "About this editor", ["ed_buttons_main.gif",8,2], true, function(e) {e.execCommand("about");} ],
+    showhelp: [ "Help using editor", ["ed_buttons_main.gif",9,2], true, function(e) {e.execCommand("showhelp");} ],
+
+    splitblock:    [ "Split Block", "ed_splitblock.gif", false, function(e) {e._splitBlock();} ],
+    lefttoright: [ "Direction left to right", ["ed_buttons_main.gif",0,4], false, function(e) {e.execCommand("lefttoright");} ],
+    righttoleft: [ "Direction right to left", ["ed_buttons_main.gif",1,4], false, function(e) {e.execCommand("righttoleft");} ],
+    overwrite: [ "Insert/Overwrite", "ed_overwrite.gif", false, function(e) {e.execCommand("overwrite");} ],
+
+    wordclean:     [ "MS Word Cleaner", ["ed_buttons_main.gif",5,3], false, function(e) {e._wordClean();} ],
+    clearfonts:    [ "Clear Inline Font Specifications", ["ed_buttons_main.gif",5,4], false, function(e) {e._clearFonts();} ],
+    removeformat:  [ "Remove formatting", ["ed_buttons_main.gif",4,4], false, function(e) {e.execCommand("removeformat");} ],
+    killword:      [ "Clear MSOffice tags", ["ed_buttons_main.gif",4,3], false, function(e) {e.execCommand("killword");} ]
+
+  };
+  /* ADDING CUSTOM BUTTONS
+   * ---------------------
+   *
+   * It is recommended that you add the custom buttons in an external
+   * file and leave this one unchanged.  That's because when we
+   * (InteractiveTools.com) release a new official version, it's less
+   * likely that you will have problems upgrading HTMLArea.
+   *
+   * Example on how to add a custom button when you construct the HTMLArea:
+   *
+   *   var editor = new HTMLArea("your_text_area_id");
+   *   var cfg = editor.config; // this is the default configuration
+   *   cfg.btnList["my-hilite"] =
+   *	[ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action
+   *	  "Highlight selection", // tooltip
+   *	  "my_hilite.gif", // image
+   *	  false // disabled in text mode
+   *	];
+   *   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
+   *
+   * An alternate (also more convenient and recommended) way to
+   * accomplish this is to use the registerButton function below.
+   */
+  // initialize tooltips from the I18N module and generate correct image path
+  for (var i in this.btnList) {
+    var btn = this.btnList[i];
+    if(typeof btn[1] != 'string')
+    {
+      btn[1][0] = _editor_url + this.imgURL + btn[1][0];
+    }
+    else
+    {
+      btn[1] = _editor_url + this.imgURL + btn[1];
+    }
+    btn[0] = HTMLArea._lc(btn[0]); //initialize tooltip
+  }
+
+};
+
+/** Helper function: register a new button with the configuration.  It can be
+ * called with all 5 arguments, or with only one (first one).  When called with
+ * only one argument it must be an object with the following properties: id,
+ * tooltip, image, textMode, action.  Examples:
+ *
+ * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...});
+ * 2. config.registerButton({
+ *      id       : "my-hilite",      // the ID of your button
+ *      tooltip  : "Hilite text",    // the tooltip
+ *      image    : "my-hilite.gif",  // image to be displayed in the toolbar
+ *      textMode : false,            // disabled in text mode
+ *      action   : function(editor) { // called when the button is clicked
+ *                   editor.surroundHTML('<span class="hilite">', '</span>');
+ *                 },
+ *      context  : "p"               // will be disabled if outside a <p> element
+ *    });
+ */
+HTMLArea.Config.prototype.registerButton = function(id, tooltip, image, textMode, action, context) {
+  var the_id;
+  if (typeof id == "string") {
+    the_id = id;
+  } else if (typeof id == "object") {
+    the_id = id.id;
+  } else {
+    alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");
+    return false;
+  }
+  // check for existing id
+  if (typeof this.customSelects[the_id] != "undefined") {
+    // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
+  }
+  if (typeof this.btnList[the_id] != "undefined") {
+    // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
+  }
+  switch (typeof id) {
+      case "string": this.btnList[id] = [ tooltip, image, textMode, action, context ]; break;
+      case "object": this.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action, id.context ]; break;
+  }
+};
+
+HTMLArea.prototype.registerPanel = function(side, object)
+{
+  if(!side) side = 'right';
+  var panel = this.addPanel(side);
+  if(object)
+  {
+    object.drawPanelIn(panel);
+  }
+}
+
+/** The following helper function registers a dropdown box with the editor
+ * configuration.  You still have to add it to the toolbar, same as with the
+ * buttons.  Call it like this:
+ *
+ * FIXME: add example
+ */
+HTMLArea.Config.prototype.registerDropdown = function(object) {
+  // check for existing id
+  if (typeof this.customSelects[object.id] != "undefined") {
+    // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
+  }
+  if (typeof this.btnList[object.id] != "undefined") {
+    // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
+  }
+  this.customSelects[object.id] = object;
+};
+
+/** Call this function to remove some buttons/drop-down boxes from the toolbar.
+ * Pass as the only parameter a string containing button/drop-down names
+ * delimited by spaces.  Note that the string should also begin with a space
+ * and end with a space.  Example:
+ *
+ *   config.hideSomeButtons(" fontname fontsize textindicator ");
+ *
+ * It's useful because it's easier to remove stuff from the defaul toolbar than
+ * create a brand new toolbar ;-)
+ */
+HTMLArea.Config.prototype.hideSomeButtons = function(remove) {
+  var toolbar = this.toolbar;
+  for (var i = toolbar.length; --i >= 0;) {
+    var line = toolbar[i];
+    for (var j = line.length; --j >= 0; ) {
+      if (remove.indexOf(" " + line[j] + " ") >= 0) {
+        var len = 1;
+        if (/separator|space/.test(line[j + 1])) {
+          len = 2;
+        }
+        line.splice(j, len);
+      }
+    }
+  }
+};
+
+/** Helper Function: add buttons/drop-downs boxes with title or separator to the toolbar
+ * if the buttons/drop-downs boxes doesn't allready exists.
+ * id: button or selectbox (as array with separator or title)
+ * where: button or selectbox (as array if the first is not found take the second and so on)
+ * position:
+ * -1 = insert button (id) one position before the button (where)
+ * 0 = replace button (where) by button (id)
+ * +1 = insert button (id) one position after button (where)
+ *
+ * cfg.addToolbarElement(["T[title]", "button_id", "separator"] , ["first_id","second_id"], -1);
+*/
+
+HTMLArea.Config.prototype.addToolbarElement = function(id, where, position) {
+  var toolbar = this.toolbar;
+  var a, i, j, o, sid;
+  var idIsArray = false;
+  var whereIsArray = false;
+  var whereLength = 0;
+  var whereJ = 0;
+  var whereI = 0;
+  var exists = false;
+  var found = false;
+  // check if id and where are arrys
+  if ((id && typeof id == "object") && (id.constructor == Array)) {
+    idIsArray = true;
+  }
+  if ((where && typeof where == "object") && (where.constructor == Array)) {
+    whereIsArray = true;
+    whereLength = where.length;
+	}
+
+  if (idIsArray) { //find the button/select box in input array
+    for (i = 0; i < id.length; ++i) {
+      if ((id[i] != "separator") && (id[i].indexOf("T[") != 0)) {
+        sid = id[i];
+      }
+    }
+  } else {
+    sid = id;
+  }
+
+  for (var i = 0; !exists && !found && i < toolbar.length; ++i) {
+    a = toolbar[i]
+    for (j = 0; !found && j < a.length; ++j) {
+      if (a[i] == sid) { // check if button/select box exists
+        exists = true;
+        break;
+      }
+      if (whereIsArray) {
+        for (o = 0; o < whereLength; ++o) {
+          if(a[j] == where[o]) {
+            if (o == 0) {
+              found = true;
+              j--;
+              break;
+            } else {
+              whereI = i;
+              whereJ = j;
+              whereLength = o;
+            }
+          }
+        }
+      } else {
+        if (a[j] == where) { // find the position to insert
+          found = true;
+          break;
+        }
+      }
+    }
+  }
+
+  if (!exists) {
+    if (!found && whereIsArray) { //if check found any other as the first button
+      if (where.length != whereLength) {
+        j = whereJ;
+        a = toolbar[whereI];
+        found = true;
+      }
+    }
+    if (found) {
+      if (position == 0) { // replace the found button
+        if (idIsArray) {
+          a[j] = id[id.length-1];
+          for (i = id.length-1; --i >= 0;) {
+            a.splice(j, 0, id[i]);
+          }
+        } else {
+          a[j] = id;
+        }
+      } else { // insert before/after the found button
+        if (position < 0) {
+          j = j + position + 1; //correct position before
+        } else if (position > 0) {
+          j = j + position; //correct posion after
+        }
+        if (idIsArray) {
+          for (i = id.length; --i >= 0;) {
+            a.splice(j, 0, id[i]);
+          }
+        } else {
+           a.splice(j, 0, id);
+        }
+      }
+    }	else { // no button found
+      toolbar[0].splice(0, 0, "separator");
+      if (idIsArray) {
+        for (i = id.length; --i >= 0;) {
+          toolbar[0].splice(0, 0, id[i]);
+        }
+      } else {
+        toolbar[0].splice(0, 0, id);
+      }
+    }
+  }
+}
+
+/** Helper function: replace all TEXTAREA-s in the document with HTMLArea-s. */
+HTMLArea.replaceAll = function(config) {
+  var tas = document.getElementsByTagName("textarea");
+  for (var i = tas.length; i > 0; (new HTMLArea(tas[--i], config)).generate());
+};
+
+/** Helper function: replaces the TEXTAREA with the given ID with HTMLArea. */
+HTMLArea.replace = function(id, config)
+{
+  var ta = HTMLArea.getElementById("textarea", id);
+  return ta ? (new HTMLArea(ta, config)).generate() : null;;
+};
+
+// Creates the toolbar and appends it to the _htmlarea
+HTMLArea.prototype._createToolbar = function () {
+  var editor = this;	// to access this in nested functions
+
+  var toolbar = document.createElement("div");
+  // ._toolbar is for legacy, ._toolBar is better thanks.
+  this._toolBar = this._toolbar = toolbar;
+  toolbar.className = "toolbar";
+  toolbar.unselectable = "1";
+
+  HTMLArea.freeLater(this, '_toolBar');
+  HTMLArea.freeLater(this, '_toolbar');
+  
+  var tb_row = null;
+  var tb_objects = new Object();
+  this._toolbarObjects = tb_objects;
+
+	this._createToolbar1(editor, toolbar, tb_objects);
+	this._htmlArea.appendChild(toolbar);      
+  
+  return toolbar;
+}
+
+
+HTMLArea.prototype._setConfig = function(config) {
+	this.config = config;
+}
+
+HTMLArea.prototype._addToolbar = function() {
+	this._createToolbar1(this, this._toolbar, this._toolbarObjects);
+}
+
+// separate from previous createToolBar to allow dynamic change of toolbar
+HTMLArea.prototype._createToolbar1 = function (editor, toolbar, tb_objects) {
+
+  // This shouldn't be necessary, but IE seems to float outside of the container
+  // when we float toolbar sections, so we have to clear:both here as well
+  // as at the end (which we do have to do).
+  if(editor.config.flowToolbars)
+  {
+    var brk = document.createElement('div');
+    brk.style.height =
+      brk.style.width =
+      brk.style.lineHeight =
+      brk.style.fontSize = '1px';
+    brk.style.clear = 'both';
+    toolbar.appendChild(brk);
+  }
+
+  // creates a new line in the toolbar
+  function newLine() {
+    if(typeof tb_row != 'undefined' && tb_row.childNodes.length == 0) return;
+
+    var table = document.createElement("table");
+    table.border = "0px";
+    table.cellSpacing = "0px";
+    table.cellPadding = "0px";
+    if(editor.config.flowToolbars)
+    {
+      if(HTMLArea.is_ie)
+      {
+        table.style.styleFloat = "left";
+      }
+      else
+      {
+        table.style.cssFloat = "left";
+      }
+    }
+
+    toolbar.appendChild(table);
+    // TBODY is required for IE, otherwise you don't see anything
+    // in the TABLE.
+    var tb_body = document.createElement("tbody");
+    table.appendChild(tb_body);
+    tb_row = document.createElement("tr");
+    tb_body.appendChild(tb_row);
+
+    table.className = 'toolbarRow'; // meh, kinda.
+  }; // END of function: newLine
+
+  // init first line
+  newLine();
+
+  // updates the state of a toolbar element.  This function is member of
+  // a toolbar element object (unnamed objects created by createButton or
+  // createSelect functions below).
+  function setButtonStatus(id, newval) {
+    var oldval = this[id];
+    var el = this.element;
+    if (oldval != newval) {
+      switch (id) {
+          case "enabled":
+        if (newval) {
+          HTMLArea._removeClass(el, "buttonDisabled");
+          el.disabled = false;
+        } else {
+          HTMLArea._addClass(el, "buttonDisabled");
+          el.disabled = true;
+        }
+        break;
+          case "active":
+        if (newval) {
+          HTMLArea._addClass(el, "buttonPressed");
+        } else {
+          HTMLArea._removeClass(el, "buttonPressed");
+        }
+        break;
+      }
+      this[id] = newval;
+    }
+  }; // END of function: setButtonStatus
+
+  // this function will handle creation of combo boxes.  Receives as
+  // parameter the name of a button as defined in the toolBar config.
+  // This function is called from createButton, above, if the given "txt"
+  // doesn't match a button.
+  function createSelect(txt) {
+    var options = null;
+    var el = null;
+    var cmd = null;
+    var customSelects = editor.config.customSelects;
+    var context = null;
+    var tooltip = "";
+    switch (txt) {
+        case "fontsize":
+        case "fontname":
+        case "formatblock":
+      // the following line retrieves the correct
+      // configuration option because the variable name
+      // inside the Config object is named the same as the
+      // button/select in the toolbar.  For instance, if txt
+      // == "formatblock" we retrieve config.formatblock (or
+      // a different way to write it in JS is
+      // config["formatblock"].
+      options = editor.config[txt];
+      cmd = txt;
+      break;
+        default:
+      // try to fetch it from the list of registered selects
+      cmd = txt;
+      var dropdown = customSelects[cmd];
+      if (typeof dropdown != "undefined") {
+        options = dropdown.options;
+        context = dropdown.context;
+        if (typeof dropdown.tooltip != "undefined") {
+          tooltip = dropdown.tooltip;
+        }
+      } else {
+        alert("ERROR [createSelect]:\nCan't find the requested dropdown definition");
+      }
+      break;
+    }
+    if (options) {
+      el = document.createElement("select");
+      el.title = tooltip;
+      var obj = {
+        name	: txt, // field name
+        element : el,	// the UI element (SELECT)
+        enabled : true, // is it enabled?
+        text	: false, // enabled in text mode?
+        cmd	: cmd, // command ID
+        state	: setButtonStatus, // for changing state
+        context : context
+      };
+      
+      HTMLArea.freeLater(obj);
+      
+      tb_objects[txt] = obj;
+      
+      for (var i in options) {
+        var op = document.createElement("option");
+        op.innerHTML = HTMLArea._lc(i);
+        op.value = options[i];
+        el.appendChild(op);
+      }
+      HTMLArea._addEvent(el, "change", function () {
+        editor._comboSelected(el, txt);
+      });
+    }
+    return el;
+  }; // END of function: createSelect
+
+  // appends a new button to toolbar
+  function createButton(txt) {
+    // the element that will be created
+    var el = null;
+    var btn = null;
+    switch (txt) {
+        case "separator":
+          if(editor.config.flowToolbars) newLine();
+      el = document.createElement("div");
+      el.className = "separator";
+      break;
+        case "space":
+      el = document.createElement("div");
+      el.className = "space";
+      break;
+      case "linebreak":
+          newLine();
+          return false;
+        case "textindicator":
+      el = document.createElement("div");
+      el.appendChild(document.createTextNode("A"));
+      el.className = "indicator";
+      el.title = HTMLArea._lc("Current style");
+      var obj = {
+        name	: txt, // the button name (i.e. 'bold')
+        element : el, // the UI element (DIV)
+        enabled : true, // is it enabled?
+        active	: false, // is it pressed?
+        text	: false, // enabled in text mode?
+        cmd	: "textindicator", // the command ID
+        state	: setButtonStatus // for changing state
+      };
+      
+      HTMLArea.freeLater(obj);
+      
+      tb_objects[txt] = obj;
+      break;
+        default:
+      btn = editor.config.btnList[txt];
+    }
+    if (!el && btn) {
+      el = document.createElement("a");
+      el.style.display = 'block';
+      el.href = 'javascript:void(0)';
+      el.style.textDecoration = 'none';
+      el.title = btn[0];
+      el.className = "button";
+      // let's just pretend we have a button object, and
+      // assign all the needed information to it.
+      var obj = {
+        name	: txt, // the button name (i.e. 'bold')
+        element : el, // the UI element (DIV)
+        enabled : true, // is it enabled?
+        active	: false, // is it pressed?
+        text	: btn[2], // enabled in text mode?
+        cmd	: btn[3], // the command ID
+        state	: setButtonStatus, // for changing state
+        context : btn[4] || null // enabled in a certain context?
+      };
+      
+      HTMLArea.freeLater(obj);
+      
+      tb_objects[txt] = obj;
+      // handlers to emulate nice flat toolbar buttons
+      HTMLArea._addEvent(el, "mouseout", function () {
+        if (obj.enabled) with (HTMLArea) {
+          //_removeClass(el, "buttonHover");
+          _removeClass(el, "buttonActive");
+          (obj.active) && _addClass(el, "buttonPressed");
+        }
+      });
+
+      HTMLArea._addEvent(el, "mousedown", function (ev) {
+        if (obj.enabled) with (HTMLArea) {
+          _addClass(el, "buttonActive");
+          _removeClass(el, "buttonPressed");
+          _stopEvent(is_ie ? window.event : ev);
+        }
+      });
+      // when clicked, do the following:
+      HTMLArea._addEvent(el, "click", function (ev) {
+        if (obj.enabled) with (HTMLArea) {
+          _removeClass(el, "buttonActive");
+          //_removeClass(el, "buttonHover");
+          if(HTMLArea.is_gecko)
+          {
+            editor.activateEditor();
+          }
+          obj.cmd(editor, obj.name, obj);
+          _stopEvent(is_ie ? window.event : ev);
+        }
+      });
+
+      var i_contain = HTMLArea.makeBtnImg(btn[1]);
+      var img = i_contain.firstChild;
+      el.appendChild(i_contain);
+
+      obj.imgel = img;      
+      obj.swapImage = function(newimg)
+      {
+        if(typeof newimg != 'string')
+        {
+          img.src = newimg[0];
+          img.style.position = 'relative';
+          img.style.top  = newimg[2] ? ('-' + (18 * (newimg[2] + 1)) + 'px') : '-18px';
+          img.style.left = newimg[1] ? ('-' + (18 * (newimg[1] + 1)) + 'px') : '-18px';
+        }
+        else
+        {
+          obj.imgel.src = newimg;
+          img.style.top = '0px';
+          img.style.left = '0px';
+        }
+      }
+      
+    } else if (!el) {
+      el = createSelect(txt);
+    }
+
+    return el;
+  };
+
+  var first = true;
+  for (var i = 0; i < this.config.toolbar.length; ++i) {
+    if (!first) {
+      // createButton("linebreak");
+    } else {
+      first = false;
+    }
+    if(this.config.toolbar[i] == null) this.config.toolbar[i] = ['separator'];
+    var group = this.config.toolbar[i];
+
+    for (var j = 0; j < group.length; ++j)
+    {
+      var code = group[j];
+      if (/^([IT])\[(.*?)\]/.test(code))
+      {
+        // special case, create text label
+        var l7ed = RegExp.$1 == "I"; // localized?
+        var label = RegExp.$2;
+        if (l7ed) {
+	  label = HTMLArea._lc(label);
+        }
+        var tb_cell = document.createElement("td");
+        tb_row.appendChild(tb_cell);
+        tb_cell.className = "label";
+        tb_cell.innerHTML = label;
+      }
+      else if(typeof code != 'function')
+      {
+        var tb_element = createButton(code);
+
+        if (tb_element)
+        {
+          var tb_cell = document.createElement("td");
+          tb_cell.className = 'toolbarElement';
+          tb_row.appendChild(tb_cell);
+          tb_cell.appendChild(tb_element);
+        }
+        else if (tb_element == null)
+        {
+          alert("FIXME: Unknown toolbar item: " + code);
+        }
+      }
+    }
+  }
+
+  if(editor.config.flowToolbars)
+  {
+    var brk = document.createElement('div');
+    brk.style.height =
+      brk.style.width =
+      brk.style.lineHeight =
+      brk.style.fontSize = '1px';
+    brk.style.clear = 'both';
+    toolbar.appendChild(brk);
+  }
+
+  return toolbar;
+};
+
+use_clone_img = false;
+HTMLArea.makeBtnImg = function(imgDef, doc)
+{
+  if(!doc) doc = document;
+
+  if(!doc._htmlareaImgCache)
+  {
+    doc._htmlareaImgCache = { };
+    HTMLArea.freeLater(doc._htmlareaImgCache);
+  }
+
+  var i_contain = null;
+  if(HTMLArea.is_ie && ((!doc.compatMode) || (doc.compatMode && doc.compatMode == "BackCompat")))
+  {
+    i_contain = doc.createElement('span');
+  }
+  else
+  {
+    i_contain = doc.createElement('div');
+    i_contain.style.position = 'relative';
+  }
+
+  i_contain.style.overflow = 'hidden';
+  i_contain.style.width = "18px";
+  i_contain.style.height = "18px";
+  i_contain.className    = 'buttonImageContainer';
+
+  var img = null;
+  if(typeof imgDef == 'string')
+  {
+    if(doc._htmlareaImgCache[imgDef])
+    {
+      img = doc._htmlareaImgCache[imgDef].cloneNode();
+    }
+    else
+    {
+      img = doc.createElement("img");
+      img.src = imgDef;
+      img.style.width = "18px";
+      img.style.height = "18px";
+      if(use_clone_img)
+        doc._htmlareaImgCache[imgDef] = img.cloneNode();
+    }
+  }
+  else
+  {
+    if(doc._htmlareaImgCache[imgDef[0]])
+    {
+      img = doc._htmlareaImgCache[imgDef[0]].cloneNode();
+    }
+    else
+    {
+      img = doc.createElement("img");
+      img.src = imgDef[0];
+      img.style.position = 'relative';
+      if(use_clone_img)
+        doc._htmlareaImgCache[imgDef[0]] = img.cloneNode();
+    }
+    img.style.top  = imgDef[2] ? ('-' + (18 * (imgDef[2] + 1)) + 'px') : '-18px';
+    img.style.left = imgDef[1] ? ('-' + (18 * (imgDef[1] + 1)) + 'px') : '-18px';
+  }
+  i_contain.appendChild(img);
+  return i_contain;
+}
+
+HTMLArea.prototype._createStatusBar = function() {
+  var statusbar = document.createElement("div");
+  statusbar.className = "statusBar";
+  this._statusBar = statusbar;
+  HTMLArea.freeLater(this, '_statusBar');
+  
+  // statusbar.appendChild(document.createTextNode(HTMLArea._lc("Path") + ": "));
+  // creates a holder for the path view
+  div = document.createElement("span");
+  div.className = "statusBarTree";
+  div.innerHTML = HTMLArea._lc("Path") + ": ";
+  this._statusBarTree = div;
+  HTMLArea.freeLater(this, '_statusBarTree');
+  this._statusBar.appendChild(div);
+
+  div = document.createElement("span");
+  div.innerHTML = HTMLArea._lc("You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.");
+  div.style.display = "none";
+  this._statusBarTextMode = div;
+  HTMLArea.freeLater(this, '_statusBarTextMode');
+  this._statusBar.appendChild(div);
+
+  if (!this.config.statusBar)
+  {
+    // disable it...
+    statusbar.style.display = "none";
+  }
+
+  return statusbar;
+};
+
+// Creates the HTMLArea object and replaces the textarea with it.
+HTMLArea.prototype.generate = function ()
+{
+  var editor = this;	// we'll need "this" in some nested functions
+
+  if(typeof Dialog == 'undefined')
+  {
+    HTMLArea._loadback
+      (_editor_url + 'dialog.js', function() { editor.generate(); } );
+      return false;
+  }
+
+  if(typeof HTMLArea.Dialog == 'undefined')
+  {
+    HTMLArea._loadback
+      (_editor_url + 'inline-dialog.js', function() { editor.generate(); } );
+      return false;
+  }
+
+  if(typeof PopupWin == 'undefined')
+  {
+    HTMLArea._loadback
+      (_editor_url + 'popupwin.js', function() { editor.generate(); } );
+      return false;
+  }
+
+  if(_editor_skin != "") {
+    var found=false;
+    var head = document.getElementsByTagName("head")[0];
+    var links = document.getElementsByTagName("link");
+    for(var i = 0; i<links.length; i++) {
+      if((links[i].rel == "stylesheet")&&(links[i].href == _editor_url + 'skins/' + _editor_skin + '/skin.css'))
+        found = true;
+    }
+    if(!found) {
+      var link = document.createElement("link");
+      link.type = "text/css";
+      link.href = _editor_url + 'skins/' + _editor_skin + '/skin.css';
+      link.rel = "stylesheet"
+      head.appendChild(link);
+    }
+  }
+
+  //backwards-compatibility: load FullScreen-Plugin if we find a "popupeditor"-button in the toolbar
+  var toolbar = editor.config.toolbar;
+  for (var i = toolbar.length; --i >= 0;) {
+    for (var j = toolbar[i].length; --j >= 0; ) {
+      if (toolbar[i][j]=="popupeditor") {
+        if(typeof FullScreen == "undefined") {
+          HTMLArea.loadPlugin("FullScreen", function() { editor.generate(); } );
+          return false;
+        }
+        editor.registerPlugin('FullScreen');
+      }
+    }
+  }
+
+  // If this is gecko, set up the paragraph handling now
+  if(HTMLArea.is_gecko)
+  {
+    switch(editor.config.mozParaHandler)
+    {
+      case 'best':
+      {
+        if(typeof EnterParagraphs == 'undefined')
+        {
+          HTMLArea.loadPlugin("EnterParagraphs", function() { editor.generate(); } );
+          return false;
+        }
+        editor.registerPlugin('EnterParagraphs');
+      }
+      break;
+
+      case 'dirty'   :
+      case 'built-in':
+      default        :
+      {
+        // See _editorEvent
+      }
+      break;
+    }
+  }
+
+  // create the editor framework, yah, table layout I know, but much easier
+  // to get it working correctly this way, sorry about that, patches welcome.
+
+  this._framework =
+  {
+    'table'     :document.createElement('table'),
+    'tbody'     :document.createElement('tbody'), // IE will not show the table if it doesn't have a tbody!
+    'tb_row'    :document.createElement('tr'),
+    'tb_cell'   :document.createElement('td'), // Toolbar
+
+    'tp_row'   :document.createElement('tr'),
+    'tp_cell'   :this._panels.top.container,   // top panel
+
+    'ler_row'   :document.createElement('tr'),
+    'lp_cell'   :this._panels.left.container,  // left panel
+    'ed_cell'   :document.createElement('td'), // editor
+    'rp_cell'   :this._panels.right.container, // right panel
+
+    'bp_row'    :document.createElement('tr'),
+    'bp_cell'   :this._panels.bottom.container,// bottom panel
+
+    'sb_row'    :document.createElement('tr'),
+    'sb_cell'   :document.createElement('td')  // status bar
+
+  }
+
+  HTMLArea.freeLater(this._framework);
+  
+  var fw = this._framework;
+  fw.table.border="0";
+  fw.table.cellPadding="0";
+  fw.table.cellSpacing="0";
+
+  fw.tb_row.style.verticalAlign = 'top';
+  fw.tp_row.style.verticalAlign = 'top';
+  fw.ler_row.style.verticalAlign= 'top';
+  fw.bp_row.style.verticalAlign = 'top';
+  fw.sb_row.style.verticalAlign = 'top';
+  fw.ed_cell.style.position     = 'relative';
+
+  // Put the cells in the rows        set col & rowspans
+  // note that I've set all these so that all panels are showing
+  // but they will be redone in sizeEditor() depending on which
+  // panels are shown.  It's just here to clarify how the thing
+  // is put togethor.
+  fw.tb_row.appendChild(fw.tb_cell);  fw.tb_cell.colSpan = 3;
+
+  fw.tp_row.appendChild(fw.tp_cell);  fw.tp_cell.colSpan = 3;
+
+  fw.ler_row.appendChild(fw.lp_cell);
+  fw.ler_row.appendChild(fw.ed_cell);
+  fw.ler_row.appendChild(fw.rp_cell);
+
+  fw.bp_row.appendChild(fw.bp_cell);  fw.bp_cell.colSpan = 3;
+
+  fw.sb_row.appendChild(fw.sb_cell);  fw.sb_cell.colSpan = 3;
+
+  // Put the rows in the table body
+  fw.tbody.appendChild(fw.tb_row);  // Toolbar
+  fw.tbody.appendChild(fw.tp_row); // Left, Top, Right panels
+  fw.tbody.appendChild(fw.ler_row);  // Editor/Textarea
+  fw.tbody.appendChild(fw.bp_row);  // Bottom panel
+  fw.tbody.appendChild(fw.sb_row);  // Statusbar
+
+  // and body in the table
+  fw.table.appendChild(fw.tbody);
+
+  var htmlarea = this._framework.table;
+  this._htmlArea = htmlarea;
+  HTMLArea.freeLater(this, '_htmlArea');
+  htmlarea.className = "htmlarea";
+
+    // create the toolbar and put in the area
+  var toolbar = this._createToolbar();
+  this._framework.tb_cell.appendChild(toolbar);
+
+    // create the IFRAME & add to container
+  var iframe = document.createElement("iframe");
+  iframe.src = _editor_url + editor.config.URIs["blank"];
+  this._framework.ed_cell.appendChild(iframe);
+  this._iframe = iframe;
+  this._iframe.className = 'xinha_iframe';
+  HTMLArea.freeLater(this, '_iframe');
+  
+    // creates & appends the status bar
+  var statusbar = this._createStatusBar();
+  this._framework.sb_cell.appendChild(statusbar);
+
+  // insert Xinha before the textarea.
+  var textarea = this._textArea;
+  textarea.parentNode.insertBefore(htmlarea, textarea);
+  textarea.className = 'xinha_textarea';
+
+  // extract the textarea and insert it into the htmlarea
+  HTMLArea.removeFromParent(textarea);
+  this._framework.ed_cell.appendChild(textarea);
+
+
+  // Set up event listeners for saving the iframe content to the textarea
+  if (textarea.form)
+  {
+    // onsubmit get the HTMLArea content and update original textarea.
+    HTMLArea.prependDom0Event
+    (
+      this._textArea.form,
+      'submit',
+      function() {editor._textArea.value = editor.outwardHtml(editor.getHTML()); return true;}
+    );
+
+    var initialTAContent = textarea.value;
+
+    // onreset revert the HTMLArea content to the textarea content
+    HTMLArea.prependDom0Event
+    (
+      this._textArea.form,
+      'reset',
+      function() { editor.setHTML(editor.inwardHtml(initialTAContent)); editor.updateToolbar(); return true; }
+    );
+  }
+
+  // add a handler for the "back/forward" case -- on body.unload we save
+  // the HTML content into the original textarea.
+  HTMLArea.prependDom0Event(window, 'unload', function() {textarea.value = editor.outwardHtml(editor.getHTML()); return true; });
+
+  // Hide textarea
+  textarea.style.display = "none";
+
+  // Initalize size
+  editor.initSize();
+
+  // Add an event to initialize the iframe once loaded.
+  editor._iframeLoadDone = false;
+  HTMLArea._addEvent
+  (
+    this._iframe,
+    'load',
+    function(e)
+    {
+      if(! editor._iframeLoadDone)
+      {
+        editor._iframeLoadDone = true;
+        editor.initIframe();
+      }
+      return true;
+    }
+  );
+
+};
+
+
+  /**
+   * Size the editor according to the INITIAL sizing information.
+   * config.width
+   *    The width may be set via three ways
+   *    auto    = the width is inherited from the original textarea
+   *    toolbar = the width is set to be the same size as the toolbar
+   *    <set size> = the width is an explicit size (any CSS measurement, eg 100em should be fine)
+   *
+   * config.height
+   *    auto    = the height is inherited from the original textarea
+   *    <set size> = an explicit size measurement (again, CSS measurements)
+   *
+   * config.sizeIncludesBars
+   *    true    = the tool & status bars will appear inside the width & height confines
+   *    false   = the tool & status bars will appear outside the width & height confines
+   *
+   */
+
+  HTMLArea.prototype.initSize = function()
+  {
+    var editor = this;
+
+    var width  = null;
+    var height = null;
+    switch(this.config.width)
+    {
+      case 'auto':
+      {
+        width = this._initial_ta_size.w;
+      }
+      break;
+
+      case 'toolbar':
+      {
+        width = this._toolBar.offsetWidth;
+      }
+      break;
+
+      default :
+      {
+        width = this.config.width;
+      }
+      break;
+    }
+
+    switch(this.config.height)
+    {
+      case 'auto':
+      {
+        height = this._initial_ta_size.h;
+      }
+      break;
+
+      default :
+      {
+        height = this.config.height;
+      }
+      break;
+    }
+
+    this.sizeEditor(width, height, this.config.sizeIncludesBars, this.config.sizeIncludesPanels);
+
+    HTMLArea.addDom0Event(window, 'resize', function(e) { editor.sizeEditor(); });
+
+    this.notifyOn('panel_change',function(){editor.sizeEditor();});
+  }
+
+  /**
+   *  Size the editor to a specific size, or just refresh the size (when window resizes for example)
+   *  @param width optional width (CSS specification)
+   *  @param height optional height (CSS specification)
+   *  @param includingBars optional boolean to indicate if the size should include or exclude tool & status bars
+   */
+
+  HTMLArea.prototype.sizeEditor = function(width, height, includingBars, includingPanels)
+  {
+
+    // We need to set the iframe & textarea to 100% height so that the htmlarea
+    // isn't "pushed out" when we get it's height, so we can change them later.
+    this._iframe.style.height   = '100%';
+    this._textArea.style.height = '100%';
+    this._iframe.style.width    = '';
+    this._textArea.style.width  = '';
+
+    if(includingBars != null)     this._htmlArea.sizeIncludesToolbars = includingBars;
+    if(includingPanels != null)   this._htmlArea.sizeIncludesPanels   = includingPanels;
+
+    if(width != null)
+    {
+      this._htmlArea.style.width          = width;
+      if(!this._htmlArea.sizeIncludesPanels)
+      {
+        // Need to add some for l & r panels
+        var panel = this._panels.right;
+        if(panel.on && panel.panels.length && HTMLArea.hasDisplayedChildren(panel.div))
+        {
+          this._htmlArea.style.width = this._htmlArea.offsetWidth + parseInt(this.config.panel_dimensions.right);
+        }
+
+        var panel = this._panels.left;
+        if(panel.on && panel.panels.length && HTMLArea.hasDisplayedChildren(panel.div))
+        {
+          this._htmlArea.style.width = this._htmlArea.offsetWidth + parseInt(this.config.panel_dimensions.left);
+        }
+      }
+    }
+
+    if(height != null)
+    {
+      this._htmlArea.style.height         = height;
+      if(!this._htmlArea.sizeIncludesToolbars)
+      {
+        // Need to add some for toolbars
+        this._htmlArea.style.height         = this._htmlArea.offsetHeight + this._toolbar.offsetHeight + this._statusBar.offsetHeight;
+      }
+
+      if(!this._htmlArea.sizeIncludesPanels)
+      {
+        // Need to add some for l & r panels
+        var panel = this._panels.top;
+        if(panel.on && panel.panels.length && HTMLArea.hasDisplayedChildren(panel.div))
+        {
+          this._htmlArea.style.height = this._htmlArea.offsetHeight + parseInt(this.config.panel_dimensions.top);
+        }
+
+        var panel = this._panels.bottom;
+        if(panel.on && panel.panels.length && HTMLArea.hasDisplayedChildren(panel.div))
+        {
+          this._htmlArea.style.height = this._htmlArea.offsetHeight + parseInt(this.config.panel_dimensions.bottom);
+        }
+      }
+    }
+
+    // At this point we have this._htmlArea.style.width & this._htmlArea.style.height
+    // which are the size for the OUTER editor area, including toolbars and panels
+    // now we size the INNER area and position stuff in the right places.
+    width  = this._htmlArea.offsetWidth;
+    height = this._htmlArea.offsetHeight;
+
+    // Set colspan for toolbar, and statusbar, rowspan for left & right panels, and insert panels to be displayed
+    // into thier rows
+    var panels = this._panels;
+    var editor = this;
+    var col_span = 1;
+
+    function panel_is_alive(pan)
+    {
+      if(panels[pan].on && panels[pan].panels.length && HTMLArea.hasDisplayedChildren(panels[pan].container))
+      {
+        panels[pan].container.style.display = '';
+        return true;
+      }
+
+      // Otherwise make sure it's been removed from the framework
+      else
+      {
+        panels[pan].container.style.display='none';
+        return false;
+      }
+    }
+
+    if(panel_is_alive('left'))
+    {
+      col_span += 1;      
+    }
+
+    if(panel_is_alive('top'))
+    {
+      // NOP
+    }
+
+    if(panel_is_alive('right'))
+    {
+      col_span += 1;
+    }
+
+    if(panel_is_alive('bottom'))
+    {
+      // NOP
+    }
+
+    this._framework.tb_cell.colSpan = col_span;
+    this._framework.tp_cell.colSpan = col_span;
+    this._framework.bp_cell.colSpan = col_span;
+    this._framework.sb_cell.colSpan = col_span;
+
+    // Put in the panel rows, top panel goes above editor row
+    if(!this._framework.tp_row.childNodes.length)
+    {
+      HTMLArea.removeFromParent(this._framework.tp_row);
+    }
+    else
+    {
+      if(!HTMLArea.hasParentNode(this._framework.tp_row))
+      {
+        this._framework.tbody.insertBefore(this._framework.tp_row, this._framework.ler_row);
+      }
+    }
+
+    // bp goes after the editor
+    if(!this._framework.bp_row.childNodes.length)
+    {
+      HTMLArea.removeFromParent(this._framework.bp_row);
+    }
+    else
+    {
+      if(!HTMLArea.hasParentNode(this._framework.bp_row))
+      {
+        this._framework.tbody.insertBefore(this._framework.bp_row, this._framework.ler_row.nextSibling);
+      }
+    }
+
+    // finally if the statusbar is on, insert it
+    if(!this.config.statusBar)
+    {
+      HTMLArea.removeFromParent(this._framework.sb_row);
+    }
+    else
+    {
+      if(!HTMLArea.hasParentNode(this._framework.sb_row))
+      {
+        this._framework.table.appendChild(this._framework.sb_row);
+      }
+    }
+
+    // Size and set colspans, link up the framework
+    this._framework.lp_cell.style.width  = this.config.panel_dimensions.left;
+    this._framework.rp_cell.style.width  = this.config.panel_dimensions.right;
+    this._framework.tp_cell.style.height = this.config.panel_dimensions.top;
+    this._framework.bp_cell.style.height = this.config.panel_dimensions.bottom;
+    this._framework.tb_cell.style.height = this._toolBar.offsetHeight   + 'px';
+    this._framework.sb_cell.style.height = this._statusBar.offsetHeight + 'px';
+
+    var edcellheight = height - this._toolBar.offsetHeight - this._statusBar.offsetHeight;
+    if(panel_is_alive('top'))    edcellheight  -= parseInt(this.config.panel_dimensions.top);
+    if(panel_is_alive('bottom')) edcellheight  -= parseInt(this.config.panel_dimensions.bottom);;
+    this._iframe.style.height    = edcellheight + 'px';
+
+    var edcellwidth = width;
+    if(panel_is_alive('left'))  edcellwidth -= parseInt(this.config.panel_dimensions.left);
+    if(panel_is_alive('right')) edcellwidth -= parseInt(this.config.panel_dimensions.right);
+    this._iframe.style.width     =  edcellwidth + 'px';
+
+    this._textArea.style.height = this._iframe.style.height;
+    this._textArea.style.width  = this._iframe.style.width;
+
+    this.notifyOf('resize', {width:this._htmlArea.offsetWidth, height:this._htmlArea.offsetHeight});
+  }
+
+  HTMLArea.prototype.addPanel = function(side)
+  {
+    var div = document.createElement('div');
+    div.side = side;
+    if(side == 'left' || side == 'right')
+    {
+      div.style.width = this.config.panel_dimensions[side];
+    }
+    HTMLArea.addClasses(div, 'panel');
+    this._panels[side].panels.push(div);
+    this._panels[side].div.appendChild(div);
+
+    this.notifyOf('panel_change', {'action':'add','panel':div});
+
+    return div;
+  }
+
+  HTMLArea.prototype.removePanel = function(panel)
+  {
+    this._panels[panel.side].div.removeChild(panel);
+    var clean = [ ];
+    for(var i = 0; i < this._panels[panel.side].panels.length; i++)
+    {
+      if(this._panels[panel.side].panels[i] != panel)
+      {
+        clean.push(this._panels[panel.side].panels[i]);
+      }
+    }
+    this._panels[panel.side].panels = clean;
+    this.notifyOf('panel_change', {'action':'remove','panel':panel});
+  }
+
+  HTMLArea.prototype.hidePanel = function(panel)
+  {
+    if(panel)
+    {
+      panel.style.display = 'none';
+      this.notifyOf('panel_change', {'action':'hide','panel':panel});
+    }
+  }
+
+  HTMLArea.prototype.showPanel = function(panel)
+  {
+    if(panel)
+    {
+      panel.style.display = '';
+      this.notifyOf('panel_change', {'action':'show','panel':panel});
+    }
+  }
+
+  HTMLArea.prototype.hidePanels = function(sides)
+  {
+    if(typeof sides == 'undefined')
+    {
+      sides = ['left','right','top','bottom'];
+    }
+
+    var reShow = [];
+    for(var i = 0; i < sides.length;i++)
+    {
+      if(this._panels[sides[i]].on)
+      {
+        reShow.push(sides[i]);
+        this._panels[sides[i]].on = false;
+      }
+    }
+    this.notifyOf('panel_change', {'action':'multi_hide','sides':sides});
+  }
+
+  HTMLArea.prototype.showPanels = function(sides)
+  {
+    if(typeof sides == 'undefined')
+    {
+      sides = ['left','right','top','bottom'];
+    }
+
+    var reHide = [];
+    for(var i = 0; i < sides.length;i++)
+    {
+      if(!this._panels[sides[i]].on)
+      {
+        reHide.push(sides[i]);
+        this._panels[sides[i]].on = true;
+      }
+    }
+    this.notifyOf('panel_change', {'action':'multi_show','sides':sides});
+  }
+
+  HTMLArea.objectProperties = function(obj)
+  {
+    var props = [ ];
+    for(var x in obj)
+    {
+      props[props.length] = x;
+    }
+    return props;
+  }
+
+  /*
+   * EDITOR ACTIVATION NOTES:
+   *  when a page has multiple Xinha editors, ONLY ONE should be activated at any time (this is mostly to
+   *  work around a bug in Mozilla, but also makes some sense).  No editor should be activated or focused
+   *  automatically until at least one editor has been activated through user action (by mouse-clicking in
+   *  the editor).
+   */
+
+  HTMLArea.prototype.editorIsActivated = function() {
+    try {
+      if (HTMLArea.is_gecko) return (this._doc.designMode == 'on');
+      else return (this._doc.body.contentEditable);
+    } catch (e)
+    {
+      return false;
+    }
+  }
+
+  HTMLArea._someEditorHasBeenActivated = false;
+  HTMLArea._currentlyActiveEditor      = false;
+  HTMLArea.prototype.activateEditor = function()
+  {
+    // We only want ONE editor at a time to be active
+    if(HTMLArea._currentlyActiveEditor)
+    {
+      if(HTMLArea._currentlyActiveEditor == this) return true;
+      HTMLArea._currentlyActiveEditor.deactivateEditor();
+    }
+
+    if (HTMLArea.is_gecko && this._doc.designMode != 'on')
+    {
+      try
+      {
+        // cannot set design mode if no display
+        if (this._iframe.style.display == 'none')
+        {
+          this._iframe.style.display = '';
+          this._doc.designMode = 'on';
+          this._iframe.style.display = 'none';
+        }
+        else
+        {
+          this._doc.designMode = 'on';
+        }
+      } catch (e) {}
+    }
+    else if(!HTMLArea.is_gecko && this._doc.body.contentEditable != true)
+    {
+      this._doc.body.contentEditable = true;
+    }
+
+    // We need to know that at least one editor on the page has been activated
+    // this is because we will not focus any editor until an editor has been activated
+    HTMLArea._someEditorHasBeenActivated = true;
+    HTMLArea._currentlyActiveEditor      = this;
+
+    var editor = this;
+    this.enableToolbar();
+  }
+
+  HTMLArea.prototype.deactivateEditor = function()
+  {
+    // If the editor isn't active then the user shouldn't use the toolbar
+    this.disableToolbar();
+
+    if (HTMLArea.is_gecko && this._doc.designMode != 'off')
+    {
+      try {this._doc.designMode = 'off';} catch (e) {}
+    }
+    else if(!HTMLArea.is_gecko && this._doc.body.contentEditable != false)
+    {
+      this._doc.body.contentEditable = false;
+    }
+
+    if(HTMLArea._currentlyActiveEditor != this)
+    {
+      // We just deactivated an editor that wasn't marked as the currentlyActiveEditor
+
+      return; // I think this should really be an error, there shouldn't be a situation where
+              // an editor is deactivated without first being activated.  but it probably won't
+              // hurt anything.
+    }
+
+    HTMLArea._currentlyActiveEditor = false;
+  }
+
+  HTMLArea.prototype.initIframe = function()
+  {
+    this.disableToolbar();
+    var doc = null;
+    var editor = this;
+    try
+    {
+      if (editor._iframe.contentDocument)
+      {
+        this._doc = editor._iframe.contentDocument;        
+      }
+      else
+      {
+        this._doc = editor._iframe.contentWindow.document;
+      }
+      doc = this._doc;      
+      if (!doc) { // try later
+        if (HTMLArea.is_gecko) {
+          setTimeout(function() { editor.initIframe()}, 50);
+          return false;
+        } else {
+          alert("ERROR: IFRAME can't be initialized.");
+        }
+      }
+    }
+    catch(e)
+    { // try later
+      setTimeout(function() { editor.initIframe()}, 50);
+    }
+    
+    HTMLArea.freeLater(this, '_doc');
+    
+    doc.open();
+    if (!editor.config.fullPage) {
+      var html = "<html>\n";
+      html += "<head>\n";
+      html += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + editor.config.charSet + "\">\n";
+      if(typeof editor.config.baseHref != 'undefined' && editor.config.baseHref != null)
+      {
+        html += "<base href=\"" + editor.config.baseHref + "\"/>\n";
+      }
+      html += "<style title=\"table borders\">"
+           + ".htmtableborders, .htmtableborders td, .htmtableborders th {border : 1px dashed lightgrey ! important;} \n"
+           + "</style>\n";
+      html += "<style type=\"text/css\">"
+           + "html, body { border: 0px; } \n"
+           + "span.macro, span.macro ul, span.macro div, span.macro p {background : #CCCCCC;}\n"
+           + "</style>\n";
+
+      if(editor.config.pageStyle)
+      {
+        html += "<style type=\"text/css\">\n" + editor.config.pageStyle + "\n</style>";
+      }
+
+      if(typeof editor.config.pageStyleSheets !== 'undefined')
+      {
+        for(style_i = 0; style_i < editor.config.pageStyleSheets.length; style_i++)
+        {
+          if(editor.config.pageStyleSheets[style_i].length > 0)
+              html += "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + editor.config.pageStyleSheets[style_i] + "\">";
+            //html += "<style> @import url('" + editor.config.pageStyleSheets[style_i] + "'); </style>\n";
+        }
+      }
+      html += "</head>\n";
+      html += "<body>\n";
+      html +=   editor.inwardHtml(editor._textArea.value);
+      html += "</body>\n";
+      html += "</html>";
+    } else {
+      var html = editor.inwardHtml(editor._textArea.value);
+      if (html.match(HTMLArea.RE_doctype)) {
+        editor.setDoctype(RegExp.$1);
+        html = html.replace(HTMLArea.RE_doctype, "");
+      }
+    }
+    doc.write(html);
+    doc.close();
+
+    // if we have multiple editors some bug in Mozilla makes some lose editing ability
+    HTMLArea._addEvents
+    (
+      doc,
+      ["mousedown"],
+      function() { editor.activateEditor(); return true; }
+    );
+
+
+    // intercept some events; for updating the toolbar & keyboard handlers
+    HTMLArea._addEvents
+      (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"],
+       function (event) {
+         return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event);
+       });
+
+    // check if any plugins have registered refresh handlers
+    for (var i in editor.plugins) {
+      var plugin = editor.plugins[i].instance;
+      HTMLArea.refreshPlugin(plugin);
+    }
+
+    // specific editor initialization
+    if(typeof editor._onGenerate == "function") {
+      editor._onGenerate();
+    }
+  }
+
+// Switches editor mode; parameter can be "textmode" or "wysiwyg".  If no
+// parameter was passed this function toggles between modes.
+HTMLArea.prototype.setMode = function(mode) {
+  if (typeof mode == "undefined") {
+    mode = ((this._editMode == "textmode") ? "wysiwyg" : "textmode");
+  }
+  switch (mode) {
+    case "textmode":
+    {
+      // -------------------------------------------------------------
+      // PLOG HTMLAREA TWEAK
+      // Added by: Mark Wu
+      // Original by: einSTein
+      // Date: 2005/07/20
+      // Purpose: Add a CR/LF after some HTML Tag, maintain the source format
+      // Come From: http://www.htmlarea.com/forum/htmlArea_3_(beta)_C4/htmlArea_v3.0_-_Bug_Reports_%26_Fixes_F25/Bug_Reports_%26_Fixes_-_Forum_Rules_%2AREAD_THIS%2A_P37586/gforum.cgi?post=22136#22136
+      // -------------------------------------------------------------
+      
+      if (!HTMLArea.is_gecko) {
+        var html = this.outwardHtml(this.getHTML());
+      } else {
+      	var html = insertCRLF(this.getHTML());
+      }
+      // -------------------------------------------------------------
+      
+      this.setHTML(html);
+
+      // Hide the iframe
+      this.deactivateEditor();
+      this._iframe.style.display   = 'none';
+      this._textArea.style.display = '';
+
+      if (this.config.statusBar)
+      {
+        this._statusBarTree.style.display = "none";
+        this._statusBarTextMode.style.display = "";
+      }
+
+      this.notifyOf('modechange', {'mode':'text'});
+      break;
+    }
+
+    case "wysiwyg":
+    {
+      var html = this.inwardHtml(this.getHTML());
+      this.deactivateEditor();
+      this.setHTML(html);
+      this._iframe.style.display   = '';
+      this._textArea.style.display = "none";
+      this.activateEditor();
+      if (this.config.statusBar)
+      {
+        this._statusBarTree.style.display = "";
+        this._statusBarTextMode.style.display = "none";
+      }
+
+      this.notifyOf('modechange', {'mode':'wysiwyg'});
+      break;
+    }
+
+    default:
+    {
+      alert("Mode <" + mode + "> not defined!");
+      return false;
+    }
+  }
+  this._editMode = mode;
+
+  for (var i in this.plugins) {
+    var plugin = this.plugins[i].instance;
+    if (typeof plugin.onMode == "function") plugin.onMode(mode);
+  }
+};
+
+HTMLArea.prototype.setFullHTML = function(html) {
+  var save_multiline = RegExp.multiline;
+  RegExp.multiline = true;
+  if (html.match(HTMLArea.RE_doctype)) {
+    this.setDoctype(RegExp.$1);
+    html = html.replace(HTMLArea.RE_doctype, "");
+  }
+  RegExp.multiline = save_multiline;
+  if (!HTMLArea.is_ie) {
+    if (html.match(HTMLArea.RE_head))
+      this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
+    if (html.match(HTMLArea.RE_body))
+      this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
+  } else {
+    var reac = this.editorIsActivated();
+    if(reac) this.deactivateEditor();
+    var html_re = /<html>((.|\n)*?)<\/html>/i;
+    html = html.replace(html_re, "$1");
+    this._doc.open();
+    this._doc.write(html);
+    this._doc.close();
+    if(reac) this.activateEditor();
+    return true;
+  }
+};
+
+/***************************************************
+ *  Category: PLUGINS
+ ***************************************************/
+
+// Create the specified plugin and register it with this HTMLArea
+// return the plugin created to allow refresh when necessary
+HTMLArea.prototype.registerPlugin = function() {
+  var plugin = arguments[0];
+
+  // We can only register plugins that have been succesfully loaded
+  if
+  (
+    plugin == null
+    || typeof plugin == 'undefined'
+    || (typeof plugin == 'string' && eval('typeof ' + plugin) == 'undefined')
+  ) return false;
+
+  var args = [];
+  for (var i = 1; i < arguments.length; ++i)
+    args.push(arguments[i]);
+  return this.registerPlugin2(plugin, args);
+};
+
+// this is the variant of the function above where the plugin arguments are
+// already packed in an array.  Externally, it should be only used in the
+// full-screen editor code, in order to initialize plugins with the same
+// parameters as in the opener window.
+HTMLArea.prototype.registerPlugin2 = function(plugin, args) {
+  if (typeof plugin == "string")
+    plugin = eval(plugin);
+  if (typeof plugin == "undefined") {
+    /* FIXME: This should never happen. But why does it do? */
+    return false;
+  }
+  var obj = new plugin(this, args);
+  if (obj) {
+    var clone = {};
+    var info = plugin._pluginInfo;
+    for (var i in info)
+      clone[i] = info[i];
+    clone.instance = obj;
+    clone.args = args;
+    this.plugins[plugin._pluginInfo.name] = clone;
+    return obj;
+  } else
+    alert("Can't register plugin " + plugin.toString() + ".");
+};
+
+// static function that loads the required plugin and lang file, based on the
+// language loaded already for HTMLArea.  You better make sure that the plugin
+// _has_ that language, otherwise shit might happen ;-)
+HTMLArea.getPluginDir = function(pluginName) {
+  return _editor_url + "plugins/" + pluginName;
+};
+
+HTMLArea.loadPlugin = function(pluginName, callback) {
+  // Might already be loaded
+  if(eval('typeof ' + pluginName) != 'undefined')
+  {
+    if(callback)
+    {
+      callback(pluginName);
+    }
+    return true;
+  }
+
+  var dir = this.getPluginDir(pluginName);
+  var plugin = pluginName.replace(/([a-z])([A-Z])([a-z])/g,
+          function (str, l1, l2, l3) {
+            return l1 + "-" + l2.toLowerCase() + l3;
+          }).toLowerCase() + ".js";
+  var plugin_file = dir + "/" + plugin;
+
+  if(callback)
+  {
+    HTMLArea._loadback(plugin_file, function() { callback(pluginName); });
+  }
+  else
+  {
+    document.write("<script type='text/javascript' src='" + plugin_file + "'></script>");
+  }
+  return false;
+};
+
+HTMLArea._pluginLoadStatus = { };
+HTMLArea.loadPlugins = function(plugins, callbackIfNotReady)
+{
+  // Rip the ones that are loaded and look for ones that have failed
+  var retVal = true;
+  var nuPlugins = HTMLArea.cloneObject(plugins);
+  while(nuPlugins.length)
+  {
+    var p = nuPlugins.pop();
+    if(typeof HTMLArea._pluginLoadStatus[p] == 'undefined')
+    {
+      // Load it
+      HTMLArea._pluginLoadStatus[p] = 'loading';
+      HTMLArea.loadPlugin(p,
+          function(plugin)
+          {
+            if(eval('typeof ' + plugin) != 'undefined')
+            {
+              HTMLArea._pluginLoadStatus[plugin] = 'ready';
+            }
+            else
+            {
+              // Actually, this won't happen, because if the script fails
+              // it will throw an exception preventing the callback from
+              // running.  This will leave it always in the "loading" state
+              // unfortunatly that means we can't fail plugins gracefully
+              // by just skipping them.
+              HTMLArea._pluginLoadStatus[plugin] = 'failed';
+            }
+          }
+      );
+      retVal = false;
+    }
+    else
+    {
+      switch(HTMLArea._pluginLoadStatus[p])
+      {
+        case 'failed':
+        case 'ready' :
+        break;
+
+        case 'loading':
+        default       :
+         retVal = false;
+         break;
+      }
+    }
+  }
+
+  if(retVal) return true; // All done, just return
+
+  // Waiting on plugins to load, return false now and come back a bit later
+  // if we have to callback
+  if(callbackIfNotReady)
+  {
+    setTimeout(function() { if(HTMLArea.loadPlugins(plugins, callbackIfNotReady)) callbackIfNotReady(); }, 150);
+  }
+  return retVal;
+}
+
+// refresh plugin by calling onGenerate or onGenerateOnce method.
+HTMLArea.refreshPlugin = function(plugin) {
+  if (typeof plugin.onGenerate == "function")
+    plugin.onGenerate();
+  if (typeof plugin.onGenerateOnce == "function") {
+    plugin.onGenerateOnce();
+    plugin.onGenerateOnce = null;
+  }
+};
+
+HTMLArea.loadStyle = function(style, plugin) {
+  var url = _editor_url || '';
+  if (typeof plugin != "undefined") {
+    url += "plugins/" + plugin + "/";
+  }
+  url += style;
+  if (/^\//.test(style))
+    url = style;
+  var head = document.getElementsByTagName("head")[0];
+  var link = document.createElement("link");
+  link.rel = "stylesheet";
+  link.href = url;
+  head.appendChild(link);
+  //document.write("<style type='text/css'>@import url(" + url + ");</style>");
+};
+HTMLArea.loadStyle(typeof _editor_css == "string" ? _editor_css : "htmlarea.css");
+
+/***************************************************
+ *  Category: EDITOR UTILITIES
+ ***************************************************/
+
+HTMLArea.prototype.debugTree = function() {
+  var ta = document.createElement("textarea");
+  ta.style.width = "100%";
+  ta.style.height = "20em";
+  ta.value = "";
+  function debug(indent, str) {
+    for (; --indent >= 0;)
+      ta.value += " ";
+    ta.value += str + "\n";
+  };
+  function _dt(root, level) {
+    var tag = root.tagName.toLowerCase(), i;
+    var ns = HTMLArea.is_ie ? root.scopeName : root.prefix;
+    debug(level, "- " + tag + " [" + ns + "]");
+    for (i = root.firstChild; i; i = i.nextSibling)
+      if (i.nodeType == 1)
+        _dt(i, level + 2);
+  };
+  _dt(this._doc.body, 0);
+  document.body.appendChild(ta);
+};
+
+HTMLArea.getInnerText = function(el) {
+  var txt = '', i;
+  for (i = el.firstChild; i; i = i.nextSibling) {
+    if (i.nodeType == 3)
+      txt += i.data;
+    else if (i.nodeType == 1)
+      txt += HTMLArea.getInnerText(i);
+  }
+  return txt;
+};
+
+HTMLArea.prototype._wordClean = function() {
+  var
+    editor = this,
+    stats = {
+      empty_tags : 0,
+      mso_class  : 0,
+      mso_style  : 0,
+      mso_xmlel  : 0,
+      orig_len   : this._doc.body.innerHTML.length,
+      T          : (new Date()).getTime()
+    },
+    stats_txt = {
+      empty_tags : "Empty tags removed: ",
+      mso_class  : "MSO class names removed: ",
+      mso_style  : "MSO inline style removed: ",
+      mso_xmlel  : "MSO XML elements stripped: "
+    };
+  function showStats() {
+    var txt = "HTMLArea word cleaner stats: \n\n";
+    for (var i in stats)
+      if (stats_txt[i])
+        txt += stats_txt[i] + stats[i] + "\n";
+    txt += "\nInitial document length: " + stats.orig_len + "\n";
+    txt += "Final document length: " + editor._doc.body.innerHTML.length + "\n";
+    txt += "Clean-up took " + (((new Date()).getTime() - stats.T) / 1000) + " seconds";
+    alert(txt);
+  };
+  function clearClass(node) {
+    var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig, ' ');
+    if (newc != node.className) {
+      node.className = newc;
+      if (!/\S/.test(node.className)) {
+        node.removeAttribute("className");
+        ++stats.mso_class;
+      }
+    }
+  };
+  function clearStyle(node) {
+    var declarations = node.style.cssText.split(/\s*;\s*/);
+    for (var i = declarations.length; --i >= 0;)
+      if (/^mso|^tab-stops/i.test(declarations[i]) ||
+          /^margin\s*:\s*0..\s+0..\s+0../i.test(declarations[i])) {
+        ++stats.mso_style;
+        declarations.splice(i, 1);
+      }
+    node.style.cssText = declarations.join("; ");
+  };
+  function stripTag(el) {
+    if (HTMLArea.is_ie)
+      el.outerHTML = HTMLArea.htmlEncode(el.innerText);
+    else {
+      var txt = document.createTextNode(HTMLArea.getInnerText(el));
+      el.parentNode.insertBefore(txt, el);
+      HTMLArea.removeFromParent(el);
+    }
+    ++stats.mso_xmlel;
+  };
+  function checkEmpty(el) {
+    if (/^(a|span|b|strong|i|em|font)$/i.test(el.tagName) &&
+        !el.firstChild) {
+      HTMLArea.removeFromParent(el);
+      ++stats.empty_tags;
+    }
+  };
+  function parseTree(root) {
+    var tag = root.tagName.toLowerCase(), i, next;
+    if ((HTMLArea.is_ie && root.scopeName != 'HTML') || (!HTMLArea.is_ie && /:/.test(tag))) {
+      stripTag(root);
+      return false;
+    } else {
+      clearClass(root);
+      clearStyle(root);
+      for (i = root.firstChild; i; i = next) {
+        next = i.nextSibling;
+        if (i.nodeType == 1 && parseTree(i))
+          checkEmpty(i);
+      }
+    }
+    return true;
+  };
+  parseTree(this._doc.body);
+  // showStats();
+  // this.debugTree();
+  // this.setHTML(this.getHTML());
+  // this.setHTML(this.getInnerHTML());
+  // this.forceRedraw();
+  this.updateToolbar();
+};
+
+HTMLArea.prototype._clearFonts = function() {
+  var D = this.getInnerHTML();
+
+  if(confirm('Would you like to clear font typefaces?'))
+  {
+    D = D.replace(/face="[^"]*"/gi, '');
+    D = D.replace(/font-family:[^;}"']+;?/gi, '');
+  }
+
+  if(confirm('Would you like to clear font sizes?'))
+  {
+    D = D.replace(/size="[^"]*"/gi, '');
+    D = D.replace(/font-size:[^;}"']+;?/gi, '');
+  }
+
+  if(confirm('Would you like to clear font colours?'))
+  {
+    D = D.replace(/color="[^"]*"/gi, '');
+    D = D.replace(/([^-])color:[^;}"']+;?/gi, '$1');
+  }
+
+  D = D.replace(/(style|class)="\s*"/gi, '');
+  D = D.replace(/<(font|span)\s*>/gi, '');
+  this.setHTML(D);
+  this.updateToolbar();
+}
+
+HTMLArea.prototype._splitBlock = function()
+{
+  this._doc.execCommand('formatblock', false, '<div>');
+}
+
+HTMLArea.prototype.forceRedraw = function() {
+  this._doc.body.style.visibility = "hidden";
+  this._doc.body.style.visibility = "visible";
+  // this._doc.body.innerHTML = this.getInnerHTML();
+};
+
+// focuses the iframe window.  returns a reference to the editor document.
+HTMLArea.prototype.focusEditor = function() {
+  switch (this._editMode) {
+      // notice the try { ... } catch block to avoid some rare exceptions in FireFox
+      // (perhaps also in other Gecko browsers). Manual focus by user is required in
+        // case of an error. Somebody has an idea?
+      case "wysiwyg" :
+      try
+      {
+        // We don't want to focus the field unless at least one field has been activated.
+        if(HTMLArea._someEditorHasBeenActivated)
+        {
+          this.activateEditor(); // Ensure *this* editor is activated
+          this._iframe.contentWindow.focus(); // and focus it
+        }
+      } catch (e) {} break;
+      case "textmode": try { this._textArea.focus() } catch (e) {} break;
+      default	   : alert("ERROR: mode " + this._editMode + " is not defined");
+  }
+  return this._doc;
+};
+
+// takes a snapshot of the current text (for undo)
+HTMLArea.prototype._undoTakeSnapshot = function() {
+  ++this._undoPos;
+  if (this._undoPos >= this.config.undoSteps) {
+    // remove the first element
+    this._undoQueue.shift();
+    --this._undoPos;
+  }
+  // use the fasted method (getInnerHTML);
+  var take = true;
+  var txt = this.getInnerHTML();
+  if (this._undoPos > 0)
+    take = (this._undoQueue[this._undoPos - 1] != txt);
+  if (take) {
+    this._undoQueue[this._undoPos] = txt;
+  } else {
+    this._undoPos--;
+  }
+};
+
+HTMLArea.prototype.undo = function() {
+  if (this._undoPos > 0) {
+    var txt = this._undoQueue[--this._undoPos];
+    if (txt) this.setHTML(txt);
+    else ++this._undoPos;
+  }
+};
+
+HTMLArea.prototype.redo = function() {
+  if (this._undoPos < this._undoQueue.length - 1) {
+    var txt = this._undoQueue[++this._undoPos];
+    if (txt) this.setHTML(txt);
+    else --this._undoPos;
+  }
+};
+
+HTMLArea.prototype.disableToolbar = function(except)
+{
+  if(this._timerToolbar) clearTimeout(this._timerToolbar);
+  if(typeof except == 'undefined')
+  {
+    except = [ ];
+  }
+  else if(typeof except != 'object')
+  {
+    except = [except];
+  }
+
+  for (var i in this._toolbarObjects)
+  {
+    var btn = this._toolbarObjects[i];
+    if(except.contains(i))
+    {
+      continue;
+    }
+    btn.state("enabled", false);
+  }
+}
+
+HTMLArea.prototype.enableToolbar = function()
+{
+  this.updateToolbar();
+}
+
+if(!Array.prototype.contains)
+{
+  Array.prototype.contains = function(needle)
+  {
+   var haystack = this;
+   for(var i = 0; i < haystack.length; i++)
+    {
+      if(needle == haystack[i]) return true;
+    }
+
+    return false;
+  }
+}
+
+if(!Array.prototype.indexOf)
+{
+  Array.prototype.indexOf = function(needle)
+  {
+    var haystack = this;
+    for(var i = 0; i < haystack.length; i++)
+    {
+      if(needle == haystack[i]) return i;
+    }
+
+    return null;
+  }
+}
+
+
+// updates enabled/disable/active state of the toolbar elements
+HTMLArea.prototype.updateToolbar = function(noStatus) {
+  var doc = this._doc;
+  var text = (this._editMode == "textmode");
+  var ancestors = null;
+  if (!text) {
+    ancestors = this.getAllAncestors();
+    if (this.config.statusBar && !noStatus) {
+      this._statusBarTree.innerHTML = HTMLArea._lc("Path") + ": "; // clear
+      for (var i = ancestors.length; --i >= 0;) {
+        var el = ancestors[i];
+        if (!el) {
+          // hell knows why we get here; this
+          // could be a classic example of why
+          // it's good to check for conditions
+          // that are impossible to happen ;-)
+          continue;
+        }
+        var a = document.createElement("a");
+        a.href = "javascript:void(0)";
+        a.el = el;
+        a.editor = this;
+        HTMLArea.addDom0Event(a, 'click', function() {
+          this.blur();
+          this.editor.selectNodeContents(this.el);
+          this.editor.updateToolbar(true);
+          return false;
+        });
+        HTMLArea.addDom0Event(a, 'contextmenu',  function() {
+          // TODO: add context menu here
+          this.blur();
+          var info = "Inline style:\n\n";
+          info += this.el.style.cssText.split(/;\s*/).join(";\n");
+          alert(info);
+          return false;
+        });
+        var txt = el.tagName.toLowerCase();
+        a.title = el.style.cssText;
+        if (el.id) {
+          txt += "#" + el.id;
+        }
+        if (el.className) {
+          txt += "." + el.className;
+        }
+        a.appendChild(document.createTextNode(txt));
+        this._statusBarTree.appendChild(a);
+        if (i != 0) {
+          this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(0xbb)));
+        }
+      }
+    }
+  }
+
+  for (var i in this._toolbarObjects) {
+    var btn = this._toolbarObjects[i];
+    var cmd = i;
+    var inContext = true;
+    if (btn.context && !text) {
+      inContext = false;
+      var context = btn.context;
+      var attrs = [];
+      if (/(.*)\[(.*?)\]/.test(context)) {
+        context = RegExp.$1;
+        attrs = RegExp.$2.split(",");
+      }
+      context = context.toLowerCase();
+      var match = (context == "*");
+      for (var k = 0; k < ancestors.length; ++k) {
+        if (!ancestors[k]) {
+          // the impossible really happens.
+          continue;
+        }
+        if (match || (ancestors[k].tagName.toLowerCase() == context)) {
+          inContext = true;
+          for (var ka = 0; ka < attrs.length; ++ka) {
+            if (!eval("ancestors[k]." + attrs[ka])) {
+              inContext = false;
+              break;
+            }
+          }
+          if (inContext) {
+            break;
+          }
+        }
+      }
+    }
+    btn.state("enabled", (!text || btn.text) && inContext);
+    if (typeof cmd == "function") {
+      continue;
+    }
+    // look-it-up in the custom dropdown boxes
+    var dropdown = this.config.customSelects[cmd];
+    if ((!text || btn.text) && (typeof dropdown != "undefined")) {
+      dropdown.refresh(this);
+      continue;
+    }
+    switch (cmd)
+    {
+        case "fontname":
+        case "fontsize":
+      {
+      if (!text) try {
+        var value = ("" + doc.queryCommandValue(cmd)).toLowerCase();
+        if (!value) {
+          btn.element.selectedIndex = 0;
+          break;
+        }
+
+        // HACK -- retrieve the config option for this
+        // combo box.  We rely on the fact that the
+        // variable in config has the same name as
+        // button name in the toolbar.
+        var options = this.config[cmd];
+        var k = 0;
+          for (var j in options)
+          {
+          // FIXME: the following line is scary.
+            if ((j.toLowerCase() == value) || (options[j].substr(0, value.length).toLowerCase() == value))
+            {
+            btn.element.selectedIndex = k;
+            throw "ok";
+          }
+          ++k;
+        }
+        btn.element.selectedIndex = 0;
+      } catch(e) {};
+      }
+      break;
+
+      // It's better to search for the format block by tag name from the
+      //  current selection upwards, because IE has a tendancy to return
+      //  things like 'heading 1' for 'h1', which breaks things if you want
+      //  to call your heading blocks 'header 1'.  Stupid MS.
+      case "formatblock"  :
+      {
+        var blocks = [ ];
+        for(var i in this.config['formatblock'])
+        {
+          blocks[blocks.length] = this.config['formatblock'][i];
+        }
+
+        var deepestAncestor = this._getFirstAncestor(this._getSelection(), blocks);
+        if(deepestAncestor)
+        {
+          for(var x= 0; x < blocks.length; x++)
+          {
+            if(blocks[x].toLowerCase() == deepestAncestor.tagName.toLowerCase())
+            {
+              btn.element.selectedIndex = x;
+            }
+          }
+        }
+        else
+        {
+          btn.element.selectedIndex = 0;
+        }
+      }
+        break;
+
+        case "textindicator":
+      if (!text) {
+        try {with (btn.element.style) {
+          backgroundColor = HTMLArea._makeColor(
+            doc.queryCommandValue(HTMLArea.is_ie ? "backcolor" : "hilitecolor"));
+          if (/transparent/i.test(backgroundColor)) {
+            // Mozilla
+            backgroundColor = HTMLArea._makeColor(doc.queryCommandValue("backcolor"));
+          }
+          color = HTMLArea._makeColor(doc.queryCommandValue("forecolor"));
+          fontFamily = doc.queryCommandValue("fontname");
+          fontWeight = doc.queryCommandState("bold") ? "bold" : "normal";
+          fontStyle = doc.queryCommandState("italic") ? "italic" : "normal";
+        }} catch (e) {
+          // alert(e + "\n\n" + cmd);
+        }
+      }
+      break;
+        case "htmlmode": btn.state("active", text); break;
+        case "lefttoright":
+        case "righttoleft":
+      var el = this.getParentElement();
+      while (el && !HTMLArea.isBlockElement(el))
+        el = el.parentNode;
+      if (el)
+        btn.state("active", (el.style.direction == ((cmd == "righttoleft") ? "rtl" : "ltr")));
+      break;
+        default:
+      cmd = cmd.replace(/(un)?orderedlist/i, "insert$1orderedlist");
+      try {
+        btn.state("active", (!text && doc.queryCommandState(cmd)));
+      } catch (e) {}
+    }
+  }
+  // take undo snapshots
+  if (this._customUndo && !this._timerUndo) {
+    this._undoTakeSnapshot();
+    var editor = this;
+    this._timerUndo = setTimeout(function() {
+      editor._timerUndo = null;
+    }, this.config.undoTimeout);
+  }
+
+  // Insert a space in certain locations, this is just to make editing a little
+  // easier (to "get out of" tags), it's not essential.
+  // TODO: Make this work for IE?
+  // TODO: Perhaps should use a plain space character, I'm not sure.
+  //  OK, I've disabled this temporarily, to be honest, I can't rightly remember what the
+  //  original problem was I was trying to solve with it.  I think perhaps that EnterParagraphs
+  //  might solve the problem, whatever the hell it was.  I'm going senile, I'm sure.
+  if(0 && HTMLArea.is_gecko)
+  {
+    var s = this._getSelection();
+    // If the last character in the last text node of the parent tag
+    // and the parent tag is not a block tag
+    if(s && s.isCollapsed && s.anchorNode
+         && s.anchorNode.parentNode.tagName.toLowerCase() != 'body'
+         && s.anchorNode.nodeType == 3 && s.anchorOffset == s.anchorNode.length
+         && !
+          (   s.anchorNode.parentNode.nextSibling
+           && s.anchorNode.parentNode.nextSibling.nodeType == 3
+          )
+         && !HTMLArea.isBlockElement(s.anchorNode.parentNode)
+      )
+    {
+      // Insert hair-width-space after the close tag if there isn't another text node on the other side
+      // It could also work with zero-width-space (\u200B) but I don't like it so much.
+      // Perhaps this won't work well in various character sets and we should use plain space (20)?
+      try
+      {
+        s.anchorNode.parentNode.parentNode.insertBefore
+          (this._doc.createTextNode('\t'), s.anchorNode.parentNode.nextSibling);
+      }
+      catch(e)
+      {
+        // Disregard
+      }
+    }
+  }
+
+  // check if any plugins have registered refresh handlers
+  for (var i in this.plugins) {
+    var plugin = this.plugins[i].instance;
+    if (typeof plugin.onUpdateToolbar == "function")
+      plugin.onUpdateToolbar();
+  }
+
+
+}
+
+/** Returns a node after which we can insert other nodes, in the current
+ * selection.  The selection is removed.  It splits a text node, if needed.
+ */
+HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
+  if (!HTMLArea.is_ie) {
+    var sel = this._getSelection();
+    var range = this._createRange(sel);
+    // remove the current selection
+    sel.removeAllRanges();
+    range.deleteContents();
+    var node = range.startContainer;
+    var pos = range.startOffset;
+    switch (node.nodeType) {
+        case 3: // Node.TEXT_NODE
+      // we have to split it at the caret position.
+      if (toBeInserted.nodeType == 3) {
+        // do optimized insertion
+        node.insertData(pos, toBeInserted.data);
+        range = this._createRange();
+        range.setEnd(node, pos + toBeInserted.length);
+        range.setStart(node, pos + toBeInserted.length);
+        sel.addRange(range);
+      } else {
+        node = node.splitText(pos);
+        var selnode = toBeInserted;
+        if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
+          selnode = selnode.firstChild;
+        }
+        node.parentNode.insertBefore(toBeInserted, node);
+        this.selectNodeContents(selnode);
+        this.updateToolbar();
+      }
+      break;
+        case 1: // Node.ELEMENT_NODE
+      var selnode = toBeInserted;
+      if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
+        selnode = selnode.firstChild;
+      }
+      node.insertBefore(toBeInserted, node.childNodes[pos]);
+      this.selectNodeContents(selnode);
+      this.updateToolbar();
+      break;
+    }
+  } else {
+    return null;	// this function not yet used for IE <FIXME>
+  }
+};
+
+// Returns the deepest node that contains both endpoints of the selection.
+HTMLArea.prototype.getParentElement = function(sel) {
+  if(typeof sel == 'undefined')
+  {
+    sel = this._getSelection();
+  }
+  var range = this._createRange(sel);
+  if (HTMLArea.is_ie) {
+    switch (sel.type) {
+        case "Text":
+        case "None":
+      // It seems that even for selection of type "None",
+      // there _is_ a parent element and it's value is not
+      // only correct, but very important to us.  MSIE is
+      // certainly the buggiest browser in the world and I
+      // wonder, God, how can Earth stand it?
+      return range.parentElement();
+        case "Control":
+      return range.item(0);
+        default:
+      return this._doc.body;
+    }
+  } else try {
+    var p = range.commonAncestorContainer;
+    if (!range.collapsed && range.startContainer == range.endContainer &&
+        range.startOffset - range.endOffset <= 1 && range.startContainer.hasChildNodes())
+      p = range.startContainer.childNodes[range.startOffset];
+    /*
+    alert(range.startContainer + ":" + range.startOffset + "\n" +
+          range.endContainer + ":" + range.endOffset);
+    */
+    while (p.nodeType == 3) {
+      p = p.parentNode;
+    }
+    return p;
+  } catch (e) {
+    return null;
+  }
+};
+
+// Returns an array with all the ancestor nodes of the selection.
+HTMLArea.prototype.getAllAncestors = function() {
+  var p = this.getParentElement();
+  var a = [];
+  while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
+    a.push(p);
+    p = p.parentNode;
+  }
+  a.push(this._doc.body);
+  return a;
+};
+
+// Returns the deepest ancestor of the selection that is of the current type
+HTMLArea.prototype._getFirstAncestor = function(sel, types)
+{
+  var prnt = this._activeElement(sel);
+  if(prnt == null)
+  {
+    try
+    {
+      prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
+    }
+    catch(e)
+    {
+      return null;
+    }
+  }
+
+  if(typeof types == 'string')
+  {
+    types = [types];
+  }
+
+  while(prnt)
+  {
+    if(prnt.nodeType == 1)
+    {
+      if(types == null) return prnt;
+      if(types.contains(prnt.tagName.toLowerCase()))
+      {
+
+        return prnt;
+      }
+      if(prnt.tagName.toLowerCase() == 'body') break;
+      if(prnt.tagName.toLowerCase() == 'table') break;
+    }
+    prnt = prnt.parentNode;
+  }
+
+  return null;
+}
+
+/**
+ * Returns the selected element, if any.  That is,
+ * the element that you have last selected in the "path"
+ * at the bottom of the editor, or a "control" (eg image)
+ *
+ * @returns null | element
+ */
+HTMLArea.prototype._activeElement = function(sel)
+{
+  if(sel == null) return null;
+  if(this._selectionEmpty(sel)) return null;
+
+  if(HTMLArea.is_ie)
+  {
+    if(sel.type.toLowerCase() == "control")
+    {
+      return sel.createRange().item(0);
+    }
+    else
+    {
+
+      // If it's not a control, then we need to see if
+      // the selection is the _entire_ text of a parent node
+      // (this happens when a node is clicked in the tree)
+      var range = sel.createRange();
+      var p_elm = this.getParentElement(sel);
+      if(p_elm.innerHTML == range.htmlText)
+      {
+        return p_elm;
+      }
+      /*
+      if(p_elm)
+      {
+        var p_rng = this._doc.body.createTextRange();
+        p_rng.moveToElementText(p_elm);
+        if(p_rng.isEqual(range))
+        {
+          return p_elm;
+        }
+      }
+
+      if(range.parentElement())
+      {
+        var prnt_range = this._doc.body.createTextRange();
+        prnt_range.moveToElementText(range.parentElement());
+        if(prnt_range.isEqual(range))
+        {
+          return range.parentElement();
+        }
+      }
+      */
+      return null;
+    }
+  }
+  else
+  {
+    // For Mozilla we just see if the selection is not collapsed (something is selected)
+    // and that the anchor (start of selection) is an element.  This might not be totally
+    // correct, we possibly should do a simlar check to IE?
+    if(! sel.isCollapsed)
+    {
+      if(sel.anchorNode.childNodes.length > sel.anchorOffset && sel.anchorNode.childNodes[sel.anchorOffset].nodeType == 1)
+      {
+        return sel.anchorNode.childNodes[sel.anchorOffset];
+      }
+      else if(sel.anchorNode.nodeType == 1)
+      {
+        return sel.anchorNode;
+      }
+      else
+      {
+        return sel.anchorNode.parentNode;
+      }
+    }
+    return null;
+  }
+}
+
+
+HTMLArea.prototype._selectionEmpty = function(sel)
+{
+  if(!sel) return true;
+
+  if(HTMLArea.is_ie)
+  {
+    return this._createRange(sel).htmlText == '';
+  }
+  else if(typeof sel.isCollapsed != 'undefined')
+  {
+    return sel.isCollapsed;
+  }
+
+  return true;
+}
+
+HTMLArea.prototype._getAncestorBlock = function(sel)
+{
+  // Scan upwards to find a block level element that we can change or apply to
+  var prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement : this._createRange(sel).commonAncestorContainer);
+
+  while(prnt && (prnt.nodeType == 1))
+  {
+    switch(prnt.tagName.toLowerCase())
+    {
+      case 'div' :
+      case 'p'   :
+      case 'address'    :
+      case 'blockquote' :
+      case 'center'  :
+      case 'del'     :
+      case 'ins'     :
+      case 'pre'     :
+      case 'h1'      :
+      case 'h2'      :
+      case 'h3'      :
+      case 'h4'      :
+      case 'h5'      :
+      case 'h6'      :
+      case 'h7'      :
+        // Block Element
+        return prnt;
+
+      case 'body'     :
+      case 'noframes' :
+      case 'dd'  :
+      case 'li'  :
+      case 'th'  :
+      case 'td'  :
+      case 'noscript' :
+        // Halting element (stop searching)
+        return null;
+
+      default :
+        // Keep lookin
+        break;
+    }
+  }
+
+  return null;
+}
+
+HTMLArea.prototype._createImplicitBlock = function(type)
+{
+  // expand it until we reach a block element in either direction
+  // then wrap the selection in a block and return
+  var sel = this._getSelection();
+  if(HTMLArea.is_ie)
+  {
+    sel.empty();
+  }
+  else
+  {
+    sel.collapseToStart();
+  }
+
+  var rng = this._createRange(sel);
+
+  // Expand UP
+
+  // Expand DN
+}
+
+HTMLArea.prototype._formatBlock = function(block_format)
+{
+  var ancestors = this.getAllAncestors();
+  var apply_to = null;
+
+  // Block format can be a tag followed with class defs
+  //  eg div.blue.left
+  var target_tag = null;
+  var target_classNames = [ ];
+
+  if(block_format.indexOf('.') >= 0)
+  {
+    target_tag = block_format.substr(0, block_format.indexOf('.')).toLowerCase();;
+
+    target_classNames = block_format.substr(block_format.indexOf('.'), block_format.length - block_format.indexOf('.')).replace(/\./g, '').replace(/^\s*/, '').replace(/\s*$/, '').split(' ');
+  }
+  else
+  {
+    target_tag = block_format.toLowerCase();
+  }
+
+  var sel = this._getSelection();
+  var rng = this._createRange(sel);
+  var apply_to = null;
+
+  if(HTMLArea.is_gecko)
+  {
+    if(sel.isCollapsed)
+    {
+      // With no selection we want to apply to the whole contents of the ancestor block
+      apply_to = this._getAncestorBlock(sel);
+      if(apply_to == null)
+      {
+        // If there wasn't an ancestor, make one.
+        apply_to = this._createImplicitBlock(sel, target_tag);
+      }
+    }
+    else
+    {
+      // With a selection it's more tricky
+      switch(target_tag)
+      {
+
+        case 'h1'      :
+        case 'h2'      :
+        case 'h3'      :
+        case 'h4'      :
+        case 'h5'      :
+        case 'h6'      :
+        case 'h7'      :
+          apply_to = [ ];
+          var search_tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7'];
+          for(var y = 0; y < search_tags.length; y++)
+          {
+            var headers = this._doc.getElementsByTagName(search_tag[y]);
+            for(var x = 0; x < headers.length; x++)
+            {
+              if(sel.containsNode(headers[x]))
+              {
+                apply_to[apply_to.length] = headers[x];
+              }
+            }
+          }
+          if(apply_to.length > 0) break;
+          // If there wern't any in the selection drop through
+        case 'div' :
+          apply_to = this._doc.createElement(target_tag);
+          apply_to.appendChild(rng.extractContents());
+          rng.insertNode(apply_to);
+          break;
+
+        case 'p'   :
+        case 'center'  :
+        case 'pre' :
+        case 'ins' :
+        case 'del' :
+        case 'blockquote' :
+        case 'address'    :
+          apply_to = [ ];
+          var paras = this._doc.getElementsByTagName(target_tag);
+          for(var x = 0; x < paras.length; x++)
+          {
+            if(sel.containsNode(paras[x]))
+            {
+              apply_to[apply_to.length] = paras[x];
+            }
+          }
+
+          if(apply_to.length == 0)
+          {
+            sel.collapseToStart();
+            return this._formatBlock(block_format);
+          }
+          break;
+      }
+    }
+  }
+
+}
+
+// Selects the contents inside the given node
+HTMLArea.prototype.selectNodeContents = function(node, pos) {
+  this.focusEditor();
+  this.forceRedraw();
+  var range;
+  var collapsed = typeof pos == "undefined" ? true : false;
+  if (HTMLArea.is_ie) {
+    // Tables and Images get selected as "objects" rather than the text contents
+    if(collapsed && node.tagName && node.tagName.toLowerCase().match(/table|img|input|select|textarea/))
+    {
+      range = this._doc.body.createControlRange();
+      range.add(node);
+    }
+    else
+    {
+      range = this._doc.body.createTextRange();
+      range.moveToElementText(node);
+      //(collapsed) && range.collapse(pos);
+    }
+    range.select();
+  } else {
+    var sel = this._getSelection();
+    range = this._doc.createRange();
+    // Tables and Images get selected as "objects" rather than the text contents
+    if(collapsed && node.tagName && node.tagName.toLowerCase().match(/table|img|input|textarea|select/))
+    {
+      range.selectNode(node);
+    }
+    else
+    {
+      range.selectNodeContents(node);
+      //(collapsed) && range.collapse(pos);
+    }
+    sel.removeAllRanges();
+    sel.addRange(range);
+  }
+};
+
+/** Call this function to insert HTML code at the current position.  It deletes
+ * the selection, if any.
+ */
+HTMLArea.prototype.insertHTML = function(html) {
+  var sel = this._getSelection();
+  var range = this._createRange(sel);
+  if (HTMLArea.is_ie) {
+    range.pasteHTML(html);
+  } else {
+    // construct a new document fragment with the given HTML
+    var fragment = this._doc.createDocumentFragment();
+    var div = this._doc.createElement("div");
+    div.innerHTML = html;
+    while (div.firstChild) {
+      // the following call also removes the node from div
+      fragment.appendChild(div.firstChild);
+    }
+    // this also removes the selection
+    var node = this.insertNodeAtSelection(fragment);
+  }
+};
+
+/**
+ *  Call this function to surround the existing HTML code in the selection with
+ *  your tags.  FIXME: buggy!  This function will be deprecated "soon".
+ */
+HTMLArea.prototype.surroundHTML = function(startTag, endTag) {
+  var html = this.getSelectedHTML();
+  // the following also deletes the selection
+  this.insertHTML(startTag + html + endTag);
+};
+
+/// Retrieve the selected block
+HTMLArea.prototype.getSelectedHTML = function() {
+  var sel = this._getSelection();
+  var range = this._createRange(sel);
+  var existing = null;
+  if (HTMLArea.is_ie) {
+    existing = range.htmlText;
+  } else {
+    existing = HTMLArea.getHTML(range.cloneContents(), false, this);
+  }
+  return existing;
+};
+
+/// Return true if we have some selection
+HTMLArea.prototype.hasSelectedText = function() {
+  // FIXME: come _on_ mishoo, you can do better than this ;-)
+  return this.getSelectedHTML() != '';
+};
+
+HTMLArea.prototype._createLink = function(link) {
+  var editor = this;
+  var outparam = null;
+  if (typeof link == "undefined") {
+    link = this.getParentElement();
+    if (link) {
+      if (/^img$/i.test(link.tagName))
+        link = link.parentNode;
+      if (!/^a$/i.test(link.tagName))
+        link = null;
+    }
+  }
+  if (!link) {
+    var sel = editor._getSelection();
+    var range = editor._createRange(sel);
+    var compare = 0;
+    if (HTMLArea.is_ie) {
+      if(sel.type == "Control")
+      {
+        compare = range.length;
+      }
+      else
+      {
+        compare = range.compareEndPoints("StartToEnd", range);
+      }
+    } else {
+      compare = range.compareBoundaryPoints(range.START_TO_END, range);
+    }
+    if (compare == 0) {
+      alert(HTMLArea._lc("You need to select some text before creating a link"));
+      return;
+    }
+    outparam = {
+      f_href : '',
+      f_title : '',
+      f_target : '',
+      f_usetarget : editor.config.makeLinkShowsTarget
+    };
+  } else
+    outparam = {
+      f_href   : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"),
+      f_title  : link.title,
+      f_target : link.target,
+      f_usetarget : editor.config.makeLinkShowsTarget
+    };
+  this._popupDialog(editor.config.URIs["link"], function(param) {
+    if (!param)
+      return false;
+    var a = link;
+    if (!a) try {
+      editor._doc.execCommand("createlink", false, param.f_href);
+      a = editor.getParentElement();
+      var sel = editor._getSelection();
+      var range = editor._createRange(sel);
+      if (!HTMLArea.is_ie) {
+        a = range.startContainer;
+        if (!/^a$/i.test(a.tagName)) {
+          a = a.nextSibling;
+          if (a == null)
+            a = range.startContainer.parentNode;
+        }
+      }
+    } catch(e) {}
+    else {
+      var href = param.f_href.trim();
+      editor.selectNodeContents(a);
+      if (href == "") {
+        editor._doc.execCommand("unlink", false, null);
+        editor.updateToolbar();
+        return false;
+      }
+      else {
+        a.href = href;
+      }
+    }
+    if (!(a && /^a$/i.test(a.tagName)))
+      return false;
+    a.target = param.f_target.trim();
+    a.title = param.f_title.trim();
+    editor.selectNodeContents(a);
+    editor.updateToolbar();
+  }, outparam);
+};
+
+// Called when the user clicks on "InsertImage" button.  If an image is already
+// there, it will just modify it's properties.
+HTMLArea.prototype._insertImage = function(image) {
+  var editor = this;	// for nested functions
+  var outparam = null;
+  if (typeof image == "undefined") {
+    image = this.getParentElement();
+    if (image && !/^img$/i.test(image.tagName))
+      image = null;
+  }
+  if (image) outparam = {
+    f_base   : editor.config.baseHref,
+    f_url    : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image.getAttribute("src"),
+    f_alt    : image.alt,
+    f_border : image.border,
+    f_align  : image.align,
+    f_vert   : image.vspace,
+    f_horiz  : image.hspace
+  };
+  this._popupDialog(editor.config.URIs["insert_image"], function(param) {
+    if (!param) {	// user must have pressed Cancel
+      return false;
+    }
+    var img = image;
+    if (!img) {
+      var sel = editor._getSelection();
+      var range = editor._createRange(sel);
+      editor._doc.execCommand("insertimage", false, param.f_url);
+      if (HTMLArea.is_ie) {
+        img = range.parentElement();
+        // wonder if this works...
+        if (img.tagName.toLowerCase() != "img") {
+          img = img.previousSibling;
+        }
+      } else {
+        img = range.startContainer.previousSibling;
+        if (!img.tagName) {
+          // if the cursor is at the beginning of the document
+          img = range.startContainer.firstChild;
+        }
+      }
+    } else {
+      img.src = param.f_url;
+    }
+
+    for (var field in param) {
+      var value = param[field];
+      switch (field) {
+          case "f_alt"    : img.alt	 = value; break;
+          case "f_border" : img.border = parseInt(value || "0"); break;
+          case "f_align"  : img.align	 = value; break;
+          case "f_vert"   : img.vspace = parseInt(value || "0"); break;
+          case "f_horiz"  : img.hspace = parseInt(value || "0"); break;
+      }
+    }
+  }, outparam);
+};
+
+// Called when the user clicks the Insert Table button
+HTMLArea.prototype._insertTable = function() {
+  var sel = this._getSelection();
+  var range = this._createRange(sel);
+  var editor = this;	// for nested functions
+  this._popupDialog(editor.config.URIs["insert_table"], function(param) {
+    if (!param) {	// user must have pressed Cancel
+      return false;
+    }
+    var doc = editor._doc;
+    // create the table element
+    var table = doc.createElement("table");
+    // assign the given arguments
+
+    for (var field in param) {
+      var value = param[field];
+      if (!value) {
+        continue;
+      }
+      switch (field) {
+          case "f_width"   : table.style.width = value + param["f_unit"]; break;
+          case "f_align"   : table.align	 = value; break;
+          case "f_border"  : table.border	 = parseInt(value); break;
+          case "f_spacing" : table.cellSpacing = parseInt(value); break;
+          case "f_padding" : table.cellPadding = parseInt(value); break;
+      }
+    }
+    var cellwidth = 0;
+    if (param.f_fixed)
+      cellwidth = Math.floor(100 / parseInt(param.f_cols));
+    var tbody = doc.createElement("tbody");
+    table.appendChild(tbody);
+    for (var i = 0; i < param["f_rows"]; ++i) {
+      var tr = doc.createElement("tr");
+      tbody.appendChild(tr);
+      for (var j = 0; j < param["f_cols"]; ++j) {
+        var td = doc.createElement("td");
+        if (cellwidth)
+          td.style.width = cellwidth + "%";
+        tr.appendChild(td);
+        // Mozilla likes to see something inside the cell.
+        (HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
+      }
+    }
+    if (HTMLArea.is_ie) {
+      range.pasteHTML(table.outerHTML);
+    } else {
+      // insert the table
+      editor.insertNodeAtSelection(table);
+    }
+    return true;
+  }, null);
+};
+
+/***************************************************
+ *  Category: EVENT HANDLERS
+ ***************************************************/
+
+// el is reference to the SELECT object
+// txt is the name of the select field, as in config.toolbar
+HTMLArea.prototype._comboSelected = function(el, txt) {
+  this.focusEditor();
+  var value = el.options[el.selectedIndex].value;
+  switch (txt) {
+      case "fontname":
+      case "fontsize": this.execCommand(txt, false, value); break;
+      case "formatblock":
+    // (HTMLArea.is_ie) && (value = "<" + value + ">");
+    value = "<" + value + ">"
+    this.execCommand(txt, false, value);
+    break;
+      default:
+    // try to look it up in the registered dropdowns
+    var dropdown = this.config.customSelects[txt];
+    if (typeof dropdown != "undefined") {
+      dropdown.action(this);
+    } else {
+      alert("FIXME: combo box " + txt + " not implemented");
+    }
+  }
+};
+
+// the execCommand function (intercepts some commands and replaces them with
+// our own implementation)
+HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
+  var editor = this;	// for nested functions
+  this.focusEditor();
+  cmdID = cmdID.toLowerCase();
+  if (HTMLArea.is_gecko) try { this._doc.execCommand('useCSS', false, true); } catch (e) {}; //switch useCSS off (true=off)
+  switch (cmdID) {
+    case "htmlmode" : this.setMode(); break;
+    case "hilitecolor":
+      (HTMLArea.is_ie) && (cmdID = "backcolor");
+      if (HTMLArea.is_gecko) try { editor._doc.execCommand('useCSS', false, false); } catch (e) {};//switch on useCSS (mozilla bug #279330)
+    case "forecolor":
+      this._popupDialog(editor.config.URIs["select_color"], function(color) {
+        if (color) { // selection not canceled
+          editor._doc.execCommand(cmdID, false, "#" + color);
+        }
+      }, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)));
+      break;
+    case "createlink":
+      this._createLink();
+      break;
+      case "undo":
+      case "redo":
+    if (this._customUndo)
+      this[cmdID]();
+    else
+      this._doc.execCommand(cmdID, UI, param);
+    break;
+      case "inserttable": this._insertTable(); break;
+      case "insertimage": this._insertImage(); break;
+      case "about"    : this._popupDialog(editor.config.URIs["about"], null, this); break;
+      case "showhelp" : window.open(this.config.helpURL, "ha_help"); break;
+
+      case "killword": this._wordClean(); break;
+
+      case "cut":
+      case "copy":
+      case "paste":
+    try {
+      this._doc.execCommand(cmdID, UI, param);
+      if (this.config.killWordOnPaste)
+        this._wordClean();
+    } catch (e) {
+      if (HTMLArea.is_gecko) {
+        alert(HTMLArea._lc("The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly."));
+      }
+    }
+    break;
+      case "lefttoright":
+      case "righttoleft":
+    var dir = (cmdID == "righttoleft") ? "rtl" : "ltr";
+    var el = this.getParentElement();
+    while (el && !HTMLArea.isBlockElement(el))
+      el = el.parentNode;
+    if (el) {
+      if (el.style.direction == dir)
+        el.style.direction = "";
+      else
+        el.style.direction = dir;
+    }
+    break;
+      default: try { this._doc.execCommand(cmdID, UI, param); }
+    catch(e) { if (this.config.debug) { alert(e + "\n\nby execCommand(" + cmdID + ");"); } }
+  }
+
+  this.updateToolbar();
+  return false;
+};
+
+/** A generic event handler for things that happen in the IFRAME's document.
+ * This function also handles key bindings. */
+HTMLArea.prototype._editorEvent = function(ev) {
+  var editor = this;
+  var keyEvent = (HTMLArea.is_ie && ev.type == "keydown") || (!HTMLArea.is_ie && ev.type == "keypress");
+
+  //call events of textarea
+  if(typeof editor._textArea['on'+ev.type] == "function") {
+    editor._textArea['on'+ev.type]();
+  }
+
+  if(HTMLArea.is_gecko && keyEvent && ev.ctrlKey &&  this._unLink && this._unlinkOnUndo)
+  {
+    if(String.fromCharCode(ev.charCode).toLowerCase() == 'z')
+    {
+      HTMLArea._stopEvent(ev);
+      this._unLink();
+      editor.updateToolbar();
+      return;
+    }
+  }
+
+  if (keyEvent)
+  {
+    for (var i in editor.plugins)
+    {
+      var plugin = editor.plugins[i].instance;
+      if (typeof plugin.onKeyPress == "function")
+        if (plugin.onKeyPress(ev))
+          return false;
+    }
+  }
+
+  if (keyEvent && ev.ctrlKey && !ev.altKey)
+  {
+    var sel = null;
+    var range = null;
+    var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
+    var cmd = null;
+    var value = null;
+    switch (key) {
+        case 'a':
+      if (!HTMLArea.is_ie) {
+        // KEY select all
+        sel = this._getSelection();
+        sel.removeAllRanges();
+        range = this._createRange();
+        range.selectNodeContents(this._doc.body);
+        sel.addRange(range);
+        HTMLArea._stopEvent(ev);
+      }
+      break;
+
+      // simple key commands follow
+
+        case 'b': cmd = "bold"; break;
+        case 'i': cmd = "italic"; break;
+        case 'u': cmd = "underline"; break;
+        case 's': cmd = "strikethrough"; break;
+        case 'l': cmd = "justifyleft"; break;
+        case 'e': cmd = "justifycenter"; break;
+        case 'r': cmd = "justifyright"; break;
+        case 'j': cmd = "justifyfull"; break;
+        case 'z': cmd = "undo"; break;
+        case 'y': cmd = "redo"; break;
+        case 'v': if (HTMLArea.is_ie || editor.config.htmlareaPaste) { cmd = "paste"; } break;
+        case 'n': cmd = "formatblock"; value = HTMLArea.is_ie ? "<p>" : "p"; break;
+
+        case '0': cmd = "killword"; break;
+
+      // headings
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+      cmd = "formatblock";
+      value = "h" + key;
+      if (HTMLArea.is_ie)
+        value = "<" + value + ">";
+      break;
+    }
+    if (cmd) {
+      // execute simple command
+      this.execCommand(cmd, false, value);
+      HTMLArea._stopEvent(ev);
+    }
+  }
+  else if (keyEvent)
+  {
+
+    // IE's textRange and selection object is woefully inadequate,
+    // which means this fancy stuff is gecko only sorry :-|
+    // Die Bill, Die.  (IE supports it somewhat nativly though)
+    if(HTMLArea.is_gecko)
+    {
+      var s = editor._getSelection()
+      var autoWrap = function (textNode, tag)
+      {
+        var rightText = textNode.nextSibling;
+        if(typeof tag == 'string') tag = editor._doc.createElement(tag);
+        var a = textNode.parentNode.insertBefore(tag, rightText);
+        HTMLArea.removeFromParent(textNode);
+        a.appendChild(textNode);
+        rightText.data = ' ' + rightText.data;
+
+        if(HTMLArea.is_ie)
+        {
+          var r = editor._createRange(s);
+          s.moveToElementText(rightText);
+          s.move('character', 1);
+        }
+        else
+        {
+          s.collapse(rightText, 1);
+        }
+        HTMLArea._stopEvent(ev);
+
+        editor._unLink = function()
+        {
+          var t = a.firstChild;
+          a.removeChild(t);
+          a.parentNode.insertBefore(t, a);
+          HTMLArea.removeFromParent(a);
+          editor._unLink = null;
+          editor._unlinkOnUndo = false;
+        }
+        editor._unlinkOnUndo = true;
+
+        return a;
+      }
+
+      switch(ev.which)
+      {
+        // Space, see if the text just typed looks like a URL, or email address
+        // and link it appropriatly
+        case 32:
+        {
+          if(s && s.isCollapsed && s.anchorNode.nodeType == 3 && s.anchorNode.data.length > 3 && s.anchorNode.data.indexOf('.') >= 0)
+          {
+            var midStart = s.anchorNode.data.substring(0,s.anchorOffset).search(/\S{4,}$/);
+            if(midStart == -1) break;
+
+            if(this._getFirstAncestor(s, 'a'))
+            {
+              break; // already in an anchor
+            }
+
+            var matchData = s.anchorNode.data.substring(0,s.anchorOffset).replace(/^.*?(\S*)$/, '$1');
+
+            var m        = matchData.match(HTMLArea.RE_email);
+            if(m)
+            {
+              var leftText  = s.anchorNode;
+              var rightText = leftText.splitText(s.anchorOffset);
+              var midText   = leftText.splitText(midStart);
+
+              autoWrap(midText, 'a').href = 'mailto:' + m[0];
+              break;
+            }
+
+            var m = matchData.match(HTMLArea.RE_url);
+            if(m)
+            {
+              var leftText  = s.anchorNode;
+              var rightText = leftText.splitText(s.anchorOffset);
+              var midText   = leftText.splitText(midStart);
+              autoWrap(midText, 'a').href = (m[1] ? m[1] : 'http://') + m[2];
+              break;
+            }
+          }
+
+        }
+        break;
+
+        default :
+        {
+          if(ev.keyCode == 27 || (this._unlinkOnUndo && ev.ctrlKey && ev.which == 122) )
+          {
+            if(this._unLink)
+            {
+              this._unLink();
+              HTMLArea._stopEvent(ev);
+            }
+            break;
+          }
+          else if(ev.which || ev.keyCode == 8 || ev.keyCode == 46)
+          {
+            this._unlinkOnUndo = false;
+
+            if(s.anchorNode && s.anchorNode.nodeType == 3)
+            {
+              // See if we might be changing a link
+              var a = this._getFirstAncestor(s, 'a');
+              if(!a) break; // not an anchor
+              if(!a._updateAnchTimeout)
+              {
+                if(   s.anchorNode.data.match(HTMLArea.RE_email)
+                   && (a.href.match('mailto:' + s.anchorNode.data.trim()))
+                  )
+                {
+                  var textNode = s.anchorNode;
+                  var fn = function()
+                    {
+                      a.href = 'mailto:' + textNode.data.trim();
+                      a._updateAnchTimeout = setTimeout(fn, 250);
+                    }
+                  a._updateAnchTimeout = setTimeout(fn, 250);
+                  break;
+                }
+
+                var m = s.anchorNode.data.match(HTMLArea.RE_url);
+                if(m &&  a.href.match(s.anchorNode.data.trim()) )
+                {
+                  var textNode = s.anchorNode;
+                  var fn = function()
+                    {
+                      var m = textNode.data.match(HTMLArea.RE_url);
+                      a.href = (m[1] ? m[1] : 'http://') + m[2];
+                      a._updateAnchTimeout = setTimeout(fn, 250);
+                    }
+                  a._updateAnchTimeout = setTimeout(fn, 250);
+                }
+              }
+            }
+
+          }
+        }
+        break;
+      }
+    }
+
+    // other keys here
+    switch (ev.keyCode)
+    {
+        case 13: // KEY enter
+      if (HTMLArea.is_gecko && !ev.shiftKey && this.config.mozParaHandler == 'dirty' )
+      {
+        this.dom_checkInsertP();
+        HTMLArea._stopEvent(ev);
+      }
+      break;
+        case 8: // KEY backspace
+        case 46: // KEY delete
+      if (HTMLArea.is_gecko && !ev.shiftKey) {
+        if (this.dom_checkBackspace())
+          HTMLArea._stopEvent(ev);
+      } else if (HTMLArea.is_ie) {
+        if (this.ie_checkBackspace())
+          HTMLArea._stopEvent(ev);
+      }
+      break;
+    }
+  }
+
+  // update the toolbar state after some time
+  if (editor._timerToolbar) {
+    clearTimeout(editor._timerToolbar);
+  }
+  editor._timerToolbar = setTimeout(function() {
+    editor.updateToolbar();
+    editor._timerToolbar = null;
+  }, 250);
+};
+
+HTMLArea.prototype.convertNode = function(el, newTagName) {
+  var newel = this._doc.createElement(newTagName);
+  while (el.firstChild)
+    newel.appendChild(el.firstChild);
+  return newel;
+};
+
+HTMLArea.prototype.ie_checkBackspace = function() {
+  var sel = this._getSelection();
+  if(HTMLArea.is_ie && sel.type == 'Control')
+  {
+    var elm = this._activeElement(sel);
+    HTMLArea.removeFromParent(elm);
+    return true;
+  }
+
+  // This bit of code preseves links when you backspace over the
+  // endpoint of the link in IE.  Without it, if you have something like
+  //    link_here |
+  // where | is the cursor, and backspace over the last e, then the link
+  // will de-link, which is a bit tedious
+  var range = this._createRange(sel);
+  var r2 = range.duplicate();
+  r2.moveStart("character", -1);
+  var a = r2.parentElement();
+  if (a != range.parentElement() &&
+      /^a$/i.test(a.tagName)) {
+    r2.collapse(true);
+    r2.moveEnd("character", 1);
+    r2.pasteHTML('');
+    r2.select();
+    return true;
+  }
+};
+
+HTMLArea.prototype.dom_checkBackspace = function() {
+  var self = this;
+  setTimeout(function() {
+    var sel = self._getSelection();
+    var range = self._createRange(sel);
+    var SC = range.startContainer;
+    var SO = range.startOffset;
+    var EC = range.endContainer;
+    var EO = range.endOffset;
+    var newr = SC.nextSibling;
+    if (SC.nodeType == 3)
+      SC = SC.parentNode;
+    if (!/\S/.test(SC.tagName)) {
+      var p = document.createElement("p");
+      while (SC.firstChild)
+        p.appendChild(SC.firstChild);
+      SC.parentNode.insertBefore(p, SC);
+      HTMLArea.removeFromParent(SC);
+      var r = range.cloneRange();
+      r.setStartBefore(newr);
+      r.setEndAfter(newr);
+      r.extractContents();
+      sel.removeAllRanges();
+      sel.addRange(r);
+    }
+  }, 10);
+};
+
+/** The idea here is
+ * 1. See if we are in a block element
+ * 2. If we are not, then wrap the current "block" of text into a paragraph
+ * 3. Now that we have a block element, select all the text between the insertion point
+ *    and just AFTER the end of the block
+ *    eg <p>The quick |brown fox jumped over the lazy dog.</p>|
+ *                     ---------------------------------------
+ * 4. Extract that from the document, making
+ *       <p>The quick </p>
+ *    and a document fragment with
+ *       <p>brown fox jumped over the lazy dog.</p>
+ * 5. Reinsert it just after the block element
+ *       <p>The quick </p><p>brown fox jumped over the lazy dog.</p>
+ *
+ * Along the way, allow inserting blank paragraphs, which will look like <p><br/></p>
+ */
+
+HTMLArea.prototype.dom_checkInsertP = function() {
+
+  // Get the insertion point, we'll scrub any highlighted text the user wants rid of while we are there.
+  var sel = this._getSelection();
+  var range = this._createRange(sel);
+  if (!range.collapsed)
+  {
+    range.deleteContents();
+  }
+  this.deactivateEditor();
+  //sel.removeAllRanges();
+  //sel.addRange(range);
+
+  var SC = range.startContainer;
+  var SO = range.startOffset;
+  var EC = range.endContainer;
+  var EO = range.endOffset;
+
+  // If the insertion point is character 0 of the
+  // document, then insert a space character that we will wrap into a paragraph
+  // in a bit.
+  if (SC == EC && SC == body && !SO && !EO)
+  {
+    p = this._doc.createTextNode(" ");
+    body.insertBefore(p, body.firstChild);
+    range.selectNodeContents(p);
+    SC = range.startContainer;
+    SO = range.startOffset;
+    EC = range.endContainer;
+    EO = range.endOffset;
+  }
+
+  // See if we are in a block element, if so, great.
+  var p     = this.getAllAncestors();
+
+  var block = null;
+  var body = this._doc.body;
+  for (var i = 0; i < p.length; ++i)
+  {
+    if(HTMLArea.isParaContainer(p[i]))
+    {
+      break;
+    }
+    else if (HTMLArea.isBlockElement(p[i]) && !/body|html/i.test(p[i].tagName))
+    {
+      block = p[i];
+      break;
+    }
+  }
+
+  // If not in a block element, we'll have to turn some stuff into a paragraph
+  if (!block)
+  {
+    // We want to wrap as much stuff as possible into the paragraph in both directions
+    // from the insertion point.  We start with the start container and walk back up to the
+    // node just before any of the paragraph containers.
+    var wrap = range.startContainer;
+    while(wrap.parentNode && !HTMLArea.isParaContainer(wrap.parentNode))
+    {
+      wrap = wrap.parentNode;
+    }
+    var start = wrap;
+    var end   = wrap;
+
+    // Now we walk up the sibling list until we hit the top of the document
+    // or an element that we shouldn't put in a p (eg other p, div, ul, ol, table)
+    while(start.previousSibling)
+    {
+      if(start.previousSibling.tagName)
+      {
+        if(!HTMLArea.isBlockElement(start.previousSibling))
+        {
+          start = start.previousSibling;
+        }
+        else
+        {
+          break;
+        }
+      }
+      else
+      {
+        start = start.previousSibling;
+      }
+    }
+
+    // Same down the list
+    while(end.nextSibling)
+    {
+      if(end.nextSibling.tagName)
+      {
+        if(!HTMLArea.isBlockElement(end.nextSibling))
+        {
+          end = end.nextSibling;
+        }
+        else
+        {
+          break;
+        }
+      }
+      else
+      {
+        end = end.nextSibling;
+      }
+    }
+
+    // Select the entire block
+    range.setStartBefore(start);
+    range.setEndAfter(end);
+
+    // Make it a paragraph
+    range.surroundContents(this._doc.createElement('p'));
+
+    // Which becomes the block element
+    block = range.startContainer.firstChild;
+
+    // And finally reset the insertion point to where it was originally
+    range.setStart(SC, SO);
+  }
+
+  // The start point is the insertion point, so just move the end point to immediatly
+  // after the block
+  range.setEndAfter(block);
+
+  // Extract the range, to split the block
+  // If we just did range.extractContents() then Mozilla does wierd stuff
+  // with selections, but if we clone, then remove the original range and extract
+  // the clone, it's quite happy.
+  var r2 = range.cloneRange();
+  sel.removeRange(range);
+  var df = r2.extractContents();
+
+  if(df.childNodes.length == 0)
+  {
+    df.appendChild(this._doc.createElement('p'));
+    df.firstChild.appendChild(this._doc.createElement('br'));
+  }
+
+  if(df.childNodes.length > 1)
+  {
+    var nb = this._doc.createElement('p');
+    while(df.firstChild)
+    {
+      var s = df.firstChild;
+      df.removeChild(s);
+      nb.appendChild(s);
+    }
+    df.appendChild(nb);
+  }
+
+  // If the original block is empty, put a nsbp in it.
+  if (!/\S/.test(block.innerHTML))
+    block.innerHTML = "&nbsp;";
+
+  p = df.firstChild;
+  if (!/\S/.test(p.innerHTML))
+    p.innerHTML = "<br />";
+
+  // If the new block is empty and it's a heading, make it a paragraph
+  // note, the new block is empty when you are hitting enter at the end of the existing block
+  if (/^\s*<br\s*\/?>\s*$/.test(p.innerHTML) && /^h[1-6]$/i.test(p.tagName))
+  {
+    df.appendChild(this.convertNode(p, "p"));
+    df.removeChild(p);
+  }
+
+  var newblock = block.parentNode.insertBefore(df.firstChild, block.nextSibling);
+
+  // Select the range (to set the insertion)
+  // collapse to the start of the new block
+  //  (remember the block might be <p><br/></p>, so if we collapsed to the end the <br/> would be noticable)
+
+  //range.selectNode(newblock.firstChild);
+  //range.collapse(true);
+
+  this.activateEditor();
+
+  var sel = this._getSelection();
+  sel.removeAllRanges();
+  sel.collapse(newblock,0);
+
+  // scroll into view
+  this.scrollToElement(newblock);
+
+  //this.forceRedraw();
+
+};
+
+HTMLArea.prototype.scrollToElement = function(e)
+{
+  if(HTMLArea.is_gecko)
+  {
+    var top  = 0;
+    var left = 0;
+    while(e)
+    {
+      top  += e.offsetTop;
+      left += e.offsetLeft;
+      if(e.offsetParent && e.offsetParent.tagName.toLowerCase() != 'body')
+      {
+        e = e.offsetParent;
+      }
+      else
+      {
+        e = null;
+      }
+    }
+    this._iframe.contentWindow.scrollTo(left, top);
+  }
+}
+
+// retrieve the HTML
+HTMLArea.prototype.getHTML = function() {
+  var html = '';
+  switch (this._editMode) {
+      case "wysiwyg"  :
+        {
+          if (!this.config.fullPage)
+            html = HTMLArea.getHTML(this._doc.body, false, this);
+          else
+            html = this.doctype + "\n" + HTMLArea.getHTML(this._doc.documentElement, true, this);
+          break;
+        }
+      case "textmode" :
+        {
+          html = this._textArea.value;
+          break;
+        }
+      default	        :
+        {
+          alert("Mode <" + mode + "> not defined!");
+          return false;
+        }
+  }
+  return html;
+};
+
+HTMLArea.prototype.outwardHtml = function(html)
+{
+  html = html.replace(/<(\/?)b(\s|>|\/)/ig, "<$1strong$2");
+  html = html.replace(/<(\/?)i(\s|>|\/)/ig, "<$1em$2");
+  html = html.replace(/<(\/?)strike(\s|>|\/)/ig, "<$1del$2");
+  
+  // replace window.open to that any clicks won't open a popup in designMode
+  html = html.replace("onclick=\"try{if(document.designMode &amp;&amp; document.designMode == 'on') return false;}catch(e){} window.open(", "onclick=\"window.open(");
+
+  // Figure out what our server name is, and how it's referenced
+  var serverBase = location.href.replace(/(https?:\/\/[^\/]*)\/.*/, '$1') + '/';
+
+  // IE puts this in can't figure out why
+  html = html.replace(/https?:\/\/null\//g, serverBase);
+
+  // Make semi-absolute links to be truely absolute
+  //  we do this just to standardize so that special replacements knows what
+  //  to expect
+  html = html.replace(/((href|src|background)=[\'\"])\/+/ig, '$1' + serverBase);
+
+  html = this.outwardSpecialReplacements(html);
+
+  html = this.fixRelativeLinks(html);
+
+  if(this.config.sevenBitClean)
+  {
+    html = html.replace(/[^ -~\r\n\t]/g, function(c){ return '&#'+c.charCodeAt(0)+';';});
+  }
+
+  // ticket:56, the "greesemonkey" plugin for Firefox adds this junk,
+  // so we strip it out.  Original submitter gave a plugin, but that's
+  // a bit much just for this IMHO - james
+  if(HTMLArea.is_gecko)
+  {
+    html = html.replace(/<script[\s]*src[\s]*=[\s]*['"]chrome:\/\/.*?["']>[\s]*<\/script>/ig, '');
+  }
+
+  return html;
+}
+
+HTMLArea.prototype.inwardHtml = function(html)
+{
+  // Midas uses b and i instead of strong and em, um, hello,
+  // mozilla, this is the 21st century calling!
+  if (HTMLArea.is_gecko) {
+    html = html.replace(/<(\/?)strong(\s|>|\/)/ig, "<$1b$2");
+    html = html.replace(/<(\/?)em(\s|>|\/)/ig, "<$1i$2");
+    html = html.replace(/<(\/?)strike(\s|>|\/)/ig, "<$1del$2");
+  }
+
+  // replace window.open to that any clicks won't open a popup in designMode
+  html = html.replace("onclick=\"window.open(", "onclick=\"try{if(document.designMode &amp;&amp; document.designMode == 'on') return false;}catch(e){} window.open(");
+
+  html = this.inwardSpecialReplacements(html);
+
+  // For IE's sake, make any URLs that are semi-absolute (="/....") to be
+  // truely absolute
+  var nullRE = new RegExp('((href|src|background)=[\'"])/+', 'gi');
+  html = html.replace(nullRE, '$1' + location.href.replace(/(https?:\/\/[^\/]*)\/.*/, '$1') + '/');
+
+  html = this.fixRelativeLinks(html);
+  return html;
+}
+
+HTMLArea.prototype.outwardSpecialReplacements = function(html)
+{
+  for(var i in this.config.specialReplacements)
+  {
+    var from = this.config.specialReplacements[i];
+    var to   = i;
+    // alert('out : ' + from + '=>' + to);
+    var reg = new RegExp(from.replace(HTMLArea.RE_Specials, '\\$1'), 'g');
+    html = html.replace(reg, to.replace(/\$/g, '$$$$'));
+    //html = html.replace(from, to);
+  }
+  return html;
+}
+
+HTMLArea.prototype.inwardSpecialReplacements = function(html)
+{
+  // alert("inward");
+  for(var i in this.config.specialReplacements)
+  {
+    var from = i;
+    var to   = this.config.specialReplacements[i];
+    // alert('in : ' + from + '=>' + to);
+    //
+    // html = html.replace(reg, to);
+    // html = html.replace(from, to);
+    var reg = new RegExp(from.replace(HTMLArea.RE_Specials, '\\$1'), 'g');
+    html = html.replace(reg, to.replace(/\$/g, '$$$$')); // IE uses doubled dollar signs to escape backrefs, also beware that IE also implements $& $_ and $' like perl.
+  }
+  return html;
+}
+
+
+HTMLArea.prototype.fixRelativeLinks = function(html)
+{
+
+  if(typeof this.config.stripSelfNamedAnchors != 'undefined' && this.config.stripSelfNamedAnchors)
+  {
+    var stripRe = new RegExp(document.location.href.replace(HTMLArea.RE_Specials, '\\$1') + '(#[^\'" ]*)', 'g');
+    html = html.replace(stripRe, '$1');
+  }
+
+
+  if(typeof this.config.stripBaseHref != 'undefined' && this.config.stripBaseHref)
+  {
+    var baseRe = null
+    if(typeof this.config.baseHref != 'undefined' && this.config.baseHref != null)
+    {
+      baseRe = new RegExp(this.config.baseHref.replace(HTMLArea.RE_Specials, '\\$1'), 'g');
+    }
+    else
+    {
+      baseRe = new RegExp(document.location.href.replace(/([^\/]*\/?)$/, '').replace(HTMLArea.RE_Specials, '\\$1'), 'g');
+    }
+
+    html = html.replace(baseRe, '');
+  }
+
+  if(HTMLArea.is_ie)
+  {
+    // This is now done in inward & outward
+    // Don't know why but IE is doing this (putting http://null/ on links?!
+    // alert(html);
+    // var nullRE = new RegExp('https?:\/\/null\/', 'g');
+    // html = html.replace(nullRE, location.href.replace(/(https?:\/\/[^\/]*\/).*/, '$1'));
+    // alert(html);
+  }
+
+  return html;
+}
+
+// retrieve the HTML (fastest version, but uses innerHTML)
+HTMLArea.prototype.getInnerHTML = function() {
+  if(!this._doc.body) return '';
+  switch (this._editMode) {
+      case "wysiwyg"  :
+        if (!this.config.fullPage)
+          // return this._doc.body.innerHTML;
+          html = this._doc.body.innerHTML;
+        else
+          html = this.doctype + "\n" + this._doc.documentElement.innerHTML;
+        break;
+      case "textmode" :
+        html = this._textArea.value;
+        break;
+      default	    :
+        alert("Mode <" + mode + "> not defined!");
+        return false;
+  }
+
+  return html;
+};
+
+// completely change the HTML inside
+HTMLArea.prototype.setHTML = function(html) {
+  if (!this.config.fullPage)
+  {
+    this._doc.body.innerHTML = html;
+  }
+  else
+  {
+    this.setFullHTML(html);
+  }
+  this._textArea.value = html;
+};
+
+// sets the given doctype (useful when config.fullPage is true)
+HTMLArea.prototype.setDoctype = function(doctype) {
+  this.doctype = doctype;
+};
+
+/***************************************************
+ *  Category: UTILITY FUNCTIONS
+ ***************************************************/
+
+// variable used to pass the object to the popup editor window.
+HTMLArea._object = null;
+
+// function that returns a clone of the given object
+HTMLArea.cloneObject = function(obj) {
+  if (!obj) return null;
+  var newObj = new Object;
+
+  // check for array objects
+  if (obj.constructor.toString().indexOf("function Array(") == 1) {
+    newObj = obj.constructor();
+  }
+
+  // check for function objects (as usual, IE is fucked up)
+  if (obj.constructor.toString().indexOf("function Function(") == 1) {
+    newObj = obj; // just copy reference to it
+  } else for (var n in obj) {
+    var node = obj[n];
+    if (typeof node == 'object') { newObj[n] = HTMLArea.cloneObject(node); }
+    else                         { newObj[n] = node; }
+  }
+
+  return newObj;
+};
+
+// FIXME!!! this should return false for IE < 5.5
+HTMLArea.checkSupportedBrowser = function() {
+  if (HTMLArea.is_gecko) {
+    if (navigator.productSub < 20021201) {
+      alert("You need at least Mozilla-1.3 Alpha.\n" +
+            "Sorry, your Gecko is not supported.");
+      return false;
+    }
+    if (navigator.productSub < 20030210) {
+      alert("Mozilla < 1.3 Beta is not supported!\n" +
+            "I'll try, though, but it might not work.");
+    }
+  }
+  return HTMLArea.is_gecko || HTMLArea.is_ie;
+};
+
+// selection & ranges
+
+// returns the current selection object
+HTMLArea.prototype._getSelection = function() {
+  if (HTMLArea.is_ie) {
+    return this._doc.selection;
+  } else {
+    return this._iframe.contentWindow.getSelection();
+  }
+};
+
+// returns a range for the current selection
+HTMLArea.prototype._createRange = function(sel) {
+  if (HTMLArea.is_ie) {
+    return sel.createRange();
+  } else {
+    this.activateEditor();
+    if (typeof sel != "undefined") {
+      try {
+        return sel.getRangeAt(0);
+      } catch(e) {
+        return this._doc.createRange();
+      }
+    } else {
+      return this._doc.createRange();
+    }
+  }
+};
+
+// event handling
+
+/** Event Flushing
+ *  To try and work around memory leaks in the rather broken
+ *  garbage collector in IE, HTMLArea.flushEvents can be called
+ *  onunload, it will remove any event listeners (that were added
+ *  through _addEvent(s)) and clear any DOM-0 events.
+ */
+HTMLArea._eventFlushers = [ ];
+HTMLArea.flushEvents = function()
+{
+  var x = 0;
+  var e = null;
+  while(e = HTMLArea._eventFlushers.pop())
+  {
+    if(e.length == 3)
+    {
+      HTMLArea._removeEvent(e[0], e[1], e[2]);
+      x++;
+    }
+    else if (e.length == 2)
+    {
+      e[0]['on' + e[1]] = null;
+      e[0]._xinha_dom0Events[e[1]] = null;
+      x++;
+    }
+  }
+  
+  /* 
+    // This code is very agressive, and incredibly slow in IE, so I've disabled it.
+    
+    if(document.all)
+    {
+      for(var i = 0; i < document.all.length; i++)
+      {
+        for(var j in document.all[i])
+        {
+          if(/^on/.test(j) && typeof document.all[i][j] == 'function')
+          {
+            document.all[i][j] = null;
+            x++;
+          }
+        }
+      }
+    }
+  */
+  
+  // alert('Flushed ' + x + ' events.');
+}
+
+HTMLArea._addEvent = function(el, evname, func) {
+  if (HTMLArea.is_ie) {
+    el.attachEvent("on" + evname, func);
+  } else {
+    el.addEventListener(evname, func, true);
+  }
+  HTMLArea._eventFlushers.push([el, evname, func]);
+};
+
+HTMLArea._addEvents = function(el, evs, func) {
+  for (var i = evs.length; --i >= 0;) {
+    HTMLArea._addEvent(el, evs[i], func);
+  }
+};
+
+HTMLArea._removeEvent = function(el, evname, func) {
+  if (HTMLArea.is_ie) {
+    el.detachEvent("on" + evname, func);
+  } else {
+    el.removeEventListener(evname, func, true);
+  }
+};
+
+HTMLArea._removeEvents = function(el, evs, func) {
+  for (var i = evs.length; --i >= 0;) {
+    HTMLArea._removeEvent(el, evs[i], func);
+  }
+};
+
+HTMLArea._stopEvent = function(ev) {
+  if (HTMLArea.is_ie) {
+    ev.cancelBubble = true;
+    ev.returnValue = false;
+  } else {
+    ev.preventDefault();
+    ev.stopPropagation();
+  }
+};
+
+/**
+ * Adds a standard "DOM-0" event listener to an element.
+ * The DOM-0 events are those applied directly as attributes to
+ * an element - eg element.onclick = stuff;
+ *
+ * By using this function instead of simply overwriting any existing
+ * DOM-0 event by the same name on the element it will trigger as well
+ * as the existing ones.  Handlers are triggered one after the other
+ * in the order they are added.
+ *
+ * Remember to return true/false from your handler, this will determine
+ * whether subsequent handlers will be triggered (ie that the event will
+ * continue or be canceled).
+ *
+ */
+
+HTMLArea.addDom0Event = function(el, ev, fn)
+{
+  HTMLArea._prepareForDom0Events(el, ev);
+  el._xinha_dom0Events[ev].unshift(fn);
+}
+
+
+/**
+ * See addDom0Event, the difference is that handlers registered using
+ * prependDom0Event will be triggered before existing DOM-0 events of the
+ * same name on the same element.
+ */
+
+HTMLArea.prependDom0Event = function(el, ev, fn)
+{
+  HTMLArea._prepareForDom0Events(el, ev);
+  el._xinha_dom0Events[ev].push(fn);
+}
+
+/**
+ * Prepares an element to receive more than one DOM-0 event handler
+ * when handlers are added via addDom0Event and prependDom0Event.
+ */
+HTMLArea._prepareForDom0Events = function(el, ev)
+{
+  // Create a structure to hold our lists of event handlers
+  if(typeof el._xinha_dom0Events == 'undefined')
+  {
+    el._xinha_dom0Events = { };
+    HTMLArea.freeLater(el, '_xinha_dom0Events');
+  }
+
+  // Create a list of handlers for this event type
+  if(typeof el._xinha_dom0Events[ev] == 'undefined')
+  {
+    el._xinha_dom0Events[ev] = [ ];
+    if(typeof el['on'+ev] == 'function')
+    {
+      el._xinha_dom0Events[ev].push(el['on'+ev]);
+    }
+
+    // Make the actual event handler, which runs through
+    // each of the handlers in the list and executes them
+    // in the correct context.
+    el['on'+ev] = function(event)
+    {
+      var a = el._xinha_dom0Events[ev];
+      // call previous submit methods if they were there.
+      var allOK = true;
+      for (var i = a.length; --i >= 0;)
+      {
+        // We want the handler to be a member of the form, not the array, so that "this" will work correctly
+        el._xinha_tempEventHandler = a[i];
+        if(el._xinha_tempEventHandler(event) == false)
+        {
+          el._xinha_tempEventHandler = null;
+          allOK = false;
+          break;
+        }
+        el._xinha_tempEventHandler = null;
+      }
+      return allOK;
+    }
+
+    HTMLArea._eventFlushers.push([el, ev]);
+  }
+}
+
+HTMLArea.prototype.notifyOn = function(ev, fn)
+{
+  if(typeof this._notifyListeners[ev] == 'undefined')
+  {
+    this._notifyListeners[ev] = [ ];
+    HTMLArea.freeLater(this, '_notifyListeners');
+  }
+
+  this._notifyListeners[ev].push(fn);
+}
+
+HTMLArea.prototype.notifyOf = function(ev, args)
+{
+
+  if(this._notifyListeners[ev])
+  {
+
+    for(var i = 0; i < this._notifyListeners[ev].length; i++)
+    {
+      this._notifyListeners[ev][i](ev, args);
+    }
+  }
+}
+
+
+HTMLArea._removeClass = function(el, className) {
+  if (!(el && el.className)) {
+    return;
+  }
+  var cls = el.className.split(" ");
+  var ar = new Array();
+  for (var i = cls.length; i > 0;) {
+    if (cls[--i] != className) {
+      ar[ar.length] = cls[i];
+    }
+  }
+  el.className = ar.join(" ");
+};
+
+HTMLArea._addClass = function(el, className) {
+  // remove the class first, if already there
+  HTMLArea._removeClass(el, className);
+  el.className += " " + className;
+};
+
+HTMLArea._hasClass = function(el, className) {
+  if (!(el && el.className)) {
+    return false;
+  }
+  var cls = el.className.split(" ");
+  for (var i = cls.length; i > 0;) {
+    if (cls[--i] == className) {
+      return true;
+    }
+  }
+  return false;
+};
+
+HTMLArea._blockTags = " body form textarea fieldset ul ol dl li div " +
+"p h1 h2 h3 h4 h5 h6 quote pre table thead " +
+"tbody tfoot tr td th iframe address blockquote";
+HTMLArea.isBlockElement = function(el) {
+  return el && el.nodeType == 1 && (HTMLArea._blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+};
+
+HTMLArea._paraContainerTags = " body td th caption fieldset div";
+HTMLArea.isParaContainer = function(el)
+{
+  return el && el.nodeType == 1 && (HTMLArea._paraContainerTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+}
+
+HTMLArea._closingTags = " head script style div span tr td tbody table em strong b i strike code cite dfn abbr acronym font a title textarea select form ";
+HTMLArea.needsClosingTag = function(el) {
+  return el && el.nodeType == 1 && (HTMLArea._closingTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+};
+
+// performs HTML encoding of some given string
+HTMLArea.htmlEncode = function(str) {
+  if(typeof str.replace == 'undefined') str = str.toString();
+  // we don't need regexp for that, but.. so be it for now.
+  str = str.replace(/&/ig, "&amp;");
+  str = str.replace(/</ig, "&lt;");
+  str = str.replace(/>/ig, "&gt;");
+  str = str.replace(/\xA0/g, "&nbsp;"); // Decimal 160, non-breaking-space
+  str = str.replace(/\x22/g, "&quot;");
+  // \x22 means '"' -- we use hex reprezentation so that we don't disturb
+  // JS compressors (well, at least mine fails.. ;)
+  return str;
+};
+
+// Retrieves the HTML code from the given node.	 This is a replacement for
+// getting innerHTML, using standard DOM calls.
+// Wrapper catch a Mozilla-Exception with non well formed html source code
+HTMLArea.getHTML = function(root, outputRoot, editor){
+    try{
+        return HTMLArea.getHTMLWrapper(root,outputRoot,editor);
+    }
+    catch(e){
+        alert(HTMLArea._lc('Your Document is not well formed. Check JavaScript console for details.'));
+        return editor._iframe.contentWindow.document.body.innerHTML;
+    }
+}
+
+HTMLArea.getHTMLWrapper = function(root, outputRoot, editor, indent) {
+  var html = "";
+  if(!indent) indent = '';
+
+  switch (root.nodeType) {
+    case 10:// Node.DOCUMENT_TYPE_NODE
+    case 6: // Node.ENTITY_NODE
+    case 12:// Node.NOTATION_NODE
+      // this all are for the document type, probably not necessary
+      break;
+
+    case 2: // Node.ATTRIBUTE_NODE
+      // Never get here, this has to be handled in the ELEMENT case because
+      // of IE crapness requring that some attributes are grabbed directly from
+      // the attribute (nodeValue doesn't return correct values), see
+      //http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=3porgu4mc4ofcoa1uqkf7u8kvv064kjjb4%404ax.com
+      // for information
+      break;
+
+    case 4: // Node.CDATA_SECTION_NODE
+      // Mozilla seems to convert CDATA into a comment when going into wysiwyg mode,
+      //  don't know about IE
+      html += (HTMLArea.is_ie ? ('\n' + indent) : '') + '<![CDATA[' + root.data + ']]>' ;
+      break;
+
+    case 5: // Node.ENTITY_REFERENCE_NODE
+      html += '&' + root.nodeValue + ';';
+      break;
+
+    case 7: // Node.PROCESSING_INSTRUCTION_NODE
+      // PI's don't seem to survive going into the wysiwyg mode, (at least in moz)
+      // so this is purely academic
+      html += (HTMLArea.is_ie ? ('\n' + indent) : '') + '<?' + root.target + ' ' + root.data + ' ?>';
+      break;
+
+
+      case 1: // Node.ELEMENT_NODE
+      case 11: // Node.DOCUMENT_FRAGMENT_NODE
+      case 9: // Node.DOCUMENT_NODE
+      {
+    var closed;
+    var i;
+    var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
+    if (outputRoot)
+      outputRoot = !(editor.config.htmlRemoveTags && editor.config.htmlRemoveTags.test(root_tag));
+    if (HTMLArea.is_ie && root_tag == "head") {
+      if (outputRoot)
+        html += (HTMLArea.is_ie ? ('\n' + indent) : '') + "<head>";
+      // lowercasize
+      var save_multiline = RegExp.multiline;
+      RegExp.multiline = true;
+      var txt = root.innerHTML.replace(HTMLArea.RE_tagName, function(str, p1, p2) {
+        return p1 + p2.toLowerCase();
+      });
+      RegExp.multiline = save_multiline;
+      html += txt + '\n';
+      if (outputRoot)
+        html += (HTMLArea.is_ie ? ('\n' + indent) : '') + "</head>";
+      break;
+    } else if (outputRoot) {
+      closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root)));
+      html += (HTMLArea.is_ie && HTMLArea.isBlockElement(root) ? ('\n' + indent) : '') + "<" + root.tagName.toLowerCase();
+      var attrs = root.attributes;
+      for (i = 0; i < attrs.length; ++i) {
+        var a = attrs.item(i);
+        if (!a.specified && !(root.tagName.toLowerCase().match(/input|option/) && a.nodeName == 'value')) {
+          continue;
+        }
+        var name = a.nodeName.toLowerCase();
+        if (/_moz_editor_bogus_node/.test(name)) {
+          html = "";
+          break;
+        }
+        if (/(_moz)|(contenteditable)|(_msh)/.test(name)) {
+          // avoid certain attributes
+          continue;
+        }
+        var value;
+        if (name != "style") {
+          // IE5.5 reports 25 when cellSpacing is
+          // 1; other values might be doomed too.
+          // For this reason we extract the
+          // values directly from the root node.
+          // I'm starting to HATE JavaScript
+          // development.  Browser differences
+          // suck.
+          //
+          // Using Gecko the values of href and src are converted to absolute links
+          // unless we get them using nodeValue()
+          if (typeof root[a.nodeName] != "undefined" && name != "href" && name != "src" && !/^on/.test(name)) {
+            value = root[a.nodeName];
+          } else {
+            value = a.nodeValue;
+            // IE seems not willing to return the original values - it converts to absolute
+            // links using a.nodeValue, a.value, a.stringValue, root.getAttribute("href")
+            // So we have to strip the baseurl manually :-/
+            if (HTMLArea.is_ie && (name == "href" || name == "src")) {
+              value = editor.stripBaseURL(value);
+            }
+
+            // High-ascii (8bit) characters in links seem to cause problems for some sites,
+            // while this seems to be consistent with RFC 3986 Section 2.4
+            // because these are not "reserved" characters, it does seem to
+            // cause links to international resources not to work.  See ticket:167
+
+            // IE always returns high-ascii characters un-encoded in links even if they
+            // were supplied as % codes (it unescapes them when we pul the value from the link).
+
+            // Hmmm, very strange if we use encodeURI here, or encodeURIComponent in place
+            // of escape below, then the encoding is wrong.  I mean, completely.
+            // Nothing like it should be at all.  Using escape seems to work though.
+            // It's in both browsers too, so either I'm doing something wrong, or
+            // something else is going on?
+
+            if(editor.config.only7BitPrintablesInURLs)
+            {
+              value = value.replace(/([^!-~]+)/g, function(match) { return escape(match); });
+            }
+          }
+        } else { // IE fails to put style in attributes list
+          // FIXME: cssText reported by IE is UPPERCASE
+          value = root.style.cssText;
+        }
+        if (/^(_moz)?$/.test(value)) {
+          // Mozilla reports some special tags
+          // here; we don't need them.
+          continue;
+        }
+        html += " " + name + '="' + HTMLArea.htmlEncode(value) + '"';
+      }
+      if (html != "") {
+        if(closed && root_tag=="p") {
+          //never use <p /> as empty paragraphs won't be visible
+          html += ">&nbsp;</p>";
+        } else if(closed) {
+          html += " />";
+        } else {
+          html += ">";
+        }
+      }
+    }
+    var containsBlock = false;
+    for (i = root.firstChild; i; i = i.nextSibling) {
+      if(!containsBlock && i.nodeType == 1 && HTMLArea.isBlockElement(i)) containsBlock = true;
+      html += HTMLArea.getHTMLWrapper(i, true, editor, indent + '  ');
+    }
+    if (outputRoot && !closed) {
+      html += (HTMLArea.is_ie && HTMLArea.isBlockElement(root) && containsBlock ? ('\n' + indent) : '') + "</" + root.tagName.toLowerCase() + ">";
+    }
+    break;
+      }
+      case 3: // Node.TEXT_NODE
+    html = /^script|style$/i.test(root.parentNode.tagName) ? root.data : HTMLArea.htmlEncode(root.data);
+    break;
+
+      case 8: // Node.COMMENT_NODE
+    html = "<!--" + root.data + "-->";
+    break;
+  }
+  return html;
+};
+
+/** @see getHTMLWrapper (search for "value = a.nodeValue;") */
+
+HTMLArea.prototype.stripBaseURL = function(string)
+{
+  if(this.config.baseHref==null || !this.config.stripBaseHref)
+  {
+    return(string);
+  }
+  var baseurl = this.config.baseHref;
+
+  // strip host-part of URL which is added by MSIE to links relative to server root
+  baseurl = baseurl.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1');
+  basere = new RegExp(baseurl);
+  return string.replace(basere, "");
+};
+
+String.prototype.trim = function() {
+  return this.replace(/^\s+/, '').replace(/\s+$/, '');
+};
+
+// creates a rgb-style color from a number
+HTMLArea._makeColor = function(v) {
+  if (typeof v != "number") {
+    // already in rgb (hopefully); IE doesn't get here.
+    return v;
+  }
+  // IE sends number; convert to rgb.
+  var r = v & 0xFF;
+  var g = (v >> 8) & 0xFF;
+  var b = (v >> 16) & 0xFF;
+  return "rgb(" + r + "," + g + "," + b + ")";
+};
+
+// returns hexadecimal color representation from a number or a rgb-style color.
+HTMLArea._colorToRgb = function(v) {
+  if (!v)
+    return '';
+
+  // returns the hex representation of one byte (2 digits)
+  function hex(d) {
+    return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
+  };
+
+  if (typeof v == "number") {
+    // we're talking to IE here
+    var r = v & 0xFF;
+    var g = (v >> 8) & 0xFF;
+    var b = (v >> 16) & 0xFF;
+    return "#" + hex(r) + hex(g) + hex(b);
+  }
+
+  if (v.substr(0, 3) == "rgb") {
+    // in rgb(...) form -- Mozilla
+    var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
+    if (v.match(re)) {
+      var r = parseInt(RegExp.$1);
+      var g = parseInt(RegExp.$2);
+      var b = parseInt(RegExp.$3);
+      return "#" + hex(r) + hex(g) + hex(b);
+    }
+    // doesn't match RE?!  maybe uses percentages or float numbers
+    // -- FIXME: not yet implemented.
+    return null;
+  }
+
+  if (v.substr(0, 1) == "#") {
+    // already hex rgb (hopefully :D )
+    return v;
+  }
+
+  // if everything else fails ;)
+  return null;
+};
+
+// modal dialogs for Mozilla (for IE we're using the showModalDialog() call).
+
+// receives an URL to the popup dialog and a function that receives one value;
+// this function will get called after the dialog is closed, with the return
+// value of the dialog.
+HTMLArea.prototype._popupDialog = function(url, action, init) {
+  Dialog(this.popupURL(url), action, init);
+};
+
+// paths
+
+HTMLArea.prototype.imgURL = function(file, plugin) {
+  if (typeof plugin == "undefined")
+    return _editor_url + file;
+  else
+    return _editor_url + "plugins/" + plugin + "/img/" + file;
+};
+
+HTMLArea.prototype.popupURL = function(file) {
+  var url = "";
+  if (file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
+    var plugin = RegExp.$1;
+    var popup = RegExp.$2;
+    if (!/\.html$/.test(popup))
+      popup += ".html";
+    url = _editor_url + "plugins/" + plugin + "/popups/" + popup;
+  } else if(file.match(/^\/.*?/))
+            url = file;
+        else
+    url = _editor_url + this.config.popupURL + file;
+  return url;
+};
+
+/**
+ * FIX: Internet Explorer returns an item having the _name_ equal to the given
+ * id, even if it's not having any id.  This way it can return a different form
+ * field even if it's not a textarea.  This workarounds the problem by
+ * specifically looking to search only elements having a certain tag name.
+ */
+HTMLArea.getElementById = function(tag, id) {
+  var el, i, objs = document.getElementsByTagName(tag);
+  for (i = objs.length; --i >= 0 && (el = objs[i]);)
+    if (el.id == id)
+      return el;
+  return null;
+};
+
+
+/** Use some CSS trickery to toggle borders on tables */
+
+HTMLArea.prototype._toggleBorders = function()
+{
+  tables = this._doc.getElementsByTagName('TABLE');
+  if(tables.length != 0)
+  {
+   if(!this.borders)
+   {
+    name = "bordered";
+    this.borders = true;
+   }
+   else
+   {
+     name = "";
+     this.borders = false;
+   }
+
+   for (var ix=0;ix < tables.length;ix++)
+   {
+     if(this.borders)
+     {
+        // flashing the display forces moz to listen (JB:18-04-2005) - #102
+        if(HTMLArea.is_gecko)
+        {
+            tables[ix].style.display="none";
+            tables[ix].style.display="table";
+        }
+        HTMLArea._addClass(tables[ix], 'htmtableborders');
+     }
+     else
+     {
+       HTMLArea._removeClass(tables[ix], 'htmtableborders');
+     }
+   }
+  }
+  return true;
+}
+
+
+HTMLArea.addClasses = function(el, classes)
+  {
+    if(el != null)
+    {
+      var thiers = el.className.trim().split(' ');
+      var ours   = classes.split(' ');
+      for(var x = 0; x < ours.length; x++)
+      {
+        var exists = false;
+        for(var i = 0; exists == false && i < thiers.length; i++)
+        {
+          if(thiers[i] == ours[x])
+          {
+            exists = true;
+          }
+        }
+        if(exists == false)
+        {
+          thiers[thiers.length] = ours[x];
+        }
+      }
+      el.className = thiers.join(' ').trim();
+    }
+  }
+
+HTMLArea.removeClasses = function(el, classes)
+{
+  var existing    = el.className.trim().split();
+  var new_classes = [ ];
+  var remove      = classes.trim().split();
+
+  for(var i = 0; i < existing.length; i++)
+  {
+    var found = false;
+    for(var x = 0; x < remove.length && !found; x++)
+    {
+      if(existing[i] == remove[x])
+      {
+        found = true;
+      }
+    }
+    if(!found)
+    {
+      new_classes[new_classes.length] = existing[i];
+    }
+  }
+  return new_classes.join(' ');
+}
+
+/** Alias these for convenience */
+HTMLArea.addClass       = HTMLArea._addClass;
+HTMLArea.removeClass    = HTMLArea._removeClass;
+HTMLArea._addClasses    = HTMLArea.addClasses;
+HTMLArea._removeClasses = HTMLArea.removeClasses;
+
+/** Use XML HTTPRequest to post some data back to the server and do something
+ * with the response (asyncronously!), this is used by such things as the tidy functions
+ */
+HTMLArea._postback = function(url, data, handler)
+{
+  var req = null;
+  if(HTMLArea.is_ie)
+  {
+   req = new ActiveXObject("Microsoft.XMLHTTP");
+  }
+  else
+  {
+   req = new XMLHttpRequest();
+  }
+
+  var content = '';
+  for(var i in data)
+  {
+    content += (content.length ? '&' : '') + i + '=' + encodeURIComponent(data[i]);
+  }
+
+  function callBack()
+  {
+    if(req.readyState == 4)
+    {
+      if(req.status == 200)
+      {
+        if(typeof handler == 'function')
+        handler(req.responseText, req);
+      }
+      else
+      {
+        alert('An error has occurred: ' + req.statusText);
+      }
+    }
+  }
+
+  req.onreadystatechange = callBack;
+
+  req.open('POST', url, true);
+  req.setRequestHeader
+  (
+      'Content-Type',
+      'application/x-www-form-urlencoded; charset=UTF-8'
+  );
+  //alert(content);
+  req.send(content);
+}
+
+HTMLArea._getback = function(url, handler)
+{
+  var req = null;
+  if(HTMLArea.is_ie)
+  {
+   req = new ActiveXObject("Microsoft.XMLHTTP");
+  }
+  else
+  {
+   req = new XMLHttpRequest();
+  }
+
+  function callBack()
+  {
+    if(req.readyState == 4)
+    {
+      if(req.status == 200)
+      {
+        handler(req.responseText, req);
+      }
+      else
+      {
+        alert('An error has occurred: ' + req.statusText);
+      }
+    }
+  }
+
+  req.onreadystatechange = callBack;
+  req.open('GET', url, true);
+  req.send(null);
+}
+
+HTMLArea._geturlcontent = function(url)
+{
+  var req = null;
+  if(HTMLArea.is_ie)
+  {
+   req = new ActiveXObject("Microsoft.XMLHTTP");
+  }
+  else
+  {
+   req = new XMLHttpRequest();
+  }
+
+  // Synchronous!
+  req.open('GET', url, false);
+  req.send(null);
+  if(req.status == 200)
+  {
+    return req.responseText;
+  }
+  else
+  {
+    return '';
+  }
+
+}
+
+/**
+ * Unless somebody already has, make a little function to debug things
+ */
+if(typeof dump == 'undefined')
+{
+  function dump(o) {
+    var s = '';
+    for (var prop in o) {
+      s += prop + ' = ' + o[prop] + '\n';
+    }
+
+    x = window.open("", "debugger");
+    x.document.write('<pre>' + s + '</pre>');
+  }
+}
+
+
+HTMLArea.arrayContainsArray = function(a1, a2)
+{
+  var all_found = true;
+  for(var x = 0; x < a2.length; x++)
+  {
+    var found = false;
+    for(var i = 0; i < a1.length; i++)
+    {
+      if(a1[i] == a2[x])
+      {
+        found = true;
+        break;
+      }
+    }
+    if(!found)
+    {
+      all_found = false;
+      break;
+    }
+  }
+  return all_found;
+}
+
+HTMLArea.arrayFilter = function(a1, filterfn)
+{
+  var new_a = [ ];
+  for(var x = 0; x < a1.length; x++)
+  {
+    if(filterfn(a1[x]))
+      new_a[new_a.length] = a1[x];
+  }
+
+  return new_a;
+}
+
+HTMLArea.uniq_count = 0;
+HTMLArea.uniq = function(prefix)
+{
+  return prefix + HTMLArea.uniq_count++;
+}
+
+/** New language handling functions **/
+
+
+/** Load a language file.
+ *  This function should not be used directly, HTMLArea._lc will use it when necessary.
+ * @param context Case sensitive context name, eg 'HTMLArea', 'TableOperations', ...
+ */
+HTMLArea._loadlang = function(context)
+{
+  if(typeof _editor_lcbackend == "string")
+  {
+    //use backend
+    var url = _editor_lcbackend;
+    url = url.replace(/%lang%/, _editor_lang);
+    url = url.replace(/%context%/, context);
+  }
+  else
+  {
+    //use internal files
+    if(context != 'HTMLArea') {
+      var url = _editor_url+"plugins/"+context+"/lang/"+_editor_lang+".js";
+    } else {
+      var url = _editor_url+"lang/"+_editor_lang+".js";
+    }
+  }
+
+  var lang;
+  var langData = HTMLArea._geturlcontent(url);
+  if(langData != "") {
+    try {
+        eval('lang = ' + langData);
+    } catch(Error) {
+        alert('Error reading Language-File ('+url+'):\n'+Error.toString());
+        lang = { }
+    }
+  } else {
+    lang = { };
+  }
+
+  return lang;
+}
+
+/** Return a localised string.
+ * @param string    English language string
+ * @param context   Case sensitive context name, eg 'HTMLArea' (default), 'TableOperations'...
+ * @param replace   Replace $variables in String, eg {foo: 'replaceText'} ($foo in string will be replaced)
+ */
+HTMLArea._lc = function(string, context, replace)
+{
+  var ret;
+  if(_editor_lang == "en")
+  {
+    ret = string;
+  }
+  else
+  {
+    if(typeof HTMLArea._lc_catalog == 'undefined')
+    {
+      HTMLArea._lc_catalog = [ ];
+    }
+
+    if(typeof context == 'undefined')
+    {
+      context = 'HTMLArea';
+    }
+
+    if(typeof HTMLArea._lc_catalog[context] == 'undefined')
+    {
+      HTMLArea._lc_catalog[context] = HTMLArea._loadlang(context);
+    }
+
+    if(typeof HTMLArea._lc_catalog[context][string] == 'undefined')
+    {
+      if(context=='HTMLArea')
+      {
+        ret = string; // Indicate it's untranslated
+      }
+      else
+      {
+        //if string is not found and context is not HTMLArea try if it is in HTMLArea
+        ret = HTMLArea._lc(string, 'HTMLArea');
+      }
+    }
+    else
+    {
+      ret = HTMLArea._lc_catalog[context][string];
+    }
+  }
+
+  if(typeof replace != "undefined")
+  {
+    for(var i in replace)
+    {
+      ret = ret.replace('$'+i, replace[i]);
+    }
+  }
+
+  return ret;
+}
+
+HTMLArea.hasDisplayedChildren = function(el)
+{
+  var children = el.childNodes;
+  for(var i =0; i < children.length;i++)
+  {
+    if(children[i].tagName)
+    {
+      if(children[i].style.display != 'none')
+      {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+
+HTMLArea._loadback = function(src, callback)
+{
+  var head = document.getElementsByTagName("head")[0];
+  var evt = HTMLArea.is_ie ? "onreadystatechange" : "onload";
+
+  var script = document.createElement("script");
+  script.type = "text/javascript";
+  script.src = src;
+  script[evt] = function()
+  {
+    if(HTMLArea.is_ie && !/loaded|complete/.test(window.event.srcElement.readyState))  return;
+    callback();
+  }
+  head.appendChild(script);
+};
+
+HTMLArea.collectionToArray = function(collection)
+{
+  var array = [ ];
+  for(var i = 0; i < collection.length; i++)
+  {
+    array.push(collection.item(i));
+  }
+  return array;
+}
+
+if(!Array.prototype.append)
+{
+  Array.prototype.append  = function(a)
+  {
+    for(var i = 0; i<a.length;i++)
+    {
+      this.push(a[i]);
+    }
+    return this;
+  }
+}
+
+HTMLArea.makeEditors = function(editor_names, default_config, plugin_names)
+{
+  if(typeof default_config == 'function')
+  {
+    default_config = default_config();
+  }
+
+  var editors = { };
+  for(var x = 0; x < editor_names.length; x++)
+  {
+    var editor = new HTMLArea(editor_names[x], HTMLArea.cloneObject(default_config));
+    editor.registerPlugins(plugin_names);
+    editors[editor_names[x]] = editor;
+  }
+  return editors;
+}
+
+HTMLArea.startEditors = function(editors)
+{
+  for(var i in editors)
+  {
+    if(editors[i].generate) editors[i].generate();
+  }
+}
+
+HTMLArea.prototype.registerPlugins = function(plugin_names) {
+  if(plugin_names)
+  {
+    for(var i = 0; i < plugin_names.length; i++)
+    {
+      this.registerPlugin(eval(plugin_names[i]));
+    }
+  }
+}
+
+/** Utility function to base64_encode some arbitrary data, uses the builtin btoa() if it exists (Moz) */
+
+HTMLArea.base64_encode =  function(input)
+{
+  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+  var output = "";
+  var chr1, chr2, chr3;
+  var enc1, enc2, enc3, enc4;
+  var i = 0;
+
+  do {
+    chr1 = input.charCodeAt(i++);
+    chr2 = input.charCodeAt(i++);
+    chr3 = input.charCodeAt(i++);
+
+    enc1 = chr1 >> 2;
+    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+    enc4 = chr3 & 63;
+
+    if (isNaN(chr2)) {
+       enc3 = enc4 = 64;
+    } else if (isNaN(chr3)) {
+       enc4 = 64;
+    }
+
+    output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
+       keyStr.charAt(enc3) + keyStr.charAt(enc4);
+  } while (i < input.length);
+
+  return output;
+}
+
+/** Utility function to base64_decode some arbitrary data, uses the builtin atob() if it exists (Moz) */
+
+HTMLArea.base64_decode =function(input)
+{
+  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+  var output = "";
+  var chr1, chr2, chr3;
+  var enc1, enc2, enc3, enc4;
+  var i = 0;
+
+  // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+  input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+  do {
+    enc1 = keyStr.indexOf(input.charAt(i++));
+    enc2 = keyStr.indexOf(input.charAt(i++));
+    enc3 = keyStr.indexOf(input.charAt(i++));
+    enc4 = keyStr.indexOf(input.charAt(i++));
+
+    chr1 = (enc1 << 2) | (enc2 >> 4);
+    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+    chr3 = ((enc3 & 3) << 6) | enc4;
+
+    output = output + String.fromCharCode(chr1);
+
+    if (enc3 != 64) {
+       output = output + String.fromCharCode(chr2);
+    }
+    if (enc4 != 64) {
+       output = output + String.fromCharCode(chr3);
+    }
+  } while (i < input.length);
+
+  return output;
+}
+
+HTMLArea.removeFromParent = function(el)
+{
+  if(!el.parentNode) return;
+  var pN = el.parentNode;
+  pN.removeChild(el);
+  return el;
+}
+
+HTMLArea.hasParentNode = function(el)
+{
+  if(el.parentNode)
+  {
+    // When you remove an element from the parent in IE it makes the parent
+    // of the element a document fragment.  Moz doesn't.
+    if(el.parentNode.nodeType == 11)
+    {
+      return false;
+    }
+    return true;
+  }
+
+  return false;
+}
+
+HTMLArea.getOuterHTML = function(element)
+{
+  if(HTMLArea.is_ie)
+  {
+    return element.outerHTML;
+  }
+  else
+  {
+    return (new XMLSerializer()).serializeToString(element);
+  }
+}
+
+HTMLArea.toFree = [ ];
+HTMLArea.freeLater = function(obj,prop)
+{
+  HTMLArea.toFree.push({o:obj,p:prop});
+}
+
+HTMLArea.free = function(obj, prop)
+{
+  if(obj && !prop)
+  {
+    for(var p in obj)
+    {
+      HTMLArea.free(obj, p);
+    }
+  }
+  else if (obj)
+  {
+    obj[prop] = null;
+  }
+}
+
+/** IE's Garbage Collector is broken very badly.  We will do our best to 
+ *   do it's job for it, but we can't be perfect.
+ */
+
+HTMLArea.collectGarbageForIE = function() 
+{  
+  HTMLArea.flushEvents();   
+  for(var x = 0; x < HTMLArea.toFree.length; x++)
+  {
+    if(!HTMLArea.toFree[x].o) alert("What is " + x + ' ' + HTMLArea.toFree[x].o);
+    HTMLArea.free(HTMLArea.toFree[x].o, HTMLArea.toFree[x].p);
+  }
+}
+
+// -------------------------------------------------------------
+// PLOG HTMLAREA TWEAK
+// Added by: Mark Wu
+// Original by: einSTein
+// Date: 2005/07/20
+// Purpose: Add a CR/LF after some HTML Tag, maintain the source format
+// Come From: http://www.htmlarea.com/forum/htmlArea_3_(beta)_C4/htmlArea_v3.0_-_Bug_Reports_%26_Fixes_F25/Bug_Reports_%26_Fixes_-_Forum_Rules_%2AREAD_THIS%2A_P37586/gforum.cgi?post=22136#22136
+// -------------------------------------------------------------
+
+function insertCRLF( txt ) { 
+ 
+    txt = txt.replace(/<br \/>([^\n])/g,"<br \/>\n$1"); 
+    txt = txt.replace(/<tr>([^\n])/g,"<tr>\n$1"); 
+    txt = txt.replace(/<\/h1>([^\n])/g,"<\/h1>\n$1"); 
+    txt = txt.replace(/<\/h2>([^\n])/g,"<\/h2>\n$1"); 
+    txt = txt.replace(/<\/h3>([^\n])/g,"<\/h3>\n$1"); 
+    txt = txt.replace(/<\/h4>([^\n])/g,"<\/h4>\n$1"); 
+    txt = txt.replace(/<\/h5>([^\n])/g,"<\/h5>\n$1"); 
+    txt = txt.replace(/<\/h6>([^\n])/g,"<\/h6>\n$1"); 
+    txt = txt.replace(/<\/tr>([^\n])/g,"<\/tr>\n$1"); 
+    txt = txt.replace(/<td>([^\n])/g,"<td>\n$1"); 
+    txt = txt.replace(/<\/td>([^\n])/g,"<\/td>\n$1"); 
+    txt = txt.replace(/<\/li>([^\n])/g,"<\/li>\n$1"); 
+    txt = txt.replace(/<\/p>([^\n])/g,"<\/p>\n$1"); 
+    txt = txt.replace(/<p \/>([^\n])/g,"<p \/>\n$1"); 
+
+    return txt; 
+};
+
+// -------------------------------------------------------------
+
+HTMLArea.init();
+HTMLArea.addDom0Event(window,'unload',HTMLArea.collectGarbageForIE);
\ No newline at end of file

Added: plog/trunk/js/xinha/images/ed_about.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_about.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_align.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_align.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_align_center.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_align_center.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_align_justify.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_align_justify.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_align_left.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_align_left.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_align_right.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_align_right.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_blank.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_blank.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_buttons_main.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_buttons_main.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_charmap.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_charmap.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_clearfonts.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_clearfonts.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_color_bg.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_color_bg.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_color_fg.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_color_fg.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_copy.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_copy.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_custom.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_custom.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_cut.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_cut.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_delete.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_delete.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_format_bold.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_format_bold.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_format_italic.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_format_italic.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_format_strike.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_format_strike.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_format_sub.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_format_sub.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_format_sup.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_format_sup.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_format_underline.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_format_underline.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_help.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_help.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_hr.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_hr.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_html.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_html.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_image.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_image.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_indent_less.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_indent_less.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_indent_more.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_indent_more.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_killword.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_killword.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_left_to_right.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_left_to_right.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_link.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_link.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_list_bullet.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_list_bullet.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_list_num.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_list_num.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_overwrite.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_overwrite.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_paste.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_paste.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_print.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_print.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_redo.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_redo.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_resource.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_resource.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_right_to_left.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_right_to_left.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_rmformat.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_rmformat.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_save.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_save.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_save.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_save.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_saveas.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_saveas.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_selectall.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_selectall.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_show_border.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_show_border.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_splitblock.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_splitblock.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_splitcel.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_splitcel.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_undo.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_undo.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/ed_word_cleaner.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/ed_word_cleaner.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/fullscreen_maximize.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/fullscreen_maximize.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/fullscreen_minimize.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/fullscreen_minimize.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/insert_table.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/insert_table.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/insertfilelink.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/insertfilelink.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/insertmacro.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/insertmacro.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/tidy.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/tidy.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/images/toggle_borders.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/images/toggle_borders.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/inline-dialog.js
===================================================================
--- plog/trunk/js/xinha/inline-dialog.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/inline-dialog.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,327 @@
+
+HTMLArea.Dialog = function(editor, html, localizer)
+{
+  this.id    = { };
+  this.r_id  = { }; // reverse lookup id
+  this.editor   = editor;
+  this.document = document;
+
+  this.rootElem = document.createElement('div');
+  this.rootElem.className = 'dialog';
+  this.rootElem.style.position = 'absolute';
+  this.rootElem.style.display  = 'none';
+  this.editor._framework.ed_cell.insertBefore(this.rootElem, this.editor._framework.ed_cell.firstChild);
+  this.rootElem.style.width  = this.width  =  this.editor._framework.ed_cell.offsetWidth + 'px';
+  this.rootElem.style.height = this.height =  this.editor._framework.ed_cell.offsetHeight + 'px';
+
+  var dialog = this;
+  if(typeof localizer == 'function')
+  {
+    this._lc = localizer;
+  }
+  else if(localizer)
+  {
+    this._lc = function(string)
+    {
+      return HTMLArea._lc(string,localizer);
+    }
+  }
+  else
+  {
+    this._lc = function(string)
+    {
+      return string;
+    }
+  }
+
+  html = html.replace(/\[([a-z0-9_]+)\]/ig,
+                      function(fullString, id)
+                      {
+                        if(typeof dialog.id[id] == 'undefined')
+                        {
+                          dialog.id[id] = HTMLArea.uniq('Dialog');
+                          dialog.r_id[dialog.id[id]] = id;
+                        }
+                        return dialog.id[id];
+                      }
+             ).replace(/<l10n>(.*?)<\/l10n>/ig,
+                       function(fullString,translate)
+                       {
+                         return dialog._lc(translate) ;
+                       }
+             ).replace(/="_\((.*?)\)"/g,
+                       function(fullString, translate)
+                       {
+                         return '="' + dialog._lc(translate) + '"';
+                       }
+             );
+
+  this.rootElem.innerHTML = html;
+
+
+
+
+  this.editor.notifyOn
+   ('resize',
+      function(e, args)
+      {
+        dialog.rootElem.style.width  = dialog.width  =  dialog.editor._framework.ed_cell.offsetWidth + 'px';
+        dialog.rootElem.style.height = dialog.height =  dialog.editor._framework.ed_cell.offsetHeight + 'px';
+        dialog.onresize();
+      }
+    );
+}
+
+HTMLArea.Dialog.prototype.onresize = function()
+{
+  return true;
+}
+
+HTMLArea.Dialog.prototype.show = function(values)
+{
+  // We need to preserve the selection for IE
+  if(HTMLArea.is_ie)
+  {
+    this._lastRange = this.editor._createRange(this.editor._getSelection());
+  }
+
+  if(typeof values != 'undefined')
+  {
+    this.setValues(values);
+  }
+  this._restoreTo = [this.editor._textArea.style.display, this.editor._iframe.style.visibility, this.editor.hidePanels()];
+
+  this.editor._textArea.style.display = 'none';
+  this.editor._iframe.style.visibility   = 'hidden';
+  this.rootElem.style.display   = '';
+}
+
+HTMLArea.Dialog.prototype.hide = function()
+{
+  this.rootElem.style.display         = 'none';
+  this.editor._textArea.style.display = this._restoreTo[0];
+  this.editor._iframe.style.visibility   = this._restoreTo[1];
+  this.editor.showPanels(this._restoreTo[2]);
+
+  // Restore the selection
+  if(HTMLArea.is_ie)
+  {
+    this._lastRange.select();
+  }
+  this.editor.updateToolbar();
+  return this.getValues();
+}
+
+HTMLArea.Dialog.prototype.toggle = function()
+{
+  if(this.rootElem.style.display == 'none')
+  {
+    this.show();
+  }
+  else
+  {
+    this.hide();
+  }
+}
+
+HTMLArea.Dialog.prototype.setValues = function(values)
+{
+  for(var i in values)
+  {
+    var elems = this.getElementsByName(i);
+    if(!elems) continue;
+    for(var x = 0; x < elems.length; x++)
+    {
+      var e = elems[x];
+      switch(e.tagName.toLowerCase())
+      {
+        case 'select'  :
+        {
+          for(var j = 0; j < e.options.length; j++)
+          {
+            if(typeof values[i] == 'object')
+            {
+              for(var k = 0; k < values[i].length; k++)
+              {
+                if(values[i][k] == e.options[j].value)
+                {
+                  e.options[j].selected = true;
+                }
+              }
+            }
+            else if(values[i] == e.options[j].value)
+            {
+              e.options[j].selected = true;
+            }
+          }
+          break;
+        }
+
+
+        case 'textarea':
+        case 'input'   :
+        {
+          switch(e.getAttribute('type'))
+          {
+            case 'radio'   :
+            {
+              if(e.value == values[i])
+              {
+                e.checked = true;
+              }
+              break;
+            }
+
+            case 'checkbox':
+            {
+              if(typeof values[i] == 'object')
+              {
+                for(var j in values[i])
+                {
+                  if(values[i][j] == e.value)
+                  {
+                    e.checked = true;
+                  }
+                }
+              }
+              else
+              {
+                if(values[i] == e.value)
+                {
+                  e.checked = true;
+                }
+              }
+              break;
+            }
+
+            default    :
+            {
+              e.value = values[i];
+            }
+          }
+          break;
+        }
+
+        default        :
+        break;
+      }
+    }
+  }
+}
+
+HTMLArea.Dialog.prototype.getValues = function()
+{
+  var values = [ ];
+  var inputs = HTMLArea.collectionToArray(this.rootElem.getElementsByTagName('input'))
+              .append(HTMLArea.collectionToArray(this.rootElem.getElementsByTagName('textarea')))
+              .append(HTMLArea.collectionToArray(this.rootElem.getElementsByTagName('select')));
+
+  for(var x = 0; x < inputs.length; x++)
+  {
+    var i = inputs[x];
+    if(!(i.name && this.r_id[i.name])) continue;
+
+    if(typeof values[this.r_id[i.name]] == 'undefined')
+    {
+      values[this.r_id[i.name]] = null;
+    }
+    var v = values[this.r_id[i.name]];
+
+    switch(i.tagName.toLowerCase())
+    {
+      case 'select':
+      {
+        if(i.multiple)
+        {
+          if(!v.push)
+          {
+            if(v != null)
+            {
+              v = [v];
+            }
+            else
+            {
+              v = new Array();
+            }
+          }
+          for(var j = 0; j < i.options.length; j++)
+          {
+            if(i.options[j].selected)
+            {
+              v.push(i.options[j].value);
+            }
+          }
+        }
+        else
+        {
+          if(i.selectedIndex >= 0)
+          {
+            v = i.options[i.selectedIndex];
+          }
+        }
+        break;
+      }
+
+      case 'textarea':
+      case 'input'   :
+      default        :
+      {
+        switch(i.type.toLowerCase())
+        {
+          case  'radio':
+          {
+            if(i.checked)
+            {
+              v = i.value;
+              break;
+            }
+          }
+
+          case 'checkbox':
+          {
+            if(v == null)
+            {
+              if(this.getElementsByName(this.r_id[i.name]).length > 1)
+              {
+                v = new Array();
+              }
+            }
+
+            if(i.checked)
+            {
+              if(typeof v == 'object' && v.push)
+              {
+                v.push(i.value);
+              }
+              else
+              {
+                v = i.value;
+              }
+            }
+            break;
+          }
+
+          default   :
+          {
+            v = i.value;
+            break;
+          }
+        }
+      }
+
+    }
+
+    values[this.r_id[i.name]] = v;
+  }
+  return values;
+}
+
+HTMLArea.Dialog.prototype.getElementById = function(id)
+{
+  return this.document.getElementById(this.id[id] ? this.id[id] : id);
+}
+
+HTMLArea.Dialog.prototype.getElementsByName = function(name)
+{
+  return this.document.getElementsByName(this.id[name] ? this.id[name] : name);
+}

Added: plog/trunk/js/xinha/lang/b5.js
===================================================================
--- plog/trunk/js/xinha/lang/b5.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/b5.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,29 @@
+// I18N constants -- UTF-8
+// by Dave Lo -- dlo at interactivetools.com
+{
+  "Bold": "ç²—é«”",
+  "Italic": "斜體",
+  "Underline": "底線",
+  "Strikethrough": "刪除線",
+  "Subscript": "下標",
+  "Superscript": "上標",
+  "Justify Left": "位置靠左",
+  "Justify Center": "位置居中",
+  "Justify Right": "位置靠右",
+  "Justify Full": "位置左右平等",
+  "Ordered List": "順序清單",
+  "Bulleted List": "無序清單",
+  "Decrease Indent": "減小行前空白",
+  "Increase Indent": "加寬行前空白",
+  "Font Color": "文字顏色",
+  "Background Color": "背景顏色",
+  "Horizontal Rule": "水平線",
+  "Insert Web Link": "插入連結",
+  "Insert/Modify Image": "插入圖形",
+  "Insert Table": "插入表格",
+  "Toggle HTML Source": "切換HTML原始碼",
+  "Enlarge Editor": "放大",
+  "About this editor": "關於 HTMLArea",
+  "Help using editor": "說明",
+  "Current style": "字體例子"
+}

Added: plog/trunk/js/xinha/lang/ch.js
===================================================================
--- plog/trunk/js/xinha/lang/ch.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/ch.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,56 @@
+// I18N constants
+
+// LANG: "ch", ENCODING: UTF-8
+// Samuel Stone, http://stonemicro.com/
+
+{
+  "Bold": "ç²—é«”",
+  "Italic": "斜體",
+  "Underline": "底線",
+  "Strikethrough": "刪線",
+  "Subscript": "下標",
+  "Superscript": "上標",
+  "Justify Left": "靠左",
+  "Justify Center": "居中",
+  "Justify Right": "靠右",
+  "Justify Full": "整齊",
+  "Ordered List": "順序清單",
+  "Bulleted List": "無序清單",
+  "Decrease Indent": "伸排",
+  "Increase Indent": "縮排",
+  "Font Color": "文字顏色",
+  "Background Color": "背景顏色",
+  "Horizontal Rule": "水平線",
+  "Insert Web Link": "插入連結",
+  "Insert/Modify Image": "插入圖像",
+  "Insert Table": "插入表格",
+  "Toggle HTML Source": "切換HTML原始碼",
+  "Enlarge Editor": "伸出編輯系統",
+  "About this editor": "關於 HTMLArea",
+  "Help using editor": "說明",
+  "Current style": "字體例子",
+  "Undoes your last action": "回原",
+  "Redoes your last action": "重来",
+  "Cut selection": "剪制选项",
+  "Copy selection": "复制选项",
+  "Paste from clipboard": "贴上",
+  "Direction left to right": "从左到右",
+  "Direction right to left": "从右到左",
+  "OK": "好",
+  "Cancel": "取消",
+  "Path": "途徑",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "你在用純字編輯方式.  用 [<>] 按鈕轉回 所見即所得 編輯方式.",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "整頁式在Internet Explorer 上常出問題, 因為這是 Internet Explorer 的無名問題,我們無法解決。你可能看見一些垃圾,或遇到其他問題。我們已警告了你. 如果要轉到 正頁式 請按 好.",
+  "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.",
+  "Cancel": "取消",
+  "Insert/Modify Link": "插入/改寫連結",
+  "New window (_blank)": "新窗户(_blank)",
+  "None (use implicit)": "ç„¡(use implicit)",
+  "Other": "其他",
+  "Same frame (_self)": "本匡 (_self)",
+  "Target:": "目標匡:",
+  "Title (tooltip):": "主題 (tooltip):",
+  "Top frame (_top)": "上匡 (_top)",
+  "URL:": "網址:",
+  "You must enter the URL where this link points to": "你必須輸入你要连结的網址"
+}

Added: plog/trunk/js/xinha/lang/cz.js
===================================================================
--- plog/trunk/js/xinha/lang/cz.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/cz.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,50 @@
+// I18N constants
+
+// LANG: "cz", ENCODING: UTF-8
+// Author: Jiri Löw, <jirilow at jirilow.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Bold": "Tučně",
+  "Italic": "Kurzíva",
+  "Underline": "Podtržení",
+  "Strikethrough": "Přeškrtnutí",
+  "Subscript": "Dolní index",
+  "Superscript": "Horní index",
+  "Justify Left": "Zarovnat doleva",
+  "Justify Center": "Na střed",
+  "Justify Right": "Zarovnat doprava",
+  "Justify Full": "Zarovnat do stran",
+  "Ordered List": "Seznam",
+  "Bulleted List": "Odrážky",
+  "Decrease Indent": "Předsadit",
+  "Increase Indent": "Odsadit",
+  "Font Color": "Barva písma",
+  "Background Color": "Barva pozadí",
+  "Horizontal Rule": "Vodorovná čára",
+  "Insert Web Link": "Vložit odkaz",
+  "Insert/Modify Image": "Vložit obrázek",
+  "Insert Table": "Vložit tabulku",
+  "Toggle HTML Source": "Přepnout HTML",
+  "Enlarge Editor": "Nové okno editoru",
+  "About this editor": "O této aplikaci",
+  "Help using editor": "Nápověda aplikace",
+  "Current style": "Zvolený styl",
+  "Undoes your last action": "Vrátí poslední akci",
+  "Redoes your last action": "Opakuje poslední akci",
+  "Cut selection": "Vyjmout",
+  "Copy selection": "Kopírovat",
+  "Paste from clipboard": "Vložit",
+  "OK": "OK",
+  "Cancel": "Zrušit",
+  "Path": "Cesta",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Jste v TEXTOVÉM REŽIMU.  Použijte tlačítko [<>] pro přepnutí do WYSIWIG."
+}

Added: plog/trunk/js/xinha/lang/da.js
===================================================================
--- plog/trunk/js/xinha/lang/da.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/da.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,30 @@
+// LANG: "da", ENCODING: UTF-8
+// Author: rene, <rene at laerke.net>
+
+{
+  "Bold": "Fed",
+  "Italic": "Kursiv",
+  "Underline": "Understregning",
+  "Strikethrough": "Overstregning ",
+  "Subscript": "Sænket skrift",
+  "Superscript": "Hævet skrift",
+  "Justify Left": "Venstrejuster",
+  "Justify Center": "Centrer",
+  "Justify Right": "Højrejuster",
+  "Justify Full": "Lige margener",
+  "Ordered List": "Opstilling med tal",
+  "Bulleted List": "Opstilling med punkttegn",
+  "Decrease Indent": "Formindsk indrykning",
+  "Increase Indent": "Forøg indrykning",
+  "Font Color": "Skriftfarve",
+  "Background Color": "Baggrundsfarve",
+  "Horizontal Rule": "Horisontal linie",
+  "Insert Web Link": "Indsæt hyperlink",
+  "Insert/Modify Image": "Indsæt billede",
+  "Insert Table": "Indsæt tabel",
+  "Toggle HTML Source": "HTML visning",
+  "Enlarge Editor": "Vis editor i popup",
+  "About this editor": "Om htmlarea",
+  "Help using editor": "Hjælp",
+  "Current style": "Anvendt stil"
+}

Added: plog/trunk/js/xinha/lang/de.js
===================================================================
--- plog/trunk/js/xinha/lang/de.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/de.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,133 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8
+
+{
+        "Bold": "Fett",
+        "Italic": "Kursiv",
+        "Underline": "Unterstrichen",
+        "Strikethrough": "Durchgestrichen",
+        "Subscript": "Tiefgestellt",
+        "Superscript": "Hochgestellt",
+        "Justify Left": "Linksbündig",
+        "Justify Center": "Zentriert",
+        "Justify Right": "Rechtsbündig",
+        "Justify Full": "Blocksatz",
+        "Ordered List": "Nummerierte Liste",
+        "Bulleted List": "Aufzählungsliste",
+        "Decrease Indent": "Einzug verkleinern",
+        "Increase Indent": "Einzug vergrößern",
+        "Font Color": "Schriftfarbe",
+        "Background Color": "Hindergrundfarbe",
+        "Horizontal Rule": "Horizontale Linie",
+        "Insert Web Link": "Hyperlink einfügen",
+        "Insert/Modify Image": "Bild einfügen/verändern",
+        "Insert Table": "Tabelle einfügen",
+        "Toggle HTML Source": "HTML Quelltext ein/ausschalten",
+        "Enlarge Editor": "Editor vergrößern",
+        "About this editor": "Ãœber diesen Editor",
+        "Help using editor": "Hilfe",
+        "Current style": "Derzeitiger Stil",
+        "Undoes your last action": "Rückgängig",
+        "Redoes your last action": "Wiederholen",
+        "Cut selection": "Ausschneiden",
+        "Copy selection": "Kopieren",
+        "Paste from clipboard": "Einfügen aus der Zwischenablage",
+        "Direction left to right": "Textrichtung von Links nach Rechts",
+        "Direction right to left": "Textrichtung von Rechts nach Links",
+        "Remove formatting": "Formatierung entfernen",
+        "Select all": "Alles markieren",
+        "Print document": "Dokument ausdrucken",
+        "Clear MSOffice tags": "MSOffice filter",
+        "Clear Inline Font Specifications": "Zeichensatz Formatierungen entfernen",
+        "Split Block": "Block teilen",
+        "Toggle Borders": "Tabellenränder ein/ausblenden",
+        "Save as": "speichern unter",
+        "Insert/Overwrite": "Einfügen/Überschreiben",
+        "&mdash; format &mdash;": "&mdash; Format &mdash;",
+        "Heading 1": "Ãœberschrift 1",
+        "Heading 2": "Ãœberschrift 2",
+        "Heading 3": "Ãœberschrift 3",
+        "Heading 4": "Ãœberschrift 4",
+        "Heading 5": "Ãœberschrift 5",
+        "Heading 6": "Ãœberschrift 6",
+        "Normal": "Normal (Absatz)",
+        "Address": "Adresse",
+        "Formatted": "Formatiert",
+        
+        //dialogs       
+        "OK": "OK",
+        "Cancel": "Abbrechen",
+        "Path": "Pfad",
+        "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Sie sind im Text-Modus. Benutzen Sie den [<>] Button, um in den visuellen Modus (WYSIWIG) zu gelangen.",
+        "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Aus Sicherheitsgründen dürfen Skripte normalerweise nicht auf Ausschneiden/Kopieren/Einfügen zugreifen. Bitte klicken Sie OK um die technische Erläuterung auf mozilla.org zu öffnen, in der erklärt wird, wie einem Skript Zugriff gewährt werden kann.",
+        
+        "You need to select some text before create a link": "Sie müssen einen Text markieren, um einen Link zu erstellen",
+        "Your Document is not well formed. Check JavaScript console for details.": "Ihr Dokument ist in keinem sauberen Format. Benutzen Sie die Javascript Console für weitere Informationen.",
+
+        "Alignment:": "Ausrichtung:",
+        "Not set": "nicht eingestellt",
+        "Left": "links",
+        "Right": "rechts",
+        "Texttop": "oben bündig",
+        "Absmiddle": "mittig",
+        "Baseline": "Grundlinie",
+        "Absbottom": "unten bündig",
+        "Bottom": "unten",
+        "Middle": "zentriert",
+        "Top": "oben",
+
+        "Layout": "Layout",
+        "Spacing": "Abstand",
+        "Horizontal:": "horizontal:",
+        "Horizontal padding": "horizontaler Inhaltsabstand",
+        "Vertical:": "vertikal:",
+        "Vertical padding": "vertikaler Inhaltsabstand",
+        "Border thickness:": "Randstärke:",
+        "Leave empty for no border": "leer lassen für keinen Rand",
+
+        //Insert Link
+        "Insert/Modify Link": "Verknüpfung hinzufügen/ändern",
+        "None (use implicit)": "k.A. (implizit)",
+        "New window (_blank)": "Neues Fenster (_blank)",
+        "Same frame (_self)": "Selber Rahmen (_self)",
+        "Top frame (_top)": "Oberster Rahmen (_top)",
+        "Other": "Anderes",
+        "Target:": "Ziel:",
+        "Title (tooltip):": "Titel (Tooltip):",
+        "URL:": "URL:",
+        "You must enter the URL where this link points to": "Sie müssen eine Ziel-URL angeben für die Verknüpfung angeben",
+
+        // Insert Table
+        "Insert Table": "Table einfügen",
+        "Rows:": "Zeilen:",
+        "Number of rows": "Zeilenanzahl",
+        "Cols:": "Spalten:",
+        "Number of columns": "Spaltenanzahl",
+        "Width:": "Breite:",
+        "Width of the table": "Tabellenbreite",
+        "Percent": "Prozent",
+        "Pixels": "Pixel",
+        "Em": "Geviert",
+        "Width unit": "Größeneinheit",
+        "Fixed width columns": "Spalten mit fester Breite",
+        "Positioning of this table": "Positionierung der Tabelle",
+        "Cell spacing:": "Zellenabstand:",
+        "Space between adjacent cells": "Raum zwischen angrenzenden Zellen",
+        "Cell padding:": "Innenabstand:",
+        "Space between content and border in cell": "Raum zwischen Inhalt und Rand der Zelle",
+        "You must enter a number of rows": "Bitte geben Sie die Anzahl der Zeilen an",
+        "You must enter a number of columns": "Bitte geben Sie die Anzahl der Spalten an",
+
+        // Insert Image
+        "Insert Image": "Bild einfügen",
+        "Image URL:": "Bild URL:",
+        "Enter the image URL here": "Bitte geben sie hier die Bild URL ein",
+        "Preview": "Voransicht",
+        "Preview the image in a new window": "Voransicht des Bildes in einem neuen Fenster",
+        "Alternate text:": "Alternativer Text:",
+        "For browsers that don't support images": "für Browser, die keine Bilder unterstützen",
+        "Positioning of this image": "Positionierung dieses Bildes",
+        "Image Preview:": "Bild Voransicht:",
+        "You must enter the URL": "Bitte geben Sie die URL ein"
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/lang/ee.js
===================================================================
--- plog/trunk/js/xinha/lang/ee.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/ee.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,50 @@
+// I18N constants
+
+// LANG: "ee", ENCODING: UTF-8
+// Author: Martin Raie, <albertvill at hot.ee>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Bold": "Paks",
+  "Italic": "Kursiiv",
+  "Underline": "Allakriipsutatud",
+  "Strikethrough": "Läbikriipsutatud",
+  "Subscript": "Allindeks",
+  "Superscript": "Ãœlaindeks",
+  "Justify Left": "Joonda vasakule",
+  "Justify Center": "Joonda keskele",
+  "Justify Right": "Joonda paremale",
+  "Justify Full": "Rööpjoonda",
+  "Ordered List": "Nummerdus",
+  "Bulleted List": "Täpploend",
+  "Decrease Indent": "Vähenda taanet",
+  "Increase Indent": "Suurenda taanet",
+  "Font Color": "Fondi värv",
+  "Background Color": "Tausta värv",
+  "Horizontal Rule": "Horisontaaljoon",
+  "Insert Web Link": "Lisa viit",
+  "Insert/Modify Image": "Lisa pilt",
+  "Insert Table": "Lisa tabel",
+  "Toggle HTML Source": "HTML/tavaline vaade",
+  "Enlarge Editor": "Suurenda toimeti aken",
+  "About this editor": "Teave toimeti kohta",
+  "Help using editor": "Spikker",
+  "Current style": "Kirjastiil",
+  "Undoes your last action": "Võta tagasi",
+  "Redoes your last action": "Tee uuesti",
+  "Cut selection": "Lõika",
+  "Copy selection": "Kopeeri",
+  "Paste from clipboard": "Kleebi",
+  "OK": "OK",
+  "Cancel": "Loobu",
+  "Path": "Path",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Sa oled tekstireziimis.  Kasuta nuppu [<>] lülitamaks tagasi WYSIWIG reziimi."
+}

Added: plog/trunk/js/xinha/lang/el.js
===================================================================
--- plog/trunk/js/xinha/lang/el.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/el.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,55 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8
+// Author: Dimitris Glezos, dimitris at glezos.com
+
+{
+  "Bold": "ΞˆΞ½Ο„ΞΏΞ½Ξ±",
+  "Italic": "Πλάγια",
+  "Underline": "Ξ�πογραμμισμένα",
+  "Strikethrough": "Διαγραμμένα",
+  "Subscript": "ΔΡίκτης",
+  "Superscript": "ΔΡίκτης",
+  "Justify Left": "Στοίχιση ΑριστΡρά",
+  "Justify Center": "Στοίχιση ΞšΞ­Ξ½Ο„ΟΞΏ",
+  "Justify Right": "Στοίχιση ΔΡξιά",
+  "Justify Full": "Ξ Ξ»Ξ�ρης Στοίχιση",
+  "Ordered List": "Αρίθμηση",
+  "Bulleted List": "ΞšΞΏΟ…ΞΊΞΊΞ―Ξ΄Ξ΅Ο‚",
+  "Decrease Indent": "ΞœΞ΅Ξ―Ο‰ΟƒΞ· ΕσοχΞ�Ο‚",
+  "Increase Indent": "Αύξηση ΕσοχΞ�Ο‚",
+  "Font Color": "Χρώμα ΓραμματοσΡιράς",
+  "Background Color": "Χρώμα Ξ¦ΟŒΞ½Ο„ΞΏΟ…",
+  "Horizontal Rule": "ΞŸΟΞΉΞΆΟŒΞ½Ο„ΞΉΞ± ΓραμμΞ�",
+  "Insert Web Link": "ΕισαγωγΞ� Συνδέσμου",
+  "Insert/Modify Image": "ΕισαγωγΞ�/Ξ�ροποποίηση Ξ•ΞΉΞΊΟŒΞ½Ξ±Ο‚",
+  "Insert Table": "ΕισαγωγΞ� Ξ Ξ―Ξ½Ξ±ΞΊΞ±",
+  "Toggle HTML Source": "ΕναλλαγΞ� σΡ/Ξ±Ο€ΟŒ HTML",
+  "Enlarge Editor": "ΞœΞ΅Ξ³Ξ­Ξ½ΞΈΟ…Ξ½ΟƒΞ· ΡπΡξΡργαστΞ�",
+  "About this editor": "ΠληροφορίΡς",
+  "Help using editor": "Ξ’ΞΏΞ�θΡια",
+  "Current style": "Παρών στυλ",
+  "Undoes your last action": "ΑναίρΡση τΡλΡυταίας ΡνέργΡιας",
+  "Redoes your last action": "Επαναφορά Ξ±Ο€ΟŒ αναίρΡση",
+  "Cut selection": "ΑποκοπΞ�",
+  "Copy selection": "ΑντιγραφΞ�",
+  "Paste from clipboard": "Ξ•Ο€ΞΉΞΊΟŒΞ»Ξ»Ξ·ΟƒΞ·",
+  "Direction left to right": "ΞšΞ±Ο„Ξ΅ΟΞΈΟ…Ξ½ΟƒΞ· αριστΡρά προς δΡξιά",
+  "Direction right to left": "ΞšΞ±Ο„Ξ΅ΟΞΈΟ…Ξ½ΟƒΞ· Ξ±Ο€ΟŒ δΡξιά προς τα αριστΡρά",
+  "OK": "OK",
+  "Cancel": "Ακύρωση",
+  "Path": "ΔιαδρομΞ�",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "ΕίστΡ σΡ TEXT MODE.  ΧρησιμοποιΞ�στΡ το κουμπί [<>] Ξ³ΞΉΞ± Ξ½Ξ± ΡπανέρθΡτΡ στο WYSIWIG.",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Ξ— κατάσταση πλΞ�ρης ΞΏΞΈΟŒΞ½Ξ·Ο‚ έχΡι προβλΞ�ματα ΞΌΞ΅ τον Internet Explorer, Ξ»ΟŒΞ³Ο‰ σφαλμάτων στον ίδιο τον browser.  Αν το σύστημα σας Ρίναι Windows 9x μπορΡί ΞΊΞ±ΞΉ Ξ½Ξ± χρΡιαστΡίτΡ reboot. Αν ΡίστΡ σίγουροι, πατΞ�στΡ ΟΚ.",
+  "Cancel": "Ακύρωση",
+  "Insert/Modify Link": "ΕισαγωγΞ�/Ξ�ροποποίηση σύνδΡσμου",
+  "New window (_blank)": "Νέο παράθυρο (_blank)",
+  "None (use implicit)": "Κανένα (χρΞ�ση Ξ±Ο€ΟŒΞ»Ο…Ο„ΞΏΟ…)",
+  "Other": "Αλλο",
+  "Same frame (_self)": "Ίδιο frame (_self)",
+  "Target:": "Target:",
+  "Title (tooltip):": "Ξ�ίτλος (tooltip):",
+  "Top frame (_top)": "Πάνω frame (_top)",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "ΠρέπΡι Ξ½Ξ± ΡισάγΡτΡ το URL που οδηγΡί Ξ±Ο…Ο„ΟŒΟ‚ ΞΏ σύνδΡσμος"
+}

Added: plog/trunk/js/xinha/lang/es.js
===================================================================
--- plog/trunk/js/xinha/lang/es.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/es.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,40 @@
+// I18N constants
+
+// LANG: "es", ENCODING: UTF-8
+
+{
+  "Bold": "Negrita",
+  "Italic": "Cursiva",
+  "Underline": "Subrayado",
+  "Strikethrough": "Tachado",
+  "Subscript": "Sub?ndice",
+  "Superscript": "Super?ndice",
+  "Justify Left": "Alinear a la Izquierda",
+  "Justify Center": "Centrar",
+  "Justify Right": "Alinear a la Derecha",
+  "Justify Full": "Justificar",
+  "Ordered List": "Lista Ordenada",
+  "Bulleted List": "Lista No Ordenada",
+  "Decrease Indent": "Aumentar Sangr?a",
+  "Increase Indent": "Disminuir Sangr?a",
+  "Font Color": "Color del Texto",
+  "Background Color": "Color del Fondo",
+  "Horizontal Rule": "L?nea Horizontal",
+  "Insert Web Link": "Insertar Enlace",
+  "Insert/Modify Image": "Insertar Imagen",
+  "Insert Table": "Insertar Tabla",
+  "Toggle HTML Source": "Ver Documento en HTML",
+  "Enlarge Editor": "Ampliar Editor",
+  "About this editor": "Acerca del Editor",
+  "Help using editor": "Ayuda",
+  "Current style": "Estilo Actual",
+  "Undoes your last action": "Deshacer",
+  "Redoes your last action": "Rehacer",
+  "Cut selection": "Cortar selecci?n",
+  "Copy selection": "Copiar selecci?n",
+  "Paste from clipboard": "Pegar desde el portapapeles",
+  "OK": "Aceptar",
+  "Cancel": "Cancelar",
+  "Path": "Ruta",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Esta en modo TEXTO. Use el boton [<>] para cambiar a WYSIWIG"
+}

Added: plog/trunk/js/xinha/lang/fi.js
===================================================================
--- plog/trunk/js/xinha/lang/fi.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/fi.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,38 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8
+
+{
+  "Bold": "Lihavoitu",
+  "Italic": "Kursivoitu",
+  "Underline": "Alleviivattu",
+  "Strikethrough": "Yliviivattu",
+  "Subscript": "Alaindeksi",
+  "Superscript": "Yläindeksi",
+  "Justify Left": "Tasaa vasemmat reunat",
+  "Justify Center": "Keskitä",
+  "Justify Right": "Tasaa oikeat reunat",
+  "Justify Full": "Tasaa molemmat reunat",
+  "Ordered List": "Numerointi",
+  "Bulleted List": "Luettelomerkit",
+  "Decrease Indent": "Lisää sisennystä",
+  "Increase Indent": "Pienennä sisennystä",
+  "Font Color": "Fontin väri",
+  "Background Color": "Taustaväri",
+  "Horizontal Rule": "Vaakaviiva",
+  "Insert Web Link": "Lisää Linkki",
+  "Insert/Modify Image": "Lisää Kuva",
+  "Insert Table": "Lisää Taulu",
+  "Toggle HTML Source": "HTML Lähdekoodi vs WYSIWYG",
+  "Enlarge Editor": "Suurenna Editori",
+  "About this editor": "Tietoja Editorista",
+  "Help using editor": "Näytä Ohje",
+  "Current style": "Nykyinen tyyli",
+  "Undoes your last action": "Peruuta viimeinen toiminto",
+  "Redoes your last action": "Palauta viimeinen toiminto",
+  "Cut selection": "Leikkaa maalattu",
+  "Copy selection": "Kopioi maalattu",
+  "Paste from clipboard": "Liitä leikepyödältä",
+  "OK": "Hyväksy",
+  "Cancel": "Peruuta"
+}

Added: plog/trunk/js/xinha/lang/fr.js
===================================================================
--- plog/trunk/js/xinha/lang/fr.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/fr.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,129 @@
+// I18N constants
+// LANG: "fr", ENCODING: UTF-8
+{
+  "Bold": "Gras",
+  "Italic": "Italique",
+  "Underline": "Souligné",
+  "Strikethrough": "Barré",
+  "Subscript": "Indice",
+  "Superscript": "Exposant",
+  "Justify Left": "Aligner à gauche",
+  "Justify Center": "Centrer",
+  "Justify Right": "Aligner à droite",
+  "Justify Full": "Justifier",
+  "Ordered List": "Numérotation",
+  "Bulleted List": "Puces",
+  "Decrease Indent": "Diminuer le retrait",
+  "Increase Indent": "Augmenter le retrait",
+  "Font Color": "Couleur de police",
+  "Background Color": "Surlignage",
+  "Horizontal Rule": "Ligne horizontale",
+  "Insert Web Link": "Insérer un lien",
+  "Insert/Modify Image": "Insérer / Modifier une image",
+  "Insert Table": "Insérer un tableau",
+  "Toggle HTML Source": "Afficher / Masquer code source",
+  "Enlarge Editor": "Agrandir l'éditeur",
+  "About this editor": "A propos",
+  "Help using editor": "Aide",
+  "Current style": "Style courant",
+  "Undoes your last action": "Annuler la dernière action",
+  "Redoes your last action": "Répéter la dernière action",
+  "Cut selection": "Couper la sélection",
+  "Copy selection": "Copier la sélection",
+  "Paste from clipboard": "Coller depuis le presse-papier",
+  "Direction left to right": "Direction de gauche à droite",
+  "Direction right to left": "Direction de droite à gauche",
+  "Remove formatting": "Supprimer mise en forme",
+  "Select all": "Tout sélectionner",
+  "Print document": "Imprimer document",
+  "Clear MSOffice tags": "Effacer tags MSOffice",
+  "Clear Inline Font Specifications": "Supprimer paramètres inline de la fonte",
+  "Split Block": "Séparer les blocks",
+  "Toggle Borders": "Afficher / Masquer les bordures",
+  "Save as": "Enregistrer sous",
+  "Insert/Overwrite": "Insertion / Remplacement",
+  "&mdash; format &mdash;": "&mdash; Format &mdash;",
+  "Heading 1": "Titre 1",
+  "Heading 2": "Titre 2",
+  "Heading 3": "Titre 3",
+  "Heading 4": "Titre 4",
+  "Heading 5": "Titre 5",
+  "Heading 6": "Titre 6",
+  "Normal": "Normal",
+  "Address": "Adresse",
+  "Formatted": "Formaté",
+  
+  //dialogs
+  "OK": "OK",
+  "Cancel": "Annuler",
+  "Path": "Chemin",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Vous êtes en MODE TEXTE.  Appuyez sur le bouton [<>] pour retourner au mode WYSIWYG.",
+  "The Paste button does not work in Mozilla based web browsers (technical security reasons). Press CTRL-V on your keyboard to paste directly.": "Le bouton Coller ne fonctionne pas sur les navigateurs basés sur Mozilla (pour des raisons de sécurité). Pressez simplement CTRL-V au clavier pour coller directement.",
+  "Your Document is not well formed. Check JavaScript console for details.": "Le document est mal formé. Vérifiez la console JavaScript pour plus de détail.",
+  
+  "Alignment:": "Alignement",
+  "Not set": "Indéfini",
+  "Left": "Gauche",
+  "Right": "Droite",
+  "Texttop": "Texttop",
+  "Absmiddle": "Absmiddle",
+  "Baseline": "Baseline",
+  "Absbottom": "Absbottom",
+  "Bottom": "Bas",
+  "Middle": "Milieu",
+  "Top": "Haut",
+  
+  "Layout": "Mise en page",
+  "Spacing": "Espacement",
+  "Horizontal:": "Horizontal",
+  "Horizontal padding": "Marge horizontale interne",
+  "Vertical:": "Vertical",
+  "Vertical padding": "Marge verticale interne",
+  "Border thickness:": "Epaisseur bordure",
+  "Leave empty for no border": "Laisser vide pour pas de bordure",
+  
+  //Insert Link
+  "Insert/Modify Link": "Insérer / Modifier un lien",
+  "None (use implicit)": "Aucune (implicite)",
+  "New window (_blank)": "Nouvelle fenêtre (_blank)",
+  "Same frame (_self)": "Même frame (_self)",
+  "Top frame (_top)": "Frame principale (_top)",
+  "Other": "Autre",
+  "Target:": "Cible",
+  "Title (tooltip):": "Text alternatif",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "Vous devez entrer l'URL de ce lien",
+  
+  // Insert Table
+  "Insert Table": "Insérer un tableau",
+  "Rows:": "Lignes",
+  "Number of rows": "Nombre de lignes",
+  "Cols:": "Colonnes",
+  "Number of columns": "Nombre de colonnes",
+  "Width:": "Largeur",
+  "Width of the table": "Largeur du tableau",
+  "Percent": "Pourcent",
+  "Pixels": "Pixels",
+  "Em": "Em",
+  "Width unit": "Unités de largeur",
+  "Fixed width columns": "Colonnes à taille fixe",
+  "Positioning of this table": "Position du tableau",
+  "Cell spacing:": "Espacement",
+  "Space between adjacent cells": "Espace entre les cellules adjacentes",
+  "Cell padding:": "Marge interne",
+  "Space between content and border in cell": "Espace entre le contenu et la bordure d'une cellule",
+  "You must enter a number of rows": "Vous devez entrez le nombre de lignes",
+  "You must enter a number of columns": "Vous devez entrer le nombre de colonnes",
+  
+  // Insert Image
+  "Insert Image": "Insérer une image",
+  "Image URL:": "URL image",
+  "Enter the image URL here": "Entrer l'url de l'image ici",
+  "Preview": "Prévisualiser",
+  "Preview the image in a new window": "Prévisualiser l'image dans une nouvelle fenêtre",
+  "Alternate text:": "Text alternatif",
+  "For browsers that don't support images": "Pour les navigateurs qui ne supportent pas les images",
+  "Positioning of this image": "Position de l'image",
+  "Image Preview:": "Prévisualisation",
+  "You must enter the URL": "Vous devez entrer l'URL"
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/lang/gb.js
===================================================================
--- plog/trunk/js/xinha/lang/gb.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/gb.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,29 @@
+// I18N constants -- Chinese GB
+// by Dave Lo -- dlo at interactivetools.com
+{
+  "Bold": "粗体",
+  "Italic": "斜体",
+  "Underline": "底线",
+  "Strikethrough": "删除线",
+  "Subscript": "下标",
+  "Superscript": "上标",
+  "Justify Left": "位置靠左",
+  "Justify Center": "位置居中",
+  "Justify Right": "位置靠右",
+  "Justify Full": "位置左右平等",
+  "Ordered List": "顺序清单",
+  "Bulleted List": "无序清单",
+  "Decrease Indent": "减小行前空白",
+  "Increase Indent": "加宽行前空白",
+  "Font Color": "文字颜色",
+  "Background Color": "背景颜色",
+  "Horizontal Rule": "水平线",
+  "Insert Web Link": "插入连结",
+  "Insert/Modify Image": "插入图形",
+  "Insert Table": "插入表格",
+  "Toggle HTML Source": "切换HTML原始码",
+  "Enlarge Editor": "放大",
+  "About this editor": "关於 HTMLArea",
+  "Help using editor": "说明",
+  "Current style": "字体例子"
+}

Added: plog/trunk/js/xinha/lang/he.js
===================================================================
--- plog/trunk/js/xinha/lang/he.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/he.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,64 @@
+// I18N constants
+
+// LANG: "he", ENCODING: UTF-8
+// Author: Liron Newman, http://www.eesh.net, <plastish at ultinet dot org>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Bold": "מודגש",
+  "Italic": "נטוי",
+  "Underline": "קו תחתי",
+  "Strikethrough": "קו אמצע",
+  "Subscript": "כתב עילי",
+  "Superscript": "כתב תחתי",
+  "Justify Left": " ישור לשמאל",
+  "Justify Center": "ישור למרכז",
+  "Justify Right": "ישור לימין",
+  "Justify Full": "ישור לשורה מלאה",
+  "Ordered List": "רשימה ממוספרת",
+  "Bulleted List": "רשימה לא ממוספרת",
+  "Decrease Indent": "הקטן כניסה",
+  "Increase Indent": "הגדל כניסה",
+  "Font Color": "צבע גופן",
+  "Background Color": "צבע רקע",
+  "Horizontal Rule": "קו אנכי",
+  "Insert Web Link": "הכנס היפר-קישור",
+  "Insert/Modify Image": "הכנס/שנה תמונה",
+  "Insert Table": "הכנס טבלה",
+  "Toggle HTML Source": "שנה מצב קוד HTML",
+  "Enlarge Editor": "הגדל את העורך",
+  "About this editor": "אודות עורך זה",
+  "Help using editor": "עזרה לשימוש בעורך",
+  "Current style": "סגנון נוכחי",
+  "Undoes your last action": "מבטל את פעולתך האחרונה",
+  "Redoes your last action": "מבצע מחדש את הפעולה האחרונה שביטלת",
+  "Cut selection": "גזור בחירה",
+  "Copy selection": "העתק בחירה",
+  "Paste from clipboard": "הדבק מהלוח",
+  "Direction left to right": "כיוון משמאל לימין",
+  "Direction right to left": "כיוון מימין לשמאל",
+  "OK": "אישור",
+  "Cancel": "ביטול",
+  "Path": "נתיב עיצוב",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "אתה במצב טקסט נקי (קוד). השתמש בכפתור [<>] כדי לחזור למצב WYSIWYG (תצוגת עיצוב).",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "מצב מסך מלא יוצר בעיות בדפדפן Internet Explorer, עקב באגים בדפדפן לא יכולנו לפתור את זה.  את/ה עלול/ה לחוות תצוגת זבל,  בעיות בתפקוד העורך ו/או קריסה של הדפדפן.  אם המערכת שלך היא Windows 9x סביר להניח שתקבל/י ",
+  "Cancel": "ביטול",
+  "Insert/Modify Link": "הוסף/שנה קישור",
+  "New window (_blank)": "חלון חדש (_blank)",
+  "None (use implicit)": "ללא (השתמש ב-frame הקיים)",
+  "Other": "אחר",
+  "Same frame (_self)": "אותו frame (_self)",
+  "Target:": "יעד:",
+  "Title (tooltip):": "כותרת (tooltip):",
+  "Top frame (_top)": "Frame עליון (_top)",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "חובה לכתוב URL שאליו קישור זה מצביע"
+}

Added: plog/trunk/js/xinha/lang/hu.js
===================================================================
--- plog/trunk/js/xinha/lang/hu.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/hu.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,64 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine at vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Bold": "Félkövér",
+  "Italic": "DÅ‘lt",
+  "Underline": "Aláhúzott",
+  "Strikethrough": "Áthúzott",
+  "Subscript": "Alsó index",
+  "Superscript": "Felső index",
+  "Justify Left": "Balra zárt",
+  "Justify Center": "Középre zárt",
+  "Justify Right": "Jobbra zárt",
+  "Justify Full": "Sorkizárt",
+  "Ordered List": "Számozott lista",
+  "Bulleted List": "Számozatlan lista",
+  "Decrease Indent": "Behúzás csökkentése",
+  "Increase Indent": "Behúzás növelése",
+  "Font Color": "Karakterszín",
+  "Background Color": "Háttérszín",
+  "Horizontal Rule": "Elválasztó vonal",
+  "Insert Web Link": "Hiperhivatkozás beszúrása",
+  "Insert/Modify Image": "Kép beszúrása",
+  "Insert Table": "Táblázat beszúrása",
+  "Toggle HTML Source": "HTML forrás be/ki",
+  "Enlarge Editor": "Szerkesztő külön ablakban",
+  "About this editor": "Névjegy",
+  "Help using editor": "Súgó",
+  "Current style": "Aktuális stílus",
+  "Undoes your last action": "Visszavonás",
+  "Redoes your last action": "Újra végrehajtás",
+  "Cut selection": "Kivágás",
+  "Copy selection": "Másolás",
+  "Paste from clipboard": "Beillesztés",
+  "Direction left to right": "Irány balról jobbra",
+  "Direction right to left": "Irány jobbról balra",
+  "OK": "Rendben",
+  "Cancel": "Mégsem",
+  "Path": "Hierarchia",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Forrás mód. Visszaváltás [<>] gomb",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "A teljesképrenyős szerkesztés hibát okozhat Internet Explorer használata esetén, ez a böngésző a hibája, amit nem tudunk kikerülni. Szemetet észlelhet a képrenyőn, illetve néhány funkció hiányozhat és/vagy véletlenszerűen lefagyhat a böngésző. Windows 9x operaciós futtatása esetén elég valószínű, hogy ",
+  "Cancel": "Mégsem",
+  "Insert/Modify Link": "Hivatkozás Beszúrása/Módosítása",
+  "New window (_blank)": "Új ablak (_blank)",
+  "None (use implicit)": "Nincs (use implicit)",
+  "Other": "Más",
+  "Same frame (_self)": "Ugyanabba a keretbe (_self)",
+  "Target:": "Cél:",
+  "Title (tooltip):": "Cím (tooltip):",
+  "Top frame (_top)": "Felső keret (_top)",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "Be kell írnia az URL-t, ahova a hivatkozás mutasson"
+}

Added: plog/trunk/js/xinha/lang/it.js
===================================================================
--- plog/trunk/js/xinha/lang/it.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/it.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,55 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8
+// Author: Mattia Landoni, http://www.webpresident.org/
+
+{
+  "Bold": "Grassetto",
+  "Italic": "Corsivo",
+  "Underline": "Sottolineato",
+  "Strikethrough": "Barrato",
+  "Subscript": "Pedice",
+  "Superscript": "Apice",
+  "Justify Left": "Sinistra",
+  "Justify Center": "Centrato",
+  "Justify Right": "Destra",
+  "Justify Full": "Giustificato",
+  "Ordered List": "Lista numerata",
+  "Bulleted List": "Lista non numerata",
+  "Decrease Indent": "Diminuisci indentazione",
+  "Increase Indent": "Aumenta indentazione",
+  "Font Color": "Colore font",
+  "Background Color": "Colore sfondo",
+  "Horizontal Rule": "Righello orizzontale",
+  "Insert Web Link": "Inserisci link",
+  "Insert/Modify Image": "Inserisci/modifica Immagine",
+  "Insert Table": "Inserisci tabella",
+  "Toggle HTML Source": "Visualizza/nascondi sorgente HTML",
+  "Enlarge Editor": "Allarga editor",
+  "About this editor": "Informazioni su HTMLArea",
+  "Help using editor": "Aiuto",
+  "Current style": "Stile corrente",
+  "Undoes your last action": "Annulla ultima azione",
+  "Redoes your last action": "Ripeti ultima azione",
+  "Cut selection": "Taglia",
+  "Copy selection": "Copia",
+  "Paste from clipboard": "Incolla",
+  "Direction left to right": "Testo da sx a dx",
+  "Direction right to left": "Testo da dx a sx",
+  "OK": "OK",
+  "Cancel": "Annulla",
+  "Path": "Percorso",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Sei in MODALITA",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "E",
+  "Cancel": "Annulla",
+  "Insert/Modify Link": "Inserisci/modifica link",
+  "New window (_blank)": "Nuova finestra (_blank)",
+  "None (use implicit)": "Niente (usa implicito)",
+  "Other": "Altro",
+  "Same frame (_self)": "Stessa frame (_self)",
+  "Target:": "Target:",
+  "Title (tooltip):": "Title (suggerimento):",
+  "Top frame (_top)": "Pagina intera (_top)",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "Devi inserire l'indirizzo a cui punta il link"
+}

Added: plog/trunk/js/xinha/lang/ja.js
===================================================================
--- plog/trunk/js/xinha/lang/ja.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/ja.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,30 @@
+// I18N constants -- Japanese UTF-8
+// by Manabu Onoue -- tmocsys at tmocsys.com
+
+{
+  "Bold": "太字",
+  "Italic": "斜体",
+  "Underline": "下線",
+  "Strikethrough": "打ち消し線",
+  "Subscript": "下付き添え字",
+  "Superscript": "上付き添え字",
+  "Justify Left": "左寄せ",
+  "Justify Center": "中央寄せ",
+  "Justify Right": "右寄せ",
+  "Justify Full": "均等割付",
+  "Ordered List": "番号付き箇条書き",
+  "Bulleted List": "記号付き箇条書き",
+  "Decrease Indent": "インデント解除",
+  "Increase Indent": "インデント設定",
+  "Font Color": "文字色",
+  "Background Color": "背景色",
+  "Horizontal Rule": "水平線",
+  "Insert Web Link": "リンク作成",
+  "Insert/Modify Image": "画像挿入",
+  "Insert Table": "テーブル挿入",
+  "Toggle HTML Source": "HTML表示切替",
+  "Enlarge Editor": "エディタ拡大",
+  "About this editor": "バージョン情報",
+  "Help using editor": "ヘルプ",
+  "Current style": "現在のスタイル"
+}

Added: plog/trunk/js/xinha/lang/lt.js
===================================================================
--- plog/trunk/js/xinha/lang/lt.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/lt.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,53 @@
+// I18N constants
+
+// LANG: "lt", ENCODING: UTF-8
+// Author: Jaroslav Šatkevič, <jaro at akl.lt>
+
+{
+  "Bold": "Paryškinti",
+  "Italic": "Kursyvas",
+  "Underline": "Pabraukti",
+  "Strikethrough": "Perbraukti",
+  "Subscript": "Apatinis indeksas",
+  "Superscript": "Viršutinis indeksas",
+  "Justify Left": "Lygiavimas pagal kairÄ™",
+  "Justify Center": "Lygiavimas pagal centrÄ…",
+  "Justify Right": "Lygiavimas pagal dešinę",
+  "Justify Full": "Lygiuoti pastraipÄ…",
+  "Ordered List": "Numeruotas sąrašas",
+  "Bulleted List": "Suženklintas sąrašas",
+  "Decrease Indent": "Sumažinti paraštę",
+  "Increase Indent": "Padidinti paraštę",
+  "Font Color": "Å rifto spalva",
+  "Background Color": "Fono spalva",
+  "Horizontal Rule": "Horizontali linija",
+  "Insert Web Link": "Įterpti nuorodą",
+  "Insert/Modify Image": "Įterpti paveiksliuką",
+  "Insert Table": "Įterpti lentelę",
+  "Toggle HTML Source": "Perjungti į HTML/WYSIWYG",
+  "Enlarge Editor": "IÅ¡plÄ—stas redagavimo ekranas/Enlarge Editor",
+  "About this editor": "Apie redaktorių",
+  "Help using editor": "Pagalba naudojant redaktorių",
+  "Current style": "Dabartinis stilius",
+  "Undoes your last action": "Atšaukia paskutini jūsų veiksmą",
+  "Redoes your last action": "Pakartoja paskutinį atšauktą jūsų veiksmą",
+  "Cut selection": "IÅ¡kirpti",
+  "Copy selection": "Kopijuoti",
+  "Paste from clipboard": "Įterpti",
+  "OK": "OK",
+  "Cancel": "Atšaukti",
+  "Path": "Kelias",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Jūs esete teksto režime.  Naudokite [<>] mygtuką grįžimui į WYSIWYG.",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren",
+  "Cancel": "Atšaukti",
+  "Insert/Modify Link": "IdÄ—ti/Modifikuoti",
+  "New window (_blank)": "Naujas langas (_blank)",
+  "None (use implicit)": "None (use implicit)",
+  "Other": "Kitas",
+  "Same frame (_self)": "Same frame (_self)",
+  "Target:": "Target:",
+  "Title (tooltip):": "Pavadinimas (tooltip):",
+  "Top frame (_top)": "Top frame (_top)",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "Jus privalote nurodyti URL į kuri rodo šitą nuoroda"
+}

Added: plog/trunk/js/xinha/lang/lv.js
===================================================================
--- plog/trunk/js/xinha/lang/lv.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/lv.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,42 @@
+// I18N constants
+
+// LANG: "lv", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+// Translated by: Janis Klavins, <janis.klavins at devia.lv>
+
+{
+  "Bold": "Trekniem burtiem",
+  "Italic": "Kursîvâ",
+  "Underline": "Pasvîtrots",
+  "Strikethrough": "Pârsvîtrots",
+  "Subscript": "Novietot zem rindas",
+  "Superscript": "Novietot virs rindas",
+  "Justify Left": "Izlîdzinât pa kreisi",
+  "Justify Center": "Izlîdzinât centrâ",
+  "Justify Right": "Izlîdzinât pa labi",
+  "Justify Full": "Izlîdzinât pa visu lapu",
+  "Ordered List": "Numurçts saraksts",
+  "Bulleted List": "Saraksts",
+  "Decrease Indent": "Samazinât atkâpi",
+  "Increase Indent": "Palielinât atkâpi",
+  "Font Color": "Burtu krâsa",
+  "Background Color": "Fona krâsa",
+  "Horizontal Rule": "Horizontâla atdalîtâjsvîtra",
+  "Insert Web Link": "Ievietot hipersaiti",
+  "Insert/Modify Image": "Ievietot attçlu",
+  "Insert Table": "Ievietot tabulu",
+  "Toggle HTML Source": "Skatît HTML kodu",
+  "Enlarge Editor": "Palielinât Rediìçtâju",
+  "About this editor": "Par ðo rediìçtâju",
+  "Help using editor": "Rediìçtâja palîgs",
+  "Current style": "Patreizçjais stils",
+  "Undoes your last action": "Atcelt pçdçjo darbîbu",
+  "Redoes your last action": "Atkârtot pçdçjo darbîbu",
+  "Cut selection": "Izgriezt iezîmçto",
+  "Copy selection": "Kopçt iezîmçto",
+  "Paste from clipboard": "Ievietot iezîmçto",
+  "OK": "Labi",
+  "Cancel": "Atcelt",
+  "Path": "Ceïð",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Jûs patlaban darbojaties TEKSTA REÞÎMÂ. Lai pârietu atpakaï uz GRAFISKO REÞÎMU (WYSIWIG), lietojiet [<>] pogu."
+}

Added: plog/trunk/js/xinha/lang/nb.js
===================================================================
--- plog/trunk/js/xinha/lang/nb.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/nb.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,31 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8
+
+{
+  "Bold": "Fet",
+  "Italic": "Kursiv",
+  "Underline": "Understreket",
+  "Strikethrough": "Gjennomstreket",
+  "Subscript": "Senket",
+  "Superscript": "Hevet",
+  "Justify Left": "Venstrejuster",
+  "Justify Center": "Midtjuster",
+  "Justify Right": "Høyrejuster",
+  "Justify Full": "Blokkjuster",
+  "Ordered List": "Nummerert liste",
+  "Bulleted List": "Punktmerket liste",
+  "Decrease Indent": "Øke innrykk",
+  "Increase Indent": "Reduser innrykk",
+  "Font Color": "Skriftfarge",
+  "Background Color": "Bakgrunnsfarge",
+  "Horizontal Rule": "Horisontal linje",
+  "Insert Web Link": "Sett inn lenke",
+  "Insert/Modify Image": "Sett inn bilde",
+  "Insert Table": "Sett inn tabell",
+  "Toggle HTML Source": "Vis HTML kode",
+  "Enlarge Editor": "Forstørr redigeringsvindu",
+  "About this editor": "Om..",
+  "Help using editor": "Hjelp",
+  "Current style": "Gjeldende stil"
+}

Added: plog/trunk/js/xinha/lang/nl.js
===================================================================
--- plog/trunk/js/xinha/lang/nl.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/nl.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,64 @@
+// I18N constants
+
+// LANG: "nl", ENCODING: UTF-8
+// Author: Michel Weegeerink (info at mmc-shop.nl), http://mmc-shop.nl
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Bold": "Vet",
+  "Italic": "Cursief",
+  "Underline": "Onderstrepen",
+  "Strikethrough": "Doorhalen",
+  "Subscript": "Subscript",
+  "Superscript": "Superscript",
+  "Justify Left": "Links uitlijnen",
+  "Justify Center": "Centreren",
+  "Justify Right": "Rechts uitlijnen",
+  "Justify Full": "Uitvullen",
+  "Ordered List": "Nummering",
+  "Bulleted List": "Opsommingstekens",
+  "Decrease Indent": "Inspringing verkleinen",
+  "Increase Indent": "Inspringing vergroten",
+  "Font Color": "Tekstkleur",
+  "Background Color": "Achtergrondkleur",
+  "Horizontal Rule": "Horizontale lijn",
+  "Insert Web Link": "Hyperlink invoegen/aanpassen",
+  "Insert/Modify Image": "Afbeelding invoegen/aanpassen",
+  "Insert Table": "Tabel invoegen",
+  "Toggle HTML Source": "HTML broncode",
+  "Enlarge Editor": "Vergroot Editor",
+  "About this editor": "Over deze editor",
+  "Help using editor": "HTMLArea help",
+  "Current style": "Huidige stijl",
+  "Undoes your last action": "Ongedaan maken",
+  "Redoes your last action": "Herhalen",
+  "Cut selection": "Knippen",
+  "Copy selection": "Kopi?ren",
+  "Paste from clipboard": "Plakken",
+  "Direction left to right": "Tekstrichting links naar rechts",
+  "Direction right to left": "Tekstrichting rechts naar links",
+  "OK": "OK",
+  "Cancel": "Annuleren",
+  "Path": "Pad",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Je bent in TEKST-mode. Gebruik de [<>] knop om terug te keren naar WYSIWYG-mode.",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Fullscreen-mode veroorzaakt problemen met Internet Explorer door bugs in de webbrowser die we niet kunnen omzeilen. Hierdoor kunnen de volgende effecten optreden: verknoeide teksten, een verlies aan editor-functionaliteit en/of willekeurig vastlopen van de webbrowser. Als u Windows 95 of 98 gebruikt, is het zeer waarschijnlijk dat u een algemene beschermingsfout (",
+  "Cancel": "Annuleren",
+  "Insert/Modify Link": "Hyperlink invoegen/aanpassen",
+  "New window (_blank)": "Nieuw venster (_blank)",
+  "None (use implicit)": "Geen",
+  "Other": "Ander",
+  "Same frame (_self)": "Zelfde frame (_self)",
+  "Target:": "Doel:",
+  "Title (tooltip):": "Titel (tooltip):",
+  "Top frame (_top)": "Bovenste frame (_top)",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "Geef de URL in waar de link naar verwijst"
+}

Added: plog/trunk/js/xinha/lang/no.js
===================================================================
--- plog/trunk/js/xinha/lang/no.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/no.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,61 @@
+// I18N constants
+
+// LANG: "no", ENCODING: UTF-8
+
+// - translated by ses<ses at online.no>
+// Additional translations by HÃ¥vard Wigtil <havardw at extend.no>
+// Additional translations by Kim Steinhaug <kim at steinhaug.com>
+
+{
+  "Bold": "Fet",
+  "Italic": "Kursiv",
+  "Underline": "Understreket",
+  "Strikethrough": "Gjennomstreket",
+  "Subscript": "Nedsenket",
+  "Superscript": "Opphøyet",
+  "Justify Left": "Venstrejuster",
+  "Justify Center": "Midtjuster",
+  "Justify Right": "Høyrejuster",
+  "Justify Full": "Blokkjuster",
+  "Ordered List": "Nummerert liste",
+  "Bulleted List": "Punktliste",
+  "Decrease Indent": "Reduser innrykk",
+  "Increase Indent": "Øke innrykk",
+  "Font Color": "Tekstfarge",
+  "Background Color": "Bakgrundsfarge",
+  "Horizontal Rule": "Vannrett linje",
+  "Insert Web Link": "Lag lenke",
+  "Insert/Modify Image": "Sett inn bilde",
+  "Insert Table": "Sett inn tabell",
+  "Toggle HTML Source": "Vis kildekode",
+  "Enlarge Editor": "Vis i eget vindu",
+  "About this editor": "Om denne editor",
+  "Help using editor": "Hjelp",
+  "Current style": "Nåværende stil",
+  "Undoes your last action": "Angrer siste redigering",
+  "Redoes your last action": "Gjør om siste angring",
+  "Cut selection": "Klipp ut område",
+  "Copy selection": "Kopier område",
+  "Save as": "Lagre som",
+  "Paste from clipboard": "Lim inn",
+  "Remove formatting": "Fjern formattering",
+  "Direction left to right": "Fra venstre mot høyre",
+  "Direction right to left": "Fra høyre mot venstre",
+  "Insert/Overwrite": "Sett inn/Overskriv",
+  "OK": "OK",
+  "Cancel": "Avbryt",
+  "Path": "Tekstvelger",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Du er i tekstmodus  Klikk på [<>] for å gå tilbake til WYSIWIG.",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Visning i eget vindu har kjente problemer med Internet Explorer, på grunn av problemer med denne nettleseren. Mulige problemer er et uryddig skjermbilde, manglende editorfunksjoner og/eller at nettleseren crasher. Hvis du bruker Windows 95 eller Windows 98 er det også muligheter for at Windows will crashe.\n\nTrykk ",
+  "Cancel": "Avbryt",
+  "Insert/Modify Link": "Rediger lenke",
+  "New window (_blank)": "Eget vindu (_blank)",
+  "None (use implicit)": "Ingen (bruk standardinnstilling)",
+  "Other": "Annen",
+  "Same frame (_self)": "Samme ramme (_self)",
+  "Target:": "MÃ¥l:",
+  "Title (tooltip):": "Tittel (tooltip):",
+  "Top frame (_top)": "Toppramme (_top)",
+  "URL:": "Adresse:",
+  "You must enter the URL where this link points to": "Du må skrive inn en adresse som denne lenken skal peke til"
+}

Added: plog/trunk/js/xinha/lang/pl.js
===================================================================
--- plog/trunk/js/xinha/lang/pl.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/pl.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,32 @@
+// I18N constants
+
+// LANG: "pl", ENCODING: UTF-8
+
+
+{
+  "Bold": "Pogrubienie",
+  "Italic": "Pochylenie",
+  "Underline": "PodkreÂœlenie",
+  "Strikethrough": "PrzekreÂœlenie",
+  "Subscript": "Indeks dolny",
+  "Superscript": "Indeks górny",
+  "Justify Left": "Wyrównaj do lewej",
+  "Justify Center": "WyÂœrodkuj",
+  "Justify Right": "Wyrównaj do prawej",
+  "Justify Full": "Wyjustuj",
+  "Ordered List": "Numerowanie",
+  "Bulleted List": "Wypunktowanie",
+  "Decrease Indent": "Zmniejsz wcięcie",
+  "Increase Indent": "Zwiększ wcięcie",
+  "Font Color": "Kolor czcionki",
+  "Background Color": "Kolor tła",
+  "Horizontal Rule": "Linia pozioma",
+  "Insert Web Link": "Wstaw adres sieci Web",
+  "Insert/Modify Image": "Wstaw obraz",
+  "Insert Table": "Wstaw tabelÄ™",
+  "Toggle HTML Source": "Edycja WYSIWYG/w Ÿródle strony",
+  "Enlarge Editor": "Pełny ekran",
+  "About this editor": "Informacje o tym edytorze",
+  "Help using editor": "Pomoc",
+  "Current style": "Obecny styl"
+}

Added: plog/trunk/js/xinha/lang/pt_br.js
===================================================================
--- plog/trunk/js/xinha/lang/pt_br.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/pt_br.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,32 @@
+// I18N constants
+
+// LANG: "bt_br", ENCODING: UTF-8
+// Brazilian Portuguese Translation by Alex Piaz <webmaster at globalmap.com>
+
+{
+  "Bold": "Negrito",
+  "Italic": "Itálico",
+  "Underline": "Sublinhado",
+  "Strikethrough": "Tachado",
+  "Subscript": "Subescrito",
+  "Superscript": "Sobrescrito",
+  "Justify Left": "Alinhar à Esquerda",
+  "Justify Center": "Centralizar",
+  "Justify Right": "Alinhar à Direita",
+  "Justify Full": "Justificar",
+  "Ordered List": "Lista Numerada",
+  "Bulleted List": "Lista Marcadores",
+  "Decrease Indent": "Diminuir Indentação",
+  "Increase Indent": "Aumentar Indentação",
+  "Font Color": "Cor da Fonte",
+  "Background Color": "Cor do Fundo",
+  "Horizontal Rule": "Linha Horizontal",
+  "Insert Web Link": "Inserir Link",
+  "Insert/Modify Image": "Inserir Imagem",
+  "Insert Table": "Inserir Tabela",
+  "Toggle HTML Source": "Ver Código-Fonte",
+  "Enlarge Editor": "Expandir Editor",
+  "About this editor": "Sobre",
+  "Help using editor": "Ajuda",
+  "Current style": "Estilo Atual"
+}

Added: plog/trunk/js/xinha/lang/ro.js
===================================================================
--- plog/trunk/js/xinha/lang/ro.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/ro.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "ro", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Bold": "ÃŽngroÅŸat",
+  "Italic": "Italic",
+  "Underline": "Subliniat",
+  "Strikethrough": "Tăiat",
+  "Subscript": "Indice jos",
+  "Superscript": "Indice sus",
+  "Justify Left": "Aliniere la stânga",
+  "Justify Center": "Aliniere pe centru",
+  "Justify Right": "Aliniere la dreapta",
+  "Justify Full": "Aliniere în ambele părţi",
+  "Ordered List": "Listă ordonată",
+  "Bulleted List": "Listă marcată",
+  "Decrease Indent": "Micşorează alineatul",
+  "Increase Indent": "Măreşte alineatul",
+  "Font Color": "Culoarea textului",
+  "Background Color": "Culoare de fundal",
+  "Horizontal Rule": "Linie orizontală",
+  "Insert Web Link": "Inserează/modifică link",
+  "Insert/Modify Image": "Inserează/modifică imagine",
+  "Insert Table": "Inserează un tabel",
+  "Toggle HTML Source": "Sursa HTML / WYSIWYG",
+  "Enlarge Editor": "Maximizează editorul",
+  "About this editor": "Despre editor",
+  "Help using editor": "Documentaţie (devel)",
+  "Current style": "Stilul curent",
+  "Undoes your last action": "Anulează ultima acţiune",
+  "Redoes your last action": "Reface ultima acţiune anulată",
+  "Cut selection": "Taie în clipboard",
+  "Copy selection": "Copie în clipboard",
+  "Paste from clipboard": "Aduce din clipboard",
+  "Direction left to right": "Direcţia de scriere: stânga - dreapta",
+  "Direction right to left": "Direcţia de scriere: dreapta - stânga",
+  "OK": "OK",
+  "Cancel": "Anulează",
+  "Path": "Calea",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Eşti în modul TEXT.  Apasă butonul [<>] pentru a te întoarce în modul WYSIWYG.",
+  "Cancel": "Renunţă",
+  "Insert/Modify Link": "Inserează/modifcă link",
+  "New window (_blank)": "Fereastră nouă (_blank)",
+  "None (use implicit)": "Nimic (foloseÅŸte ce-i implicit)",
+  "Other": "Alt target",
+  "Same frame (_self)": "Aceeaşi fereastră (_self)",
+  "Target:": "Å¢inta:",
+  "Title (tooltip):": "Titlul (tooltip):",
+  "Top frame (_top)": "Fereastra principală (_top)",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "Trebuie să introduceţi un URL"
+}

Added: plog/trunk/js/xinha/lang/ru.js
===================================================================
--- plog/trunk/js/xinha/lang/ru.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/ru.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,50 @@
+// I18N constants
+
+// LANG: "ru", ENCODING: UTF-8
+// Author: Yulya Shtyryakova, <yulya at vdcom.ru>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Bold": "Полужирный",
+  "Italic": "Наклонный",
+  "Underline": "Подчеркнутый",
+  "Strikethrough": "Перечеркнутый",
+  "Subscript": "Нижний индекс",
+  "Superscript": "Верхний индекс",
+  "Justify Left": "По левому краю",
+  "Justify Center": "По центру",
+  "Justify Right": "По правому краю",
+  "Justify Full": "По ширине",
+  "Ordered List": "Нумерованный лист",
+  "Bulleted List": "Маркированный лист",
+  "Decrease Indent": "Уменьшить отступ",
+  "Increase Indent": "Увеличить отступ",
+  "Font Color": "Цвет шрифта",
+  "Background Color": "Цвет фона",
+  "Horizontal Rule": "Горизонтальный разделитель",
+  "Insert Web Link": "Вставить гиперссылку",
+  "Insert/Modify Image": "Вставить изображение",
+  "Insert Table": "Вставить таблицу",
+  "Toggle HTML Source": "Показать Html-код",
+  "Enlarge Editor": "Увеличить редактор",
+  "About this editor": "О редакторе",
+  "Help using editor": "Помощь",
+  "Current style": "Текущий стиль",
+  "Undoes your last action": "Отменить",
+  "Redoes your last action": "Повторить",
+  "Cut selection": "Вырезать",
+  "Copy selection": "Копировать",
+  "Paste from clipboard": "Вставить",
+  "OK": "OK",
+  "Cancel": "Отмена",
+  "Path": "Путь",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Вы в режиме отображения Html-кода. нажмите кнопку [<>], чтобы переключиться в визуальный режим."
+}

Added: plog/trunk/js/xinha/lang/se.js
===================================================================
--- plog/trunk/js/xinha/lang/se.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/se.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,32 @@
+// LANG: "se", ENCODING: UTF-8
+
+// Swedish version for htmlArea v3.0 - Alpha Release
+// - translated by pat<pat at engvall.nu>
+
+{
+  "Bold": "Fet",
+  "Italic": "Kursiv",
+  "Underline": "Understruken",
+  "Strikethrough": "Genomstruken",
+  "Subscript": "Nedsänkt",
+  "Superscript": "Upphöjd",
+  "Justify Left": "Vänsterjustera",
+  "Justify Center": "Centrera",
+  "Justify Right": "Högerjustera",
+  "Justify Full": "Marginaljustera",
+  "Ordered List": "Numrerad lista",
+  "Bulleted List": "Punktlista",
+  "Decrease Indent": "Minska indrag",
+  "Increase Indent": "Öka indrag",
+  "Font Color": "Textfärg",
+  "Background Color": "Bakgrundsfärg",
+  "Horizontal Rule": "Vågrät linje",
+  "Insert Web Link": "Infoga länk",
+  "Insert/Modify Image": "Infoga bild",
+  "Insert Table": "Infoga tabell",
+  "Toggle HTML Source": "Visa källkod",
+  "Enlarge Editor": "Visa i eget fönster",
+  "About this editor": "Om denna editor",
+  "Help using editor": "Hjälp",
+  "Current style": "Nuvarande stil"
+}

Added: plog/trunk/js/xinha/lang/si.js
===================================================================
--- plog/trunk/js/xinha/lang/si.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/si.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,50 @@
+// I18N constants
+
+// LANG: "si", ENCODING: UTF-8
+// Author: Tomaz Kregar, x_tomo_x at email.si
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Bold": "Krepko",
+  "Italic": "Ležeče",
+  "Underline": "Podčrtano",
+  "Strikethrough": "Prečrtano",
+  "Subscript": "Podpisano",
+  "Superscript": "Nadpisano",
+  "Justify Left": "Poravnaj levo",
+  "Justify Center": "Na sredino",
+  "Justify Right": "Poravnaj desno",
+  "Justify Full": "Porazdeli vsebino",
+  "Ordered List": "Oštevilčevanje",
+  "Bulleted List": "Označevanje",
+  "Decrease Indent": "Zmanjšaj zamik",
+  "Increase Indent": "Povečaj zamik",
+  "Font Color": "Barva pisave",
+  "Background Color": "Barva ozadja",
+  "Horizontal Rule": "Vodoravna črta",
+  "Insert Web Link": "Vstavi hiperpovezavo",
+  "Insert/Modify Image": "Vstavi sliko",
+  "Insert Table": "Vstavi tabelo",
+  "Toggle HTML Source": "Preklopi na HTML kodo",
+  "Enlarge Editor": "Povečaj urejevalnik",
+  "About this editor": "Vizitka za urejevalnik",
+  "Help using editor": "Pomoč za urejevalnik",
+  "Current style": "Trenutni slog",
+  "Undoes your last action": "Razveljavi zadnjo akcijo",
+  "Redoes your last action": "Uveljavi zadnjo akcijo",
+  "Cut selection": "Izreži",
+  "Copy selection": "Kopiraj",
+  "Paste from clipboard": "Prilepi",
+  "OK": "V redu",
+  "Cancel": "Prekliči",
+  "Path": "Pot",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Si v tekstovnem načinu.  Uporabi [<>] gumb za prklop nazaj na WYSIWYG."
+}

Added: plog/trunk/js/xinha/lang/vn.js
===================================================================
--- plog/trunk/js/xinha/lang/vn.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/lang/vn.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,56 @@
+// I18N constants : Vietnamese
+// LANG: "en", ENCODING: UTF-8
+// Author: Nguyễn Đình Nam, <hncryptologist at yahoo.com>
+// Modified 21/07/2004 by Phạm Mai Quân <pmquan at 4vn.org>
+
+{
+  "Bold": "Đậm",
+  "Italic": "Nghiêng",
+  "Underline": "Gạch Chân",
+  "Strikethrough": "Gạch Xóa",
+  "Subscript": "Viết Xuống Dưới",
+  "Superscript": "Viết Lên Trên",
+  "Justify Left": "Căn Trái",
+  "Justify Center": "Căn Giữa",
+  "Justify Right": "Căn Phải",
+  "Justify Full": "Căn Đều",
+  "Ordered List": "Danh Sách Có Thứ Tự (1, 2, 3)",
+  "Bulleted List": "Danh Sách Phi Thứ Tự (Chấm đầu dòng)",
+  "Decrease Indent": "Lùi Ra Ngoài",
+  "Increase Indent": "Thụt Vào Trong",
+  "Font Color": "Màu Chữ",
+  "Background Color": "Màu Nền",
+  "Horizontal Rule": "Dòng Kẻ Ngang",
+  "Insert Web Link": "Tạo Liên Kết",
+  "Insert/Modify Image": "Chèn Ảnh",
+  "Insert Table": "Chèn Bảng",
+  "Toggle HTML Source": "Chế Độ Mã HTML",
+  "Enlarge Editor": "Phóng To Ô Soạn Thảo",
+  "About this editor": "Tự Giới Thiệu",
+  "Help using editor": "Giúp Đỡ",
+  "Current style": "Định Dạng Hiện Thời",
+  "Undoes your last action": "Hủy thao tác trước",
+  "Redoes your last action": "Lấy lại thao tác vừa bỏ",
+  "Cut selection": "Cắt",
+  "Copy selection": "Sao chép",
+  "Paste from clipboard": "Dán",
+  "Direction left to right": "Viết từ trái sang phải",
+  "Direction right to left": "Viết từ phải sang trái",
+  "OK": "Đồng ý",
+  "Cancel": "Hủy",
+  "The full screen mode is known to cause problems with Internet Explorer, due to browser bugs that we weren": "Chế độ phóng to ô soạn thảo có thể gây lỗi với Internet Explorer vì một số lỗi của trình duyệt này, vì thế chế độ này có thể sẽ không chạy. Hiển thị không đúng, lộn xộn, không có đầy đủ chức năng, và cũng có thể làm trình duyệt của bạn bị tắt ngang. Nếu bạn đang sử dụng Windows 9x bạn có thể bị báo lỗi ",
+  "Path": "Đường Dẫn",
+  "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.": "Bạn đang ở chế độ text.  Sử dụng nút [<>] để chuyển lại chế độ WYSIWIG.",
+  "Cancel": "Hủy",
+  "Insert/Modify Link": "Thêm/Chỉnh sửa đường dẫn",
+  "New window (_blank)": "Cửa sổ mới (_blank)",
+  "None (use implicit)": "Không (sử dụng implicit)",
+  "OK": "Đồng ý",
+  "Other": "Khác",
+  "Same frame (_self)": "Trên cùng khung (_self)",
+  "Target:": "Nơi hiện thị:",
+  "Title (tooltip):": "Tiêu đề (của hướng dẫn):",
+  "Top frame (_top)": "Khung trên cùng (_top)",
+  "URL:": "URL:",
+  "You must enter the URL where this link points to": "Bạn phải điền địa chỉ (URL) mà đường dẫn sẽ liên kết tới"
+}

Added: plog/trunk/js/xinha/license.txt
===================================================================
--- plog/trunk/js/xinha/license.txt	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/license.txt	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,30 @@
+htmlArea License (based on BSD license)
+Copyright (c) 2002-2004, interactivetools.com, inc.
+Copyright (c) 2003-2004 dynarch.com
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1) Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2) Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3) Neither the name of interactivetools.com, inc. nor the names of its
+   contributors may be used to endorse or promote products derived from this
+   software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.

Added: plog/trunk/js/xinha/panel-dialog.js
===================================================================
--- plog/trunk/js/xinha/panel-dialog.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/panel-dialog.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,76 @@
+
+HTMLArea.PanelDialog = function(editor, side, html, localizer)
+{
+  this.id    = { };
+  this.r_id  = { }; // reverse lookup id
+  this.editor   = editor;
+  this.document = document;
+  this.rootElem = editor.addPanel(side);
+
+  var dialog = this;
+  if(typeof localizer == 'function')
+  {
+    this._lc = localizer;
+  }
+  else if(localizer)
+  {
+    this._lc = function(string)
+    {
+      return HTMLArea._lc(string,localizer);
+    }
+  }
+  else
+  {
+    this._lc = function(string)
+    {
+      return string;
+    }
+  }
+
+  html = html.replace(/\[([a-z0-9_]+)\]/ig,
+                      function(fullString, id)
+                      {
+                        if(typeof dialog.id[id] == 'undefined')
+                        {
+                          dialog.id[id] = HTMLArea.uniq('Dialog');
+                          dialog.r_id[dialog.id[id]] = id;
+                        }
+                        return dialog.id[id];
+                      }
+             ).replace(/<l10n>(.*?)<\/l10n>/ig,
+                       function(fullString,translate)
+                       {
+                         return dialog._lc(translate) ;
+                       }
+             ).replace(/="_\((.*?)\)"/g,
+                       function(fullString, translate)
+                       {
+                         return '="' + dialog._lc(translate) + '"';
+                       }
+             );
+
+  this.rootElem.innerHTML = html;
+}
+
+HTMLArea.PanelDialog.prototype.show = function(values)
+{
+  this.editor.showPanel(this.rootElem);
+}
+
+HTMLArea.PanelDialog.prototype.hide = function()
+{
+  this.editor.hidePanel(this.rootElem);
+  return this.getValues();
+}
+
+HTMLArea.PanelDialog.prototype.onresize   = HTMLArea.Dialog.prototype.onresize;
+
+HTMLArea.PanelDialog.prototype.toggle     = HTMLArea.Dialog.prototype.toggle;
+
+HTMLArea.PanelDialog.prototype.setValues  = HTMLArea.Dialog.prototype.setValues;
+
+HTMLArea.PanelDialog.prototype.getValues  = HTMLArea.Dialog.prototype.getValues;
+
+HTMLArea.PanelDialog.prototype.getElementById    = HTMLArea.Dialog.prototype.getElementById;
+
+HTMLArea.PanelDialog.prototype.getElementsByName = HTMLArea.Dialog.prototype.getElementsByName;

Added: plog/trunk/js/xinha/plugins/ContextMenu/1.pl
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/1.pl	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/1.pl	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,38 @@
+#! /usr/bin/perl -w
+
+use strict;
+
+my $file = 'context-menu.js';
+my $outfile = $file.'-i18n';
+my $langfile = 'en.js';
+
+open FILE, "<$file";
+#open OUTFILE, ">$outfile";
+#open LANGFILE, ">$langfile";
+my %texts = ();
+while (<FILE>) {
+    if (/"(.*?)"/) {
+        my $inline = $_;
+        chomp $inline;
+        my $key = $1;
+        my $val = $1;
+        print "Key: [$key]: ";
+        my $line = <STDIN>;
+        if (defined $line) {
+            chomp $line;
+            if ($line =~ /(\S+)/) {
+                $key = $1;
+                print "-- using $key\n";
+            }
+            $texts{$val} = $key;
+        } else {
+            print " -- skipped...\n";
+        }
+    }
+}
+#close LANGFILE;
+#close OUTFILE;
+close FILE;
+
+print "\n\n\n";
+print '"', join("\"\n\"", sort keys %texts), '"', "\n";

Added: plog/trunk/js/xinha/plugins/ContextMenu/context-menu.js
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/context-menu.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/context-menu.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,448 @@
+// Context Menu Plugin for HTMLArea-3.0
+// Sponsored by www.americanbible.org
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: context-menu.js 262 2005-07-17 00:46:20Z gogo $
+
+HTMLArea.loadStyle("menu.css", "ContextMenu");
+
+function ContextMenu(editor) {
+	this.editor = editor;
+};
+
+ContextMenu._pluginInfo = {
+	name          : "ContextMenu",
+	version       : "1.0",
+	developer     : "Mihai Bazon",
+	developer_url : "http://dynarch.com/mishoo/",
+	c_owner       : "dynarch.com",
+	sponsor       : "American Bible Society",
+	sponsor_url   : "http://www.americanbible.org",
+	license       : "htmlArea"
+};
+
+ContextMenu.prototype.onGenerate = function() {
+	var self = this;
+	var doc = this.editordoc = this.editor._iframe.contentWindow.document;
+	HTMLArea._addEvents(doc, ["contextmenu"],
+			    function (event) {
+				    return self.popupMenu(HTMLArea.is_ie ? self.editor._iframe.contentWindow.event : event);
+			    });
+	this.currentMenu = null;
+};
+
+ContextMenu.prototype.getContextMenu = function(target) {
+	var self = this;
+	var editor = this.editor;
+	var config = editor.config;
+	var menu = [];
+	var tbo = this.editor.plugins.TableOperations;
+	if (tbo) tbo = tbo.instance;
+
+	var selection = editor.hasSelectedText();
+	if (selection)
+		menu.push([ HTMLArea._lc("Cut", "ContextMenu"), function() { editor.execCommand("cut"); }, null, config.btnList["cut"][1] ],
+			  [ HTMLArea._lc("Copy", "ContextMenu"), function() { editor.execCommand("copy"); }, null, config.btnList["copy"][1] ]);
+	menu.push([ HTMLArea._lc("Paste", "ContextMenu"), function() { editor.execCommand("paste"); }, null, config.btnList["paste"][1] ]);
+
+	var currentTarget = target;
+	var elmenus = [];
+
+	var link = null;
+	var table = null;
+	var tr = null;
+	var td = null;
+	var img = null;
+
+	function tableOperation(opcode) {
+		tbo.buttonPress(editor, opcode);
+	};
+
+	function insertPara(after) {
+		var el = currentTarget;
+		var par = el.parentNode;
+		var p = editor._doc.createElement("p");
+		p.appendChild(editor._doc.createElement("br"));
+		par.insertBefore(p, after ? el.nextSibling : el);
+		var sel = editor._getSelection();
+		var range = editor._createRange(sel);
+		if (!HTMLArea.is_ie) {
+			sel.removeAllRanges();
+			range.selectNodeContents(p);
+			range.collapse(true);
+			sel.addRange(range);
+		} else {
+			range.moveToElementText(p);
+			range.collapse(true);
+			range.select();
+		}
+	};
+
+	for (; target; target = target.parentNode) {
+		var tag = target.tagName;
+		if (!tag)
+			continue;
+		tag = tag.toLowerCase();
+		switch (tag) {
+		    case "img":
+			img = target;
+			elmenus.push(null,
+				     [ HTMLArea._lc("_Image Properties...", "ContextMenu"),
+				       function() {
+					       editor._insertImage(img);
+				       },
+				       HTMLArea._lc("Show the image properties dialog", "ContextMenu"),
+				       config.btnList["insertimage"][1] ]
+				);
+			break;
+		    case "a":
+			link = target;
+			elmenus.push(null,
+				     [ HTMLArea._lc("_Modify Link...", "ContextMenu"),
+               function() { editor.config.btnList['createlink'][3](editor); },
+				       HTMLArea._lc("Current URL is", "ContextMenu") + ': ' + link.href,
+				       config.btnList["createlink"][1] ],
+
+				     [ HTMLArea._lc("Chec_k Link...", "ContextMenu"),
+				       function() { window.open(link.href); },
+				       HTMLArea._lc("Opens this link in a new window", "ContextMenu") ],
+
+				     [ HTMLArea._lc("_Remove Link...", "ContextMenu"),
+				       function() {
+					       if (confirm(HTMLArea._lc("Please confirm that you want to unlink this element.", "ContextMenu") + "\n" +
+							   HTMLArea._lc("Link points to:", "ContextMenu") + " " + link.href)) {
+						       while (link.firstChild)
+							       link.parentNode.insertBefore(link.firstChild, link);
+						       link.parentNode.removeChild(link);
+					       }
+				       },
+				       HTMLArea._lc("Unlink the current element", "ContextMenu") ]
+				);
+			break;
+		    case "td":
+			td = target;
+			if (!tbo) break;
+			elmenus.push(null,
+				     [ HTMLArea._lc("C_ell Properties...", "ContextMenu"),
+				       function() { tableOperation("TO-cell-prop"); },
+				       HTMLArea._lc("Show the Table Cell Properties dialog", "ContextMenu"),
+				       config.btnList["TO-cell-prop"][1] ]
+				);
+			break;
+		    case "tr":
+			tr = target;
+			if (!tbo) break;
+			elmenus.push(null,
+				     [ HTMLArea._lc("Ro_w Properties...", "ContextMenu"),
+				       function() { tableOperation("TO-row-prop"); },
+				       HTMLArea._lc("Show the Table Row Properties dialog", "ContextMenu"),
+				       config.btnList["TO-row-prop"][1] ],
+
+				     [ HTMLArea._lc("I_nsert Row Before", "ContextMenu"),
+				       function() { tableOperation("TO-row-insert-above"); },
+				       HTMLArea._lc("Insert a new row before the current one", "ContextMenu"),
+				       config.btnList["TO-row-insert-above"][1] ],
+
+				     [ HTMLArea._lc("In_sert Row After", "ContextMenu"),
+				       function() { tableOperation("TO-row-insert-under"); },
+				       HTMLArea._lc("Insert a new row after the current one", "ContextMenu"),
+				       config.btnList["TO-row-insert-under"][1] ],
+
+				     [ HTMLArea._lc("_Delete Row", "ContextMenu"),
+				       function() { tableOperation("TO-row-delete"); },
+				       HTMLArea._lc("Delete the current row", "ContextMenu"),
+				       config.btnList["TO-row-delete"][1] ]
+				);
+			break;
+		    case "table":
+			table = target;
+			if (!tbo) break;
+			elmenus.push(null,
+				     [ HTMLArea._lc("_Table Properties...", "ContextMenu"),
+				       function() { tableOperation("TO-table-prop"); },
+				       HTMLArea._lc("Show the Table Properties dialog", "ContextMenu"),
+				       config.btnList["TO-table-prop"][1] ],
+
+				     [ HTMLArea._lc("Insert _Column Before", "ContextMenu"),
+				       function() { tableOperation("TO-col-insert-before"); },
+				       HTMLArea._lc("Insert a new column before the current one", "ContextMenu"),
+				       config.btnList["TO-col-insert-before"][1] ],
+
+				     [ HTMLArea._lc("Insert C_olumn After", "ContextMenu"),
+				       function() { tableOperation("TO-col-insert-after"); },
+				       HTMLArea._lc("Insert a new column after the current one", "ContextMenu"),
+				       config.btnList["TO-col-insert-after"][1] ],
+
+				     [ HTMLArea._lc("De_lete Column", "ContextMenu"),
+				       function() { tableOperation("TO-col-delete"); },
+				       HTMLArea._lc("Delete the current column", "ContextMenu"),
+				       config.btnList["TO-col-delete"][1] ]
+				);
+			break;
+		    case "body":
+			elmenus.push(null,
+				     [ HTMLArea._lc("Justify Left", "ContextMenu"),
+				       function() { editor.execCommand("justifyleft"); }, null,
+				       config.btnList["justifyleft"][1] ],
+				     [ HTMLArea._lc("Justify Center", "ContextMenu"),
+				       function() { editor.execCommand("justifycenter"); }, null,
+				       config.btnList["justifycenter"][1] ],
+				     [ HTMLArea._lc("Justify Right", "ContextMenu"),
+				       function() { editor.execCommand("justifyright"); }, null,
+				       config.btnList["justifyright"][1] ],
+				     [ HTMLArea._lc("Justify Full", "ContextMenu"),
+				       function() { editor.execCommand("justifyfull"); }, null,
+				       config.btnList["justifyfull"][1] ]
+				);
+			break;
+		}
+	}
+
+	if (selection && !link)
+		menu.push(null, [ HTMLArea._lc("Make lin_k...", "ContextMenu"),
+           function() { editor.config.btnList['createlink'][3](editor); },
+				  HTMLArea._lc("Create a link", "ContextMenu"),
+				  config.btnList["createlink"][1] ]);
+
+	for (var i = 0; i < elmenus.length; ++i)
+		menu.push(elmenus[i]);
+
+	if (!/html|body/i.test(currentTarget.tagName))
+		menu.push(null,
+			  [ HTMLArea._lc("Remove the $elem Element...", "ContextMenu", {elem: "&lt;" + currentTarget.tagName + "&gt;"}),
+			    function() {
+				    if (confirm(HTMLArea._lc("Please confirm that you want to remove this element:", "ContextMenu") + " " +
+						currentTarget.tagName)) {
+					    var el = currentTarget;
+					    var p = el.parentNode;
+					    p.removeChild(el);
+					    if (HTMLArea.is_gecko) {
+						    if (p.tagName.toLowerCase() == "td" && !p.hasChildNodes())
+							    p.appendChild(editor._doc.createElement("br"));
+						    editor.forceRedraw();
+						    editor.focusEditor();
+						    editor.updateToolbar();
+						    if (table) {
+							    var save_collapse = table.style.borderCollapse;
+							    table.style.borderCollapse = "collapse";
+							    table.style.borderCollapse = "separate";
+							    table.style.borderCollapse = save_collapse;
+						    }
+					    }
+				    }
+			    },
+			    HTMLArea._lc("Remove this node from the document", "ContextMenu") ],
+			  [ HTMLArea._lc("Insert paragraph before", "ContextMenu"),
+			    function() { insertPara(false); },
+			    HTMLArea._lc("Insert a paragraph before the current node", "ContextMenu") ],
+			  [ HTMLArea._lc("Insert paragraph after", "ContextMenu"),
+			    function() { insertPara(true); },
+			    HTMLArea._lc("Insert a paragraph after the current node", "ContextMenu") ]
+			  );
+	return menu;
+};
+
+ContextMenu.prototype.popupMenu = function(ev) {
+	var self = this;
+	if (this.currentMenu)
+		this.currentMenu.parentNode.removeChild(this.currentMenu);
+	function getPos(el) {
+		var r = { x: el.offsetLeft, y: el.offsetTop };
+		if (el.offsetParent) {
+			var tmp = getPos(el.offsetParent);
+			r.x += tmp.x;
+			r.y += tmp.y;
+		}
+		return r;
+	};
+	function documentClick(ev) {
+		ev || (ev = window.event);
+		if (!self.currentMenu) {
+			alert(HTMLArea._lc("How did you get here? (Please report!)", "ContextMenu"));
+			return false;
+		}
+		var el = HTMLArea.is_ie ? ev.srcElement : ev.target;
+		for (; el != null && el != self.currentMenu; el = el.parentNode);
+		if (el == null)
+			self.closeMenu();
+		//HTMLArea._stopEvent(ev);
+		//return false;
+	};
+	var keys = [];
+	function keyPress(ev) {
+		ev || (ev = window.event);
+		HTMLArea._stopEvent(ev);
+		if (ev.keyCode == 27) {
+			self.closeMenu();
+			return false;
+		}
+		var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
+		for (var i = keys.length; --i >= 0;) {
+			var k = keys[i];
+			if (k[0].toLowerCase() == key)
+				k[1].__msh.activate();
+		}
+	};
+	self.closeMenu = function() {
+		self.currentMenu.parentNode.removeChild(self.currentMenu);
+		self.currentMenu = null;
+		HTMLArea._removeEvent(document, "mousedown", documentClick);
+		HTMLArea._removeEvent(self.editordoc, "mousedown", documentClick);
+		if (keys.length > 0)
+			HTMLArea._removeEvent(self.editordoc, "keypress", keyPress);
+		if (HTMLArea.is_ie)
+			self.iePopup.hide();
+	};
+	var target = HTMLArea.is_ie ? ev.srcElement : ev.target;
+     var ifpos = getPos(self.editor._htmlArea);//_iframe);
+	var x = ev.clientX + ifpos.x;
+	var y = ev.clientY + ifpos.y;
+
+	var div;
+	var doc;
+	if (!HTMLArea.is_ie) {
+		doc = document;
+	} else {
+		// IE stinks
+		var popup = this.iePopup = window.createPopup();
+		doc = popup.document;
+		doc.open();
+		doc.write("<html><head><style type='text/css'>@import url(" + _editor_url + "plugins/ContextMenu/menu.css); html, body { padding: 0px; margin: 0px; overflow: hidden; border: 0px; }</style></head><body unselectable='yes'></body></html>");
+		doc.close();
+	}
+	div = doc.createElement("div");
+	if (HTMLArea.is_ie)
+		div.unselectable = "on";
+	div.oncontextmenu = function() { return false; };
+	div.className = "htmlarea-context-menu";
+	if (!HTMLArea.is_ie)
+		div.style.left = div.style.top = "0px";
+	doc.body.appendChild(div);
+
+	var table = doc.createElement("table");
+	div.appendChild(table);
+	table.cellSpacing = 0;
+	table.cellPadding = 0;
+	var parent = doc.createElement("tbody");
+	table.appendChild(parent);
+
+	var options = this.getContextMenu(target);
+	for (var i = 0; i < options.length; ++i) {
+		var option = options[i];
+		var item = doc.createElement("tr");
+		parent.appendChild(item);
+		if (HTMLArea.is_ie)
+			item.unselectable = "on";
+		else item.onmousedown = function(ev) {
+			HTMLArea._stopEvent(ev);
+			return false;
+		};
+		if (!option) {
+			item.className = "separator";
+			var td = doc.createElement("td");
+			td.className = "icon";
+			var IE_IS_A_FUCKING_SHIT = '>';
+			if (HTMLArea.is_ie) {
+				td.unselectable = "on";
+				IE_IS_A_FUCKING_SHIT = " unselectable='on' style='height=1px'>&nbsp;";
+			}
+			td.innerHTML = "<div" + IE_IS_A_FUCKING_SHIT + "</div>";
+			var td1 = td.cloneNode(true);
+			td1.className = "label";
+			item.appendChild(td);
+			item.appendChild(td1);
+		} else {
+			var label = option[0];
+			item.className = "item";
+			item.__msh = {
+				item: item,
+				label: label,
+				action: option[1],
+				tooltip: option[2] || null,
+				icon: option[3] || null,
+				activate: function() {
+					self.closeMenu();
+					self.editor.focusEditor();
+					this.action();
+				}
+			};
+			label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>");
+			if (label != option[0])
+				keys.push([ RegExp.$1, item ]);
+			label = label.replace(/__/, "_");
+			var td1 = doc.createElement("td");
+			if (HTMLArea.is_ie)
+				td1.unselectable = "on";
+			item.appendChild(td1);
+			td1.className = "icon";
+			if (item.__msh.icon)
+      {
+        var t = HTMLArea.makeBtnImg(item.__msh.icon, doc);
+        td1.appendChild(t);
+        // td1.innerHTML = "<img align='middle' src='" + item.__msh.icon + "' />";
+      }
+      var td2 = doc.createElement("td");
+			if (HTMLArea.is_ie)
+				td2.unselectable = "on";
+			item.appendChild(td2);
+			td2.className = "label";
+			td2.innerHTML = label;
+			item.onmouseover = function() {
+				this.className += " hover";
+				self.editor._statusBarTree.innerHTML = this.__msh.tooltip || '&nbsp;';
+			};
+			item.onmouseout = function() { this.className = "item"; };
+			item.oncontextmenu = function(ev) {
+				this.__msh.activate();
+				if (!HTMLArea.is_ie)
+					HTMLArea._stopEvent(ev);
+				return false;
+			};
+			item.onmouseup = function(ev) {
+				var timeStamp = (new Date()).getTime();
+				if (timeStamp - self.timeStamp > 500)
+					this.__msh.activate();
+				if (!HTMLArea.is_ie)
+					HTMLArea._stopEvent(ev);
+				return false;
+			};
+			//if (typeof option[2] == "string")
+			//item.title = option[2];
+		}
+	}
+
+	if (!HTMLArea.is_ie) {
+    /* FIXME: I think this is to stop the popup from running off the bottom of the screen?
+		var dx = x + div.offsetWidth - window.innerWidth + 4;
+		var dy = y + div.offsetHeight - window.innerHeight + 4;
+    // alert('dy= (' + y + '+' + div.offsetHeight + '-' + window.innerHeight + ' + 4 ) = ' + dy);
+		if (dx > 0) x -= dx;
+		if (dy > 0) y -= dy;
+    */
+		div.style.left = x + "px";
+		div.style.top = y + "px";
+	} else {
+    // To get the size we need to display the popup with some width/height
+    // then we can get the actual size of the div and redisplay the popup at the
+    // correct dimensions.
+    this.iePopup.show(ev.screenX, ev.screenY, 300,50);
+		var w = div.offsetWidth;
+		var h = div.offsetHeight;
+		this.iePopup.show(ev.screenX, ev.screenY, w, h);
+	}
+
+	this.currentMenu = div;
+	this.timeStamp = (new Date()).getTime();
+
+	HTMLArea._addEvent(document, "mousedown", documentClick);
+	HTMLArea._addEvent(this.editordoc, "mousedown", documentClick);
+	if (keys.length > 0)
+		HTMLArea._addEvent(this.editordoc, "keypress", keyPress);
+
+	HTMLArea._stopEvent(ev);
+	return false;
+};

Added: plog/trunk/js/xinha/plugins/ContextMenu/lang/de.js
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/lang/de.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/lang/de.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,54 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8
+
+// translated: Raimund Meyer xinha at ray-of-light.org
+
+
+{
+  "Cut": "Ausschneiden",
+  "Copy": "Kopieren",
+  "Paste": "Einfügen",
+  "_Image Properties...": "Eigenschaften",
+  "Show the image properties dialog": "Fenster für die Bildoptionen anzeigen",  
+  "_Modify Link...": "Link ändern",
+  "Current URL is": "Aktuelle URL ist",
+  "Chec_k Link...": "Link testen",
+  "Opens this link in a new window": "Diesen Link in neuem Fenster öffnen",
+  "_Remove Link...": "Link entfernen",
+  "Please confirm that you want to unlink this element.": "Wollen sie diesen Link wirklich entfernen?",
+  "Link points to:": "Link zeigt auf:",
+  "Unlink the current element": "Link auf Element entfernen",
+  "C_ell Properties...": "Zellenoptionen",
+  "Show the Table Cell Properties dialog": "Zellenoptionen anzeigen",
+  "Ro_w Properties...": "Zeilenoptionen",
+  "Show the Table Row Properties dialog": "Zeilenoptionen anzeigen",
+  "I_nsert Row Before": "Zeile einfügen vor Position",
+  "Insert a new row before the current one": "Zeile einfügen vor der aktuellen Position",
+  "In_sert Row After": "Zeile einügen nach Position",
+  "Insert a new row after the current one": "Zeile einfügen nach der aktuellen Position",
+  "_Delete Row": "Zeile löschen",
+  "Delete the current row": "Zeile löschen",
+  "_Table Properties...": "Tabellenoptionen",
+  "Show the Table Properties dialog": "Tabellenoptionen anzeigen",
+  "Insert _Column Before": "Spalte einfügen vor Position",
+  "Insert a new column before the current one": "Spalte einfügen vor der aktuellen Position",
+  "Insert C_olumn After": "Spalte einfügen nach Position",
+  "Insert a new column after the current one": "Spalte einfügen nach der aktuellen Position",
+  "De_lete Column": "Spalte löschen",
+  "Delete the current column": "Spalte löschen",
+  "Justify Left": "Linksbündig",
+  "Justify Center": "Zentriert",
+  "Justify Right": "Rechtsbündig",
+  "Justify Full": "Blocksatz",
+  "Make lin_k...": "Link erstellen",
+  "Create a link": "Link erstellen",
+  "Remove the $elem Element...": "Element $elem entfernen...",
+  "Please confirm that you want to remove this element:": "Wollen sie dieses Element wirklich entfernen?",
+  "Remove this node from the document": "Dieses Element aus dem Dokument entfernen",
+  "Insert paragraph before": "Absatz einfügen vor Position",
+  "Insert a paragraph before the current node": "Absatz einfügen vor der aktuellen Position",
+  "Insert paragraph after": "Absatz einfügen hinter Position",
+  "Insert a paragraph after the current node": "Absatz einfügen hinter der aktuellen Position",
+  "How did you get here? (Please report!)": "Wie sind Sie denn hier hin gekommen? (Please report!)"
+}

Added: plog/trunk/js/xinha/plugins/ContextMenu/lang/el.js
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/lang/el.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/lang/el.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,49 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8
+// Author: Dimitris Glezos, dimitris at glezos.com
+
+{
+  "Cut": "ΑποκοπΞ�",
+  "Copy": "ΑντιγραφΞ�",
+  "Paste": "Ξ•Ο€ΞΉΞΊΟŒΞ»Ξ»Ξ·ΟƒΞ·",
+  "_Image Properties...": "Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ Ξ•ΞΉΞΊΟŒΞ½Ξ±Ο‚...",
+  "_Modify Link...": "Ξ�ροποποίηση συνδέσμου...",
+  "Chec_k Link...": "ΞˆΞ»Ξ΅Ξ³Ο‡ΞΏΟ‚ συνδέσμων...",
+  "_Remove Link...": "ΔιαγραφΞ� συνδέσμου...",
+  "C_ell Properties...": "Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ κΡλιού...",
+  "Ro_w Properties...": "Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ γραμμΞ�Ο‚...",
+  "I_nsert Row Before": "ΕισαγωγΞ� γραμμΞ�Ο‚ πριν",
+  "In_sert Row After": "ΕισαγωγΞ� γραμμΞ�Ο‚ μΡτά",
+  "_Delete Row": "ΔιαγραφΞ� γραμμΞ�Ο‚",
+  "_Table Properties...": "Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ πίνακα...",
+  "Insert _Column Before": "ΕισαγωγΞ� στΞ�λης πριν",
+  "Insert C_olumn After": "ΕισαγωγΞ� στΞ�λης μΡτά",
+  "De_lete Column": "ΔιαγραφΞ� στΞ�λης",
+  "Justify Left": "Στοίχηση ΑριστΡρά",
+  "Justify Center": "Στοίχηση ΞšΞ­Ξ½Ο„ΟΞΏ",
+  "Justify Right": "Στοίχηση ΔΡξιά",
+  "Justify Full": "Ξ Ξ»Ξ�ρης Στοίχηση",
+  "Make lin_k...": "Δημιουργία συνδέσμου...",
+  "Remove the $elem Element...": "ΑφαίρΡση $elem στοιχΡίου...",
+  "Please confirm that you want to remove this element:": "ΕίστΡ Ξ²Ξ­Ξ²Ξ±ΞΉΞΏΟ‚ πως θέλΡτΡ Ξ½Ξ± αφαιρέσΡτΡ το στοιχΡίο ",
+  "Remove this node from the document": "ΑφαίρΡση αυτού του ΞΊΟŒΞΌΞ²ΞΏΟ… Ξ±Ο€ΟŒ το έγγραφο",
+  "How did you get here? (Please report!)": "Ξ ΟŽΟ‚ Ξ�ρθατΡ μέχρι Ρδώ; (ΠαρακαλούμΡ αναφέρΡτΡ το!)",
+  "Show the image properties dialog": "Εμφάνιση Ξ΄ΞΉΞ±Ξ»ΟŒΞ³ΞΏΟ… ΞΌΞ΅ τις Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ Ξ΅ΞΉΞΊΟŒΞ½Ξ±Ο‚",
+  "Modify URL": "Ξ�ροποποίηση URL",
+  "Current URL is": "Ξ�ΞΏ τρέχων URL Ρίναι",
+  "Opens this link in a new window": "ΑνοίγΡι Ξ±Ο…Ο„ΟŒ τον σύνδΡσμο σΡ Ξ­Ξ½Ξ± Ξ½Ξ­ΞΏ παράθυρο",
+  "Please confirm that you want to unlink this element.": "ΕίστΡ Ξ²Ξ­Ξ²Ξ±ΞΉΞΏΟ‚ πως θέλΡτΡ Ξ½Ξ± αφαιρέσΡτΡ τον σύνδΡσμο Ξ±Ο€ΟŒ Ξ±Ο…Ο„ΟŒ το στοιχΡίο:",
+  "Link points to:": "Ο σύνδΡμος οδηγΡί Ρδώ:",
+  "Unlink the current element": "ΑφαίρΡση συνδέσμου Ξ±Ο€ΟŒ το Ο€Ξ±ΟΟŽΞ½ στοιχΡίο",
+  "Show the Table Cell Properties dialog": "Εμφάνιση Ξ΄ΞΉΞ±Ξ»ΟŒΞ³ΞΏΟ… ΞΌΞ΅ τις Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ κΡλιού Ξ Ξ―Ξ½Ξ±ΞΊΞ±",
+  "Show the Table Row Properties dialog": "Εμφάνιση Ξ΄ΞΉΞ±Ξ»ΟŒΞ³ΞΏΟ… ΞΌΞ΅ τις Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ γραμμΞ�Ο‚ Ξ Ξ―Ξ½Ξ±ΞΊΞ±",
+  "Insert a new row before the current one": "ΕισαγωγΞ� ΞΌΞΉΞ±Ο‚ Ξ½Ξ­Ξ±Ο‚ γραμμΞ�Ο‚ πριν την ΡπιλΡγμένη",
+  "Insert a new row after the current one": "ΕισαγωγΞ� ΞΌΞΉΞ±Ο‚ Ξ½Ξ­Ξ±Ο‚ γραμμΞ�Ο‚ μΡτά την ΡπιλΡγμένη",
+  "Delete the current row": "ΔιαγραφΞ� ΡπιλΡγμένης γραμμΞ�Ο‚",
+  "Show the Table Properties dialog": "Εμφάνιση Ξ΄ΞΉΞ±Ξ»ΟŒΞ³ΞΏΟ… ΞΌΞ΅ τις Ξ™Ξ΄ΞΉΟŒΟ„Ξ·Ο„Ξ΅Ο‚ Ξ Ξ―Ξ½Ξ±ΞΊΞ±",
+  "Insert a new column before the current one": "ΕισαγωγΞ� Ξ½Ξ­Ξ±Ο‚ στΞ�λης πριν την ΡπιλΡγμένη",
+  "Insert a new column after the current one": "ΕισαγωγΞ� Ξ½Ξ­Ξ±Ο‚ στΞ�λης μΡτά την ΡπιλΡγμένη",
+  "Delete the current column": "ΔιαγραφΞ� ΡπιλΡγμένης στΞ�λης",
+  "Create a link": "Δημιουργία συνδέσμου"
+}

Added: plog/trunk/js/xinha/plugins/ContextMenu/lang/fr.js
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/lang/fr.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/lang/fr.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,50 @@
+// I18N constants
+// LANG: "fr", ENCODING: UTF-8
+{
+  "Cut": "Couper",
+  "Copy": "Copier",
+  "Paste": "Coller",
+  "_Image Properties...": "_Propriétés de l'image...",
+  "_Modify Link...": "_Modifier le lien...",
+  "Chec_k Link...": "_Vérifier le lien...",
+  "_Remove Link...": "_Supprimer le lien...",
+  "C_ell Properties...": "P_ropriétés de la cellule...",
+  "Ro_w Properties...": "Pr_opriétés de la rangée...",
+  "I_nsert Row Before": "Insérer une rangée a_vant",
+  "In_sert Row After": "Insér_er une rangée après",
+  "_Delete Row": "Suppr_imer une rangée",
+  "_Table Properties...": "Proprié_tés de la table...",
+  "Insert _Column Before": "I_nsérer une colonne avant",
+  "Insert C_olumn After": "Insérer une colonne après",
+  "De_lete Column": "_Supprimer la colonne",
+  "Justify Left": "Aligner à gauche",
+  "Justify Center": "Aligner au centre",
+  "Justify Right": "Aligner à droite",
+  "Justify Full": "Justifier",
+  "Make lin_k...": "Convertir en lien...",
+  "Remove the $elem Element...": "Supprimer Élément $elem...",
+  "Insert paragraph before": "Insérer un paragraphe avant",
+  "Insert paragraph after": "Insérer un paragraphe après",
+  "Please confirm that you want to remove this element:": "Confirmer la suppression de cet élément:",
+  "Remove this node from the document": "Supprimer ce noeud du document",
+  "How did you get here? (Please report!)": "Comment êtes-vous arrivé ici ? (Reportez le bug SVP !)",
+  "Show the image properties dialog": "Afficher le dialogue des propriétés d'image",
+  "Modify URL": "Modifier l'URL",
+  "Current URL is": "L'URL courante est",
+  "Opens this link in a new window": "Ouvrir ce lien dans une nouvelle fenêtre",
+  "Please confirm that you want to unlink this element.": "Voulez-vous vraiment enlever le lien présent sur cet élément.",
+  "Link points to:": "Le lien pointe sur:",
+  "Unlink the current element": "Enlever le lien sur cet élément",
+  "Show the Table Cell Properties dialog": "Afficher la boite de propriété des cellules",
+  "Show the Table Row Properties dialog": "Afficher la boite de propriété des rangées",
+  "Insert a new row before the current one": "Insérer une nouvelle rangée avant celle-ci",
+  "Insert a new row after the current one": "Insérer une nouvelle rangée après celle-ci",
+  "Delete the current row": "Supprimer la rangée courante",
+  "Show the Table Properties dialog": "Afficher la boite de propriété de tableau",
+  "Insert a new column before the current one": "Insérer une nouvelle rangée avant celle-ci",
+  "Insert a new column after the current one": "Insérer une nouvelle colonne après celle-ci",
+  "Delete the current column": "Supprimer cette colonne",
+  "Create a link": "Créer un lien",
+  "Insert a paragraph before the current node": "Insérer un paragraphe avant le noeud courant",
+  "Insert a paragraph after the current node": "Insérer un paragraphe après le noeud courant"
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/plugins/ContextMenu/lang/he.js
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/lang/he.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/lang/he.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,58 @@
+// I18N constants
+
+// LANG: "he", ENCODING: UTF-8
+// Author: Liron Newman, http://www.eesh.net, <plastish at ultinet dot org>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Cut": "גזור",
+  "Copy": "העתק",
+  "Paste": "הדבק",
+  "_Image Properties...": "_מאפייני תמונה...",
+  "_Modify Link...": "_שנה קישור...",
+  "Chec_k Link...": "בדו_ק קישור...",
+  "_Remove Link...": "_הסר קישור...",
+  "C_ell Properties...": "מאפייני ת_א...",
+  "Ro_w Properties...": "מאפייני _טור...",
+  "I_nsert Row Before": "ה_כנס שורה לפני",
+  "In_sert Row After": "הכנ_ס שורה אחרי",
+  "_Delete Row": "_מחק שורה",
+  "_Table Properties...": "מאפייני ט_בלה...",
+  "Insert _Column Before": "הכנס _טור לפני",
+  "Insert C_olumn After": "הכנס ט_ור אחרי",
+  "De_lete Column": "מח_ק טור",
+  "Justify Left": "ישור לשמאל",
+  "Justify Center": "ישור למרכז",
+  "Justify Right": "ישור לימין",
+  "Justify Full": "ישור לשורה מלאה",
+  "Make lin_k...": "צור קי_שור...",
+  "Remove the $elem Element...": "הסר את אלמנט ה- $elem...",
+  "Please confirm that you want to remove this element:": "אנא אשר שברצונך להסיר את האלמנט הזה:",
+  "Remove this node from the document": "הסרה של node זה מהמסמך",
+  "How did you get here? (Please report!)": "איך הגעת הנה? (אנא דווח!)",
+  "Show the image properties dialog": "מציג את חלון הדו-שיח של מאפייני תמונה",
+  "Modify URL": "שינוי URL",
+  "Current URL is": "URL נוכחי הוא",
+  "Opens this link in a new window": "פתיחת קישור זה בחלון חדש",
+  "Please confirm that you want to unlink this element.": "אנא אשר שאתה רוצה לנתק את אלמנט זה.",
+  "Link points to:": "הקישור מצביע אל:",
+  "Unlink the current element": "ניתוק את האלמנט הנוכחי",
+  "Show the Table Cell Properties dialog": "מציג את חלון הדו-שיח של מאפייני תא בטבלה",
+  "Show the Table Row Properties dialog": "מציג את חלון הדו-שיח של מאפייני שורה בטבלה",
+  "Insert a new row before the current one": "הוספת שורה חדשה לפני הנוכחית",
+  "Insert a new row after the current one": "הוספת שורה חדשה אחרי הנוכחית",
+  "Delete the current row": "מחיקת את השורה הנוכחית",
+  "Show the Table Properties dialog": "מציג את חלון הדו-שיח של מאפייני טבלה",
+  "Insert a new column before the current one": "הוספת טור חדש לפני הנוכחי",
+  "Insert a new column after the current one": "הוספת טור חדש אחרי הנוכחי",
+  "Delete the current column": "מחיקת את הטור הנוכחי",
+  "Create a link": "יצירת קישור"
+}

Added: plog/trunk/js/xinha/plugins/ContextMenu/lang/nl.js
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/lang/nl.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/lang/nl.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,58 @@
+// I18N constants
+
+// LANG: "nl", ENCODING: UTF-8
+// Author: Michel Weegeerink (info at mmc-shop.nl), http://mmc-shop.nl
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Cut": "Knippen",
+  "Copy": "Kopiëren",
+  "Paste": "Plakken",
+  "_Image Properties...": "Eigenschappen afbeelding...",
+  "_Modify Link...": "Hyperlin_k aanpassen...",
+  "Chec_k Link...": "Controleer hyperlin_k...",
+  "_Remove Link...": "Ve_rwijder hyperlink...",
+  "C_ell Properties...": "C_eleigenschappen...",
+  "Ro_w Properties...": "Rijeigenscha_ppen...",
+  "I_nsert Row Before": "Rij invoegen boven",
+  "In_sert Row After": "Rij invoegen onder",
+  "_Delete Row": "Rij _verwijderen",
+  "_Table Properties...": "_Tabeleigenschappen...",
+  "Insert _Column Before": "Kolom invoegen voor",
+  "Insert C_olumn After": "Kolom invoegen na",
+  "De_lete Column": "Kolom verwijderen",
+  "Justify Left": "Links uitlijnen",
+  "Justify Center": "Centreren",
+  "Justify Right": "Rechts uitlijnen",
+  "Justify Full": "Uitvullen",
+  "Make lin_k...": "Maak hyperlin_k...",
+  "Remove the $elem Element...": "Verwijder het $elem element...",
+  "Please confirm that you want to remove this element:": "Is het werkelijk de bedoeling dit element te verwijderen:",
+  "Remove this node from the document": "Verwijder dit punt van het document",
+  "How did you get here? (Please report!)": "Hoe kwam je hier? (A.U.B. doorgeven!)",
+  "Show the image properties dialog": "Laat het afbeeldingseigenschappen dialog zien",
+  "Modify URL": "Aanpassen URL",
+  "Current URL is": "Huidig URL is",
+  "Opens this link in a new window": "Opend deze hyperlink in een nieuw venster",
+  "Please confirm that you want to unlink this element.": "Is het werkelijk de bedoeling dit element te unlinken.",
+  "Link points to:": "Hyperlink verwijst naar:",
+  "Unlink the current element": "Unlink het huidige element",
+  "Show the Table Cell Properties dialog": "Laat de tabel celeigenschappen dialog zien",
+  "Show the Table Row Properties dialog": "Laat de tabel rijeigenschappen dialog zien",
+  "Insert a new row before the current one": "Voeg een nieuwe rij in boven de huidige",
+  "Insert a new row after the current one": "Voeg een nieuwe rij in onder de huidige",
+  "Delete the current row": "Verwijder de huidige rij",
+  "Show the Table Properties dialog": "Laat de tabel eigenschappen dialog zien",
+  "Insert a new column before the current one": "Voeg een nieuwe kolom in voor de huidige",
+  "Insert a new column after the current one": "Voeg een nieuwe kolom in na de huidige",
+  "Delete the current column": "Verwijder de huidige kolom",
+  "Create a link": "Maak een hyperlink"
+}

Added: plog/trunk/js/xinha/plugins/ContextMenu/lang/no.js
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/lang/no.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/lang/no.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,55 @@
+// I18N constants
+// LANG: "no", ENCODING: UTF-8
+// translated: Kim Steinhaug, http://www.steinhaug.com/, kim at steinhaug.com
+
+// Used key commands
+// C,D,e, ,I, ,k,k,l,M, ,n,o,R, ,s,T, ,w   : English
+//       H B j      R m    F       v       : Norwegian
+
+{
+  "Cut": "Klipp ut",
+  "Copy": "Kopier",
+  "Paste": "Lim inn",
+  "_Image Properties...": "_Bilde Egenskaper...",
+  "Show the image properties dialog": "Vis bildeegenskaper",
+  "_Modify Link...": "_Rediger Link...",
+  "Current URL is": "Gjeldende URL er",
+  "Chec_k Link...": "Sje_kk Link...",
+  "Opens this link in a new window": "Ã…pner denne link i nytt vindu",
+  "_Remove Link...": "_Fjerne Link...",
+  "Please confirm that you want to unlink this element.": "Vennligst bekreft at du ønsker å fjerne link på elementet",
+  "Link points to:": "Link peker til:",
+  "Unlink the current element": "Fjerne link på gjeldende element",
+  "C_ell Properties...": "C_elle Egenskaper...",
+  "Show the Table Cell Properties dialog": "Vis egenskaper for celle",
+  "Ro_w Properties...": "Rad Egenskaper... (_w)",
+  "Show the Table Row Properties dialog": "Vis egenskaper for rad",
+  "I_nsert Row Before": "Sett I_nn rad før",
+  "Insert a new row before the current one": "Sett inn ny rad før gjeldende",
+  "In_sert Row After": "_Sett inn rad etter",
+  "Insert a new row after the current one": "Sett inn ny rad etter gjeldende",
+  "_Delete Row": "Slett rad (_d)",
+  "Delete the current row": "Slett gjeldende rad",
+  "_Table Properties...": "_Tabell Egenskaper...",
+  "Show the Table Properties dialog": "Vis egenskaper for tabellen",
+  "Insert _Column Before": "Sett inn kolonne etter (_c)",
+  "Insert a new column before the current one": "Sett inn kolonne før gjeldende",
+  "Insert C_olumn After": "Sett inn k_olonne etter",
+  "Insert a new column after the current one": "Sett inn kolonne etter gjeldende",
+  "De_lete Column": "S_lett kolonne",
+  "Delete the current column": "Slett gjeldende kolonne",
+  "Justify Left": "_Venstrejuster",
+  "Justify Center": "_Midtjuster",
+  "Justify Right": "_Høyrejuster",
+  "Justify Full": "Blokk_juster",
+  "Make lin_k...": "Lag len_ke...",
+  "Create a link": "Lag ny link",
+  "Remove the $elem Element...": "Fjerne $elem elementet...",
+  "Please confirm that you want to remove this element:": "Vennligst bekreft at du ønsker å fjerne elementet:",
+  "Remove this node from the document": "Fjerne denne node fra dokumentet",
+  "Insert paragraph before": "Sett inn paragraf før",
+  "Insert a paragraph before the current node": "Sett inn paragraf før gjeldende node",
+  "Insert paragraph after": "Sett inn paragraf etter",
+  "Insert a paragraph after the current node": "Sett inn paragraf etter gjeldende node",
+  "How did you get here? (Please report!)": "Hva skjedde? (Vennligst beskriv)"
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/plugins/ContextMenu/menu.css
===================================================================
--- plog/trunk/js/xinha/plugins/ContextMenu/menu.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/ContextMenu/menu.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,67 @@
+/* styles for the ContextMenu /HTMLArea */
+/* The ContextMenu plugin is (c) dynarch.com 2003. */
+/* Distributed under the same terms as HTMLArea itself */
+
+div.htmlarea-context-menu {
+  position: absolute;
+  border: 1px solid #aca899;
+  padding: 2px;
+  background-color: #fff;
+  color: #000;
+  cursor: default;
+  z-index: 1000;
+}
+
+div.htmlarea-context-menu table {
+  font: 11px tahoma,verdana,sans-serif;
+  border-collapse: collapse;
+}
+
+div.htmlarea-context-menu tr.item td.icon img {
+/* taken care of by xinha.makeBtnImg() */
+/* width: 18px; */
+/* height: 18px; */
+}
+
+div.htmlarea-context-menu tr.item td.icon {
+  padding: 0px 3px;
+  width: 18px;
+  height: 18px;
+  background-color: #cdf;
+}
+
+div.htmlarea-context-menu tr.item td.label {
+  padding: 1px 10px 1px 3px;
+}
+
+div.htmlarea-context-menu tr.separator td {
+  padding: 2px 0px;
+}
+
+div.htmlarea-context-menu tr.separator td div {
+  border-top: 1px solid #aca899;
+  overflow: hidden;
+  position: relative;
+}
+
+div.htmlarea-context-menu tr.separator td.icon {
+  background-color: #cdf;
+}
+
+div.htmlarea-context-menu tr.separator td.icon div {
+/*  margin-left: 3px; */
+  border-color: #fff;
+}
+
+div.htmlarea-context-menu tr.separator td.label div {
+  margin-right: 3px;
+}
+
+div.htmlarea-context-menu tr.item.hover {
+  background-color: #316ac5;
+  color: #fff;
+}
+
+div.htmlarea-context-menu tr.item.hover td.icon {
+  background-color: #619af5;
+}

Added: plog/trunk/js/xinha/plugins/EnterParagraphs/enter-paragraphs.js
===================================================================
--- plog/trunk/js/xinha/plugins/EnterParagraphs/enter-paragraphs.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/EnterParagraphs/enter-paragraphs.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,1087 @@
+// tabs 2
+
+/**
+* @fileoverview By Adam Wright, for The University of Western Australia
+*
+* Distributed under the same terms as HTMLArea itself.
+* This notice MUST stay intact for use (see license.txt).
+*
+* Heavily modified by Yermo Lamers of DTLink, LLC, College Park, Md., USA.
+* For more info see http://www.areaedit.com
+*/
+
+/**
+* plugin Info
+*/
+
+EnterParagraphs._pluginInfo =
+	{
+  name          : "EnterParagraphs",
+  version       : "1.0",
+  developer     : "Adam Wright",
+  developer_url : "http://www.hipikat.org/",
+  sponsor       : "The University of Western Australia",
+  sponsor_url   : "http://www.uwa.edu.au/",
+  license       : "htmlArea"
+	};
+
+// ------------------------------------------------------------------
+
+// "constants"
+
+/**
+* Whitespace Regex
+*/
+
+EnterParagraphs.prototype._whiteSpace = /^\s*$/;
+
+/**
+* The pragmatic list of which elements a paragraph may not contain
+*/
+
+EnterParagraphs.prototype._pExclusions = /^(address|blockquote|body|dd|div|dl|dt|fieldset|form|h1|h2|h3|h4|h5|h6|hr|li|noscript|ol|p|pre|table|ul)$/i;
+
+/**
+* elements which may contain a paragraph
+*/
+
+EnterParagraphs.prototype._pContainers = /^(body|del|div|fieldset|form|ins|map|noscript|object|td|th)$/i;
+
+/**
+* Elements which may not contain paragraphs, and would prefer a break to being split
+*/
+
+EnterParagraphs.prototype._pBreak = /^(address|pre|blockquote)$/i;
+
+/**
+* Elements which may not contain children
+*/
+
+EnterParagraphs.prototype._permEmpty = /^(area|base|basefont|br|col|frame|hr|img|input|isindex|link|meta|param)$/i;
+
+/**
+* Elements which count as content, as distinct from whitespace or containers
+*/
+
+EnterParagraphs.prototype._elemSolid = /^(applet|br|button|hr|img|input|table)$/i;
+
+/**
+* Elements which should get a new P, before or after, when enter is pressed at either end
+*/
+
+EnterParagraphs.prototype._pifySibling = /^(address|blockquote|del|div|dl|fieldset|form|h1|h2|h3|h4|h5|h6|hr|ins|map|noscript|object|ol|p|pre|table|ul|)$/i;
+EnterParagraphs.prototype._pifyForced = /^(ul|ol|dl|table)$/i;
+
+/**
+* Elements which should get a new P, before or after a close parent, when enter is pressed at either end
+*/
+
+EnterParagraphs.prototype._pifyParent = /^(dd|dt|li|td|th|tr)$/i;
+
+// ---------------------------------------------------------------------
+
+/**
+* EnterParagraphs Constructor
+*/
+
+function EnterParagraphs(editor)
+	{
+
+  this.editor = editor;
+
+	// [STRIP
+	// create a ddt debug trace object. There may be multiple editors on
+	// the page each EnterParagraphs .. to distinguish which instance
+	// is generating the message we tack on the name of the textarea.
+
+	//this.ddt = new DDT( editor._textArea + ":EnterParagraphs Plugin" );
+
+	// uncomment to turn on debugging messages.
+
+	//this.ddt._ddtOn();
+
+	//this.ddt._ddt( "enter-paragraphs.js","23", "EnterParagraphs(): constructor" );
+
+	// STRIP]
+
+  // hook into the event handler to intercept key presses if we are using
+	// gecko (Mozilla/FireFox)
+
+  if (HTMLArea.is_gecko)
+		{
+		//this.ddt._ddt( "enter-paragraphs.js","23", "EnterParagraphs(): we are gecko. Setting event handler." );
+    this.onKeyPress = this.__onKeyPress;
+		}
+
+	};	// end of constructor.
+
+// ------------------------------------------------------------------
+
+/**
+* name member for debugging
+*
+* This member is used to identify objects of this class in debugging
+* messages.
+*/
+
+EnterParagraphs.prototype.name = "EnterParagraphs";
+
+/**
+* Gecko's a bit lacking in some odd ways...
+*/
+
+EnterParagraphs.prototype.insertAdjacentElement = function(ref,pos,el)
+	{
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): top with pos '" + pos + "' ref:", ref );
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): top with el:", el );
+
+  if ( pos == 'BeforeBegin' )
+		{
+		ref.parentNode.insertBefore(el,ref);
+		}
+  else if ( pos == 'AfterEnd' )
+		{
+		ref.nextSibling ? ref.parentNode.insertBefore(el,ref.nextSibling) : ref.parentNode.appendChild(el);
+		}
+  else if ( pos == 'AfterBegin' && ref.firstChild )
+		{
+		ref.insertBefore(el,ref.firstChild);
+		}
+  else if ( pos == 'BeforeEnd' || pos == 'AfterBegin' )
+		{
+		ref.appendChild(el);
+		}
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "122", "insertAdjacentElement(): bottom with ref:", ref );
+
+	};	// end of insertAdjacentElement()
+
+// ----------------------------------------------------------------
+
+/**
+* Passes a global parent node or document fragment to forEachNode
+*
+* @param root node root node to start search from.
+* @param mode string function to apply to each node.
+* @param direction string traversal direction "ltr" (left to right) or "rtl" (right_to_left)
+* @param init boolean
+*/
+
+EnterParagraphs.prototype.forEachNodeUnder = function ( root, mode, direction, init )
+	{
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): top mode is '" + mode + "' direction is '" + direction + "' starting with root node:", root );
+
+  // Identify the first and last nodes to deal with
+
+  var start, end;
+
+	// nodeType 11 is DOCUMENT_FRAGMENT_NODE which is a container.
+
+  if ( root.nodeType == 11 && root.firstChild )
+		{
+    start = root.firstChild;
+    end = root.lastChild;
+	  }
+	else
+		{
+		start = end = root;
+		}
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): start node is:", start );
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): initial end node is:", end );
+
+	// traverse down the right hand side of the tree getting the last child of the last
+	// child in each level until we reach bottom.
+  while ( end.lastChild )
+		end = end.lastChild;
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "144", "forEachNodeUnder(): end node after descent is:", end );
+
+  return this.forEachNode( start, end, mode, direction, init);
+
+	};	// end of forEachNodeUnder()
+
+// -----------------------------------------------------------------------
+
+/**
+* perform a depth first descent in the direction requested.
+*
+* @param left_node node "start node"
+* @param right_node node "end node"
+* @param mode string function to apply to each node. cullids or emptyset.
+* @param direction string traversal direction "ltr" (left to right) or "rtl" (right_to_left)
+* @param init boolean or object.
+*/
+
+EnterParagraphs.prototype.forEachNode = function (left_node, right_node, mode, direction, init)
+	{
+
+	//this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): top - mode is:" + mode + "' direction '" + direction + "'" );
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): top - left node is:", left_node );
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): top - right node is:", right_node );
+
+	// returns "Brother" node either left or right.
+
+  var getSibling = function(elem, direction)
+							{
+							return ( direction == "ltr" ? elem.nextSibling : elem.previousSibling );
+							};
+
+  var getChild = function(elem, direction)
+							{
+							return ( direction == "ltr" ? elem.firstChild : elem.lastChild );
+							};
+
+  var walk, lookup, fnReturnVal;
+
+	// FIXME: init is a boolean in the emptyset case and an object in
+	// the cullids case. Used inconsistently.
+
+	var next_node = init;
+
+	// used to flag having reached the last node.
+
+	var done_flag = false;
+
+  // loop ntil we've hit the last node in the given direction.
+	// if we're going left to right that's the right_node and visa-versa.
+
+  while ( walk != direction == "ltr" ? right_node : left_node )
+		{
+
+    // on first entry, walk here is null. So this is how
+		// we prime the loop with the first node.
+
+    if ( !walk )
+			{
+			walk = direction == "ltr" ? left_node : right_node;
+
+			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): !walk - current node is:", walk );
+			}
+    else
+			{
+
+			// is there a child node?
+
+      if ( getChild(walk,direction) )
+				{
+
+				// descend down into the child.
+
+				walk = getChild(walk,direction);
+
+				//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode():descending to child node:", walk );
+
+				}
+      else
+				{
+
+				// is there a sibling node on this level?
+
+        if ( getSibling(walk,direction) )
+					{
+
+					// move to the sibling.
+
+					walk = getSibling(walk,direction);
+
+					//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): moving to sibling node:", walk );
+
+					}
+        else
+					{
+          lookup = walk;
+
+					// climb back up the tree until we find a level where we are not the end
+					// node on the level (i.e. that we have a sibling in the direction
+					// we are searching) or until we reach the end.
+
+          while ( !getSibling(lookup,direction) && lookup != (direction == "ltr" ? right_node : left_node) )
+						{
+						lookup = lookup.parentNode;
+						}
+
+					// did we find a level with a sibling?
+
+          // walk = ( lookup.nextSibling ? lookup.nextSibling : lookup ) ;
+
+          walk = ( getSibling(lookup,direction) ? getSibling(lookup,direction) : lookup ) ;
+
+					//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): climbed back up (or found right node):", walk );
+
+			    }
+				}
+
+			}	// end of else walk.
+
+		// have we reached the end? either as a result of the top while loop or climbing
+		// back out above.
+
+		done_flag = (walk==( direction == "ltr" ? right_node : left_node));
+
+		// call the requested function on the current node. Functions
+		// return an array.
+		//
+		// Possible functions are _fenCullIds, _fenEmptySet
+		//
+		// The situation is complicated by the fact that sometimes we want to
+		// return the base node and sometimes we do not.
+		//
+		// next_node can be an object (this.takenIds), a node (text, el, etc) or false.
+
+		//this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): calling function" );
+
+		switch( mode )
+			{
+
+			case "cullids":
+
+    		fnReturnVal = this._fenCullIds(walk, next_node );
+				break;
+
+			case "find_fill":
+
+    		fnReturnVal = this._fenEmptySet(walk, next_node, mode, done_flag);
+				break;
+
+			case "find_cursorpoint":
+
+    		fnReturnVal = this._fenEmptySet(walk, next_node, mode, done_flag);
+				break;
+
+			}
+
+		// If this node wants us to return, return next_node
+
+    if ( fnReturnVal[0] )
+			{
+			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "175", "forEachNode(): returning node:", fnReturnVal[1] );
+
+			return fnReturnVal[1];
+			}
+
+		// are we done with the loop?
+
+		if ( done_flag )
+			{
+			break;
+			}
+
+		// Otherwise, pass to the next node
+
+    if ( fnReturnVal[1] )
+			{
+			next_node = fnReturnVal[1];
+			}
+
+	  }	// end of while loop
+
+	//this.ddt._ddt( "enter-paragraphs.js", "175", "forEachNode(): returning false." );
+
+  return false;
+
+	};	// end of forEachNode()
+
+// -------------------------------------------------------------------
+
+/**
+* Find a post-insertion node, only if all nodes are empty, or the first content
+*
+* @param node node current node beinge examined.
+* @param next_node node next node to be examined.
+* @param node string "find_fill" or "find_cursorpoint"
+* @param last_flag boolean is this the last node?
+*/
+
+EnterParagraphs.prototype._fenEmptySet = function( node, next_node, mode, last_flag)
+	{
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : top with mode '" + mode + "' and last_flag '" + last_flag + "' and node:", node );
+
+  // Mark this if it's the first base
+
+  if ( !next_node && !node.firstChild )
+		{
+		next_node = node;
+		}
+
+  // Is it an element node and is it considered content? (br, hr, etc)
+	// or is it a text node that is not just whitespace?
+	// or is it not an element node and not a text node?
+
+  if ( (node.nodeType == 1 && this._elemSolid.test(node.nodeName)) ||
+    (node.nodeType == 3 && !this._whiteSpace.test(node.nodeValue)) ||
+    (node.nodeType != 1 && node.nodeType != 3) )
+		{
+
+		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : found content in node:", node );
+
+		switch( mode )
+			{
+
+			case "find_fill":
+
+				// does not return content.
+
+		    return new Array(true, false );
+				breal;
+
+			case "find_cursorpoint":
+
+				// returns content
+
+		    return new Array(true, node );
+				break;
+
+			}
+
+	  }
+
+  // In either case (fill or findcursor) we return the base node. The avoids
+	// problems in terminal cases (beginning or end of document or container tags)
+
+  if ( last_flag )
+		{
+		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : return 'base' node:", next_node );
+
+		return new Array( true, next_node );
+		}
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "263", "_fenEmptySet() : bottom returning false and :", next_node );
+
+  return new Array( false, next_node );
+
+	};	// end of _fenEmptySet()
+
+// ------------------------------------------------------------------------------
+
+/**
+* remove duplicate Id's.
+*
+* @param ep_ref enterparagraphs reference to enterparagraphs object
+*/
+
+EnterParagraphs.prototype._fenCullIds = function ( ep_ref, node, pong )
+	{
+
+	//this.ddt._ddt( "enter-paragraphs.js", "299", "_fenCullIds(): top" );
+
+  // Check for an id, blast it if it's in the store, otherwise add it
+
+  if ( node.id )
+		{
+
+		//this.ddt._ddt( "enter-paragraphs.js", "299", "_fenCullIds(): node '" + node.nodeName + "' has an id '" + node.id + "'" );
+
+		pong[node.id] ? node.id = '' : pong[node.id] = true;
+		}
+
+  return new Array(false,pong);
+
+	};
+
+// ---------------------------------------------------------------------------------
+
+/**
+* Grabs a range suitable for paragraph stuffing
+*
+* @param rng Range
+* @param search_direction string "left" or "right"
+*
+* @todo check blank node issue in roaming loop.
+*/
+
+EnterParagraphs.prototype.processSide = function( rng, search_direction)
+	{
+
+	//this.ddt._ddt( "enter-paragraphs.js", "329", "processSide(): top search_direction == '" + search_direction + "'" );
+
+  var next = function(element, search_direction)
+							{
+							return ( search_direction == "left" ? element.previousSibling : element.nextSibling );
+							};
+
+  var node = search_direction == "left" ? rng.startContainer : rng.endContainer;
+  var offset = search_direction == "left" ? rng.startOffset : rng.endOffset;
+  var roam, start = node;
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "337", "processSide(): starting with node:", node );
+
+  // Never start with an element, because then the first roaming node might
+  // be on the exclusion list and we wouldn't know until it was too late
+
+  while ( start.nodeType == 1 && !this._permEmpty.test(start.nodeName) )
+		{
+		start = ( offset ? start.lastChild : start.firstChild );
+		}
+
+  // Climb the tree, left or right, until our course of action presents itself
+	//
+	// if roam is NULL try start.
+	// if roam is NOT NULL, try next node in our search_direction
+	// If that node is NULL, get our parent node.
+	//
+	// If all the above turns out NULL end the loop.
+	//
+	// FIXME: gecko (firefox 1.0.3) - enter "test" into an empty document and press enter.
+	// sometimes this loop finds a blank text node, sometimes it doesn't.
+
+  while ( roam = roam ? ( next(roam,search_direction) ? next(roam,search_direction) : roam.parentNode ) : start )
+		{
+
+		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "357", "processSide(): roaming loop, search_direction is '" + search_direction + "' current node is: ", roam );
+
+		// next() is an inline function defined above that returns the next node depending
+		// on the direction we're searching.
+
+    if ( next(roam,search_direction) )
+			{
+
+			//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Checking next node '" + next(roam,search_direction).NodeName + "' for _pExclusions list." );
+
+      // If the next sibling's on the exclusion list, stop before it
+
+      if ( this._pExclusions.test(next(roam,search_direction).nodeName) )
+				{
+
+				//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Node '" + next(roam,search_direction).NodeName + "' is on the _pExclusions list. Stopping before it." );
+
+        return this.processRng(rng, search_direction, roam, next(roam,search_direction), (search_direction == "left"?'AfterEnd':'BeforeBegin'), true, false);
+		    }
+			}
+		else
+			{
+
+			//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): No next node, examing parent node '" + roam.parentNode.nodeName + "' for containers or exclusions." );
+
+      // If our parent's on the container list, stop inside it
+
+      if (this._pContainers.test(roam.parentNode.nodeName))
+				{
+
+				//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pContainer list. Stopping inside it." );
+
+        return this.processRng(rng, search_direction, roam, roam.parentNode, (search_direction == "left"?'AfterBegin':'BeforeEnd'), true, false);
+	      }
+      else if (this._pExclusions.test(roam.parentNode.nodeName))
+				{
+
+				//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pExclusion list." );
+
+	      // chop without wrapping
+
+        if (this._pBreak.test(roam.parentNode.nodeName))
+					{
+
+					//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is on the _pBreak list." );
+
+          return this.processRng(rng, search_direction, roam, roam.parentNode,
+                            (search_direction == "left"?'AfterBegin':'BeforeEnd'), false, (search_direction == "left" ?true:false));
+	        }
+				else
+					{
+
+					//this.ddt._ddt( "enter-paragraphs.js", "371", "processSide(): Parent Node '" + roam.parentNode.nodeName + "' is not on the _pBreak list." );
+
+					// the next(roam,search_direction) in this call is redundant since we know it's false
+					// because of the "if next(roam,search_direction)" above.
+					//
+					// the final false prevents this range from being wrapped in <p>'s most likely
+					// because it's already wrapped.
+
+          return this.processRng(rng,
+																search_direction,
+																(roam = roam.parentNode),
+		                            (next(roam,search_direction) ? next(roam,search_direction) : roam.parentNode),
+									              (next(roam,search_direction) ? (search_direction == "left"?'AfterEnd':'BeforeBegin') : (search_direction == "left"?'AfterBegin':'BeforeEnd')),
+																false,
+																false);
+					}
+				}
+			}
+		}
+
+	//this.ddt._ddt( "enter-paragraphs.js", "424", "processSide(): bottom" );
+
+	};	// end of processSide()
+
+// ------------------------------------------------------------------------------
+
+/**
+* processRng - process Range.
+*
+* Neighbour and insertion identify where the new node, roam, needs to enter
+* the document; landmarks in our selection will be deleted before insertion
+*
+* @param rn Range original selected range
+* @param search_direction string Direction to search in.
+* @param roam node
+* @param insertion string may be AfterBegin of BeforeEnd
+* @return array
+*/
+
+EnterParagraphs.prototype.processRng = function(rng, search_direction, roam, neighbour, insertion, pWrap, preBr)
+	{
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "398", "processRng(): top - roam arg is:", roam );
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "398", "processRng(): top - neighbor arg is:", neighbour );
+
+	//this.ddt._ddt( "enter-paragraphs.js", "398", "processRng(): top - insertion arg is: '" + insertion + "'" );
+
+  var node = search_direction == "left" ? rng.startContainer : rng.endContainer;
+  var offset = search_direction == "left" ? rng.startOffset : rng.endOffset;
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "447", "processRng(): range start (or end) is at offset '" + offset + "' is node :", node );
+
+  // Define the range to cut, and extend the selection range to the same boundary
+
+  var editor = this.editor;
+  var newRng = editor._doc.createRange();
+
+  newRng.selectNode(roam);
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): selecting newRng is:", newRng );
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): selecting original rng is:", rng );
+
+	// extend the range in the given direction.
+
+  if ( search_direction == "left")
+		{
+    newRng.setEnd(node, offset);
+    rng.setStart(newRng.startContainer, newRng.startOffset);
+
+		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): extending direction left - newRng is:", newRng );
+		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): extending direction left - rng is:", rng );
+
+	  }
+	else if ( search_direction == "right" )
+		{
+
+    newRng.setStart(node, offset);
+		rng.setEnd(newRng.endContainer, newRng.endOffset);
+
+		//this.ddt._ddt( "enter-paragraphs.js", "522", "processRng(): right - new range start is '" + offset + "' end offset is '" + newRng.endOffset + "'" );
+	  }
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): rng is:", rng );
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "522", "processRng(): newRng is:", newRng );
+
+  // Clone the range and remove duplicate ids it would otherwise produce
+
+  var cnt = newRng.cloneContents();
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "509", "processRng(): culling duplicate ids from:", cnt );
+
+	// in this case "init" is an object not a boolen.
+
+  this.forEachNodeUnder( cnt, "cullids", "ltr", this.takenIds, false, false);
+
+  // Special case, for inserting paragraphs before some blocks when caret is at
+	// their zero offset.
+	//
+	// Used to "open up space" in front of a list, table. Usefull if the list is at
+	// the top of the document. (otherwise you'd have no way of "moving it down").
+
+  var pify, pifyOffset, fill;
+  pify = search_direction == "left" ? (newRng.endContainer.nodeType == 3 ? true:false) : (newRng.startContainer.nodeType == 3 ? false:true);
+  pifyOffset = pify ? newRng.startOffset : newRng.endOffset;
+  pify = pify ? newRng.startContainer : newRng.endContainer;
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "521", "processRng(): pify is '" + pify.nodeName + "' pifyOffset is '" + pifyOffset + "':", pify );
+
+  if ( this._pifyParent.test(pify.nodeName) && pify.parentNode.childNodes.item(0) == pify )
+		{
+    while ( !this._pifySibling.test(pify.nodeName) )
+			{
+			pify = pify.parentNode;
+			}
+	  }
+
+	// NODE TYPE 11 is DOCUMENT_FRAGMENT NODE
+
+  if ( cnt.nodeType == 11 && !cnt.firstChild )
+		{
+		cnt.appendChild(editor._doc.createElement(pify.nodeName));
+		}
+
+	// YmL: Added additional last parameter for fill case to work around logic
+	// error in forEachNode()
+
+	//this.ddt._ddt( "enter-paragraphs.js", "612", "processRng(): find_fill in cnt." );
+
+  fill = this.forEachNodeUnder(cnt, "find_fill", "ltr", false );
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "612", "processRng(): fill node:" , fill );
+
+  if ( fill &&
+				this._pifySibling.test(pify.nodeName) &&
+	    	( (pifyOffset == 0) || ( pifyOffset == 1 && this._pifyForced.test(pify.nodeName) ) ) )
+		{
+
+		//this.ddt._ddt( "enter-paragraphs.js", "544", "processRng(): pify handling. Creating p tag followed by nbsp tag" );
+
+		roam = editor._doc.createElement( 'p' );
+		roam.innerHTML = "&nbsp;";
+
+    // roam = editor._doc.createElement('p');
+    // roam.appendChild(editor._doc.createElement('br'));
+
+		// for these cases, if we are processing the left hand side we want it to halt
+		// processing instead of doing the right hand side. (Avoids adding another <p>&nbsp</p>
+		// after the list etc.
+
+    if ((search_direction == "left" ) && pify.previousSibling)
+			{
+
+			//this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam AfterEnd" );
+
+			return new Array(pify.previousSibling, 'AfterEnd', roam);
+			}
+    else if (( search_direction == "right") && pify.nextSibling)
+			{
+
+			//this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam BeforeBegin" );
+
+			return new Array(pify.nextSibling, 'BeforeBegin', roam);
+			}
+    else
+			{
+
+			//this.ddt._ddt( "enter-paragraphs.js", "682", "processRng(): returning created roam for direction '" + search_direction + "'" );
+
+			return new Array(pify.parentNode, (search_direction == "left"?'AfterBegin':'BeforeEnd'), roam);
+			}
+
+	  }
+
+  // If our cloned contents are 'content'-less, shove a break in them
+
+  if ( fill )
+		{
+
+		// Ill-concieved?
+		//
+		// 3 is a TEXT node and it should be empty.
+		//
+
+		if ( fill.nodeType == 3 )
+			{
+			// fill = fill.parentNode;
+
+			fill = editor._doc.createDocumentFragment();
+
+			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "575", "processRng(): fill.nodeType is 3. Moving up to parent:", fill );
+			}
+
+    if ( (fill.nodeType == 1 && !this._elemSolid.test()) || fill.nodeType == 11 )
+			{
+
+			// FIXME:/CHECKME: When Xinha is switched from WYSIWYG to text mode
+			// HTMLArea.getHTMLWrapper() will strip out the trailing br. Not sure why.
+
+			// fill.appendChild(editor._doc.createElement('br'));
+
+			var pterminator = editor._doc.createElement( 'p' );
+			pterminator.innerHTML = "&nbsp;";
+
+			fill.appendChild( pterminator );
+
+			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "583", "processRng(): fill type is 1 and !elemsolid or it's type 11. Appending an nbsp tag:", fill );
+
+			}
+    else
+			{
+
+			//this.ddt._ddt( "enter-paragraphs.js", "583", "processRng(): inserting a br tag before." );
+
+			// fill.parentNode.insertBefore(editor._doc.createElement('br'),fill);
+
+			var pterminator = editor._doc.createElement( 'p' );
+			pterminator.innerHTML = "&nbsp;";
+
+			fill.parentNode.insertBefore(parentNode,fill);
+
+			}
+	  }
+
+	// YmL: If there was no content replace with fill
+	// (previous code did not use fill and we ended up with the
+	// <p>test</p><p></p> because Gecko was finding two empty text nodes
+	// when traversing on the right hand side of an empty document.
+
+	if ( fill )
+		{
+
+		//this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): no content. Using fill.", fill );
+
+		roam = fill;
+		}
+	else
+		{
+	  // And stuff a shiny new object with whatever contents we have
+
+		//this.ddt._ddt( "enter-paragraphs.js", "606", "processRng(): creating p tag or document fragment - pWrap is '" + pWrap + "' " );
+
+	  roam = (pWrap || (cnt.nodeType == 11 && !cnt.firstChild)) ? editor._doc.createElement('p') : editor._doc.createDocumentFragment();
+	  roam.appendChild(cnt);
+		}
+
+  if (preBr)
+		{
+		//this.ddt._ddt( "enter-paragraphs.js", "767", "processRng(): appending a br based on preBr flag" );
+
+		roam.appendChild(editor._doc.createElement('br'));
+		}
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): bottom with roam:", roam );
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "606", "processRng(): bottom with neighbour:", neighbour );
+
+  // Return the nearest relative, relative insertion point and fragment to insert
+
+  return new Array(neighbour, insertion, roam);
+
+	};	// end of processRng()
+
+// ----------------------------------------------------------------------------------
+
+/**
+* are we an <li> that should be handled by the browser?
+*
+* there is no good way to "get out of" ordered or unordered lists from Javascript.
+* We have to pass the onKeyPress 13 event to the browser so it can take care of
+* getting us "out of" the list.
+*
+* The Gecko engine does a good job of handling all the normal <li> cases except the "press
+* enter at the first position" where we want a <p>&nbsp</p> inserted before the list. The
+* built-in behavior is to open up a <li> before the current entry (not good).
+*
+* @param rng Range range.
+*/
+
+EnterParagraphs.prototype.isNormalListItem = function(rng)
+	{
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "863", "isNormaListItem(): checking rng for list end:", rng );
+
+	var node, listNode;
+
+	node = rng.startContainer;
+
+	if (( typeof node.nodeName != 'undefined') &&
+		( node.nodeName.toLowerCase() == 'li' ))
+		{
+
+		//this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): node is a list item");
+
+		// are we a list item?
+
+		listNode = node;
+		}
+	else if (( typeof node.parentNode != 'undefined' ) &&
+				( typeof node.parentNode.nodeName != 'undefined' ) &&
+				( node.parentNode.nodeName.toLowerCase() == 'li' ))
+		{
+
+		//this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): parent is a list item");
+
+		// our parent is a list item.
+
+		listNode = node.parentNode;
+
+		}
+	else
+		{
+		//this.ddt._ddt( "enter-paragraphs.js", "863", "isNormaListItem(): not list item");
+
+		// neither we nor our parent are a list item. this is not a normal
+		// li case.
+
+		return false;
+		}
+
+	// at this point we have a listNode. Is it the first list item?
+
+	if ( ! listNode.previousSibling )
+		{
+		//this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): we are the first li." );
+
+		// are we on the first character of the first li?
+
+		if ( rng.startOffset == 0 )
+			{
+			//this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): we are on the first character." );
+
+			return false;
+			}
+		}
+
+	//this.ddt._ddt( "enter-paragraphs.js", "839", "isNormaListItem(): this is a normal list item case." );
+	return true;
+
+	};	// end of isNormalListItem()
+
+// ----------------------------------------------------------------------------------
+/**
+* Called when a key is pressed in the editor
+*/
+
+EnterParagraphs.prototype.__onKeyPress = function(ev)
+	{
+
+	//this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): top with keyCode '" + ev.keyCode + "'" );
+
+  // If they've hit enter and shift is not pressed, handle it
+
+  if (ev.keyCode == 13 && !ev.shiftKey && this.editor._iframe.contentWindow.getSelection)
+		{
+		//this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): calling handleEnter" );
+
+    return this.handleEnter(ev);
+		}
+
+	//this.ddt._ddt( "enter-paragraphs.js", "517", "__onKeyPress(): bottom" );
+
+	};	// end of _onKeyPress()
+
+// -----------------------------------------------------------------------------------
+
+/**
+* Handles the pressing of an unshifted enter for Gecko
+*/
+
+EnterParagraphs.prototype.handleEnter = function(ev)
+	{
+
+	//this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): top" );
+
+	var cursorNode;
+
+  // Grab the selection and associated range
+
+  var sel = this.editor._getSelection();
+  var rng = this.editor._createRange(sel);
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "757", "handleEnter(): initial range is: ", rng );
+
+	// if we are at the end of a list and the node is empty let the browser handle
+	// it to get us out of the list.
+
+	if ( this.isNormalListItem(rng) )
+		{
+		//this.ddt._ddt( "enter-paragraphs.js", "757", "handleEnter(): we are at the end of a list with a blank item. Letting the browser handle it." );
+		return true;
+		}
+
+	// as far as I can tell this isn't actually used.
+
+  this.takenIds = new Object();
+
+  // Grab ranges for document re-stuffing, if appropriate
+	//
+	// pStart and pEnd are arrays consisting of
+	// [0] neighbor node
+	// [1] insertion type
+	// [2] roam
+
+	//this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): calling processSide on left side." );
+
+  var pStart = this.processSide(rng, "left");
+
+	//this.ddt._ddtDumpNode( "enter-paragraphs.js", "757", "handleEnter(): after processing left side range is: ", rng );
+
+	//this.ddt._ddt( "enter-paragraphs.js", "537", "handleEnter(): calling processSide on right side." );
+
+ 	var pEnd = this.processSide(rng, "right");
+
+	// used to position the cursor after insertion.
+
+	cursorNode = pEnd[2];
+
+  // Get rid of everything local to the selection
+
+  sel.removeAllRanges();
+  rng.deleteContents();
+
+	// Grab a node we'll have after insertion, since fragments will be lost
+	//
+	// we'll use this to position the cursor.
+
+	//this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): looking for cursor position" );
+
+  var holdEnd = this.forEachNodeUnder( cursorNode, "find_cursorpoint", "ltr", false, true);
+
+	if ( ! holdEnd )
+		{
+		alert( "INTERNAL ERROR - could not find place to put cursor after ENTER" );
+		}
+
+  // Insert our carefully chosen document fragments
+
+  if ( pStart )
+		{
+
+		//this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): inserting pEnd" );
+
+		this.insertAdjacentElement(pStart[0], pStart[1], pStart[2]);
+		}
+
+  if ( pEnd && pEnd.nodeType != 1)
+		{
+
+		//this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): inserting pEnd" );
+
+		this.insertAdjacentElement(pEnd[0], pEnd[1], pEnd[2]);
+		}
+
+  // Move the caret in front of the first good text element
+
+  if ((holdEnd) && (this._permEmpty.test(holdEnd.nodeName) ))
+		{
+
+		//this.ddt._ddt( "enter-paragraphs.js", "712", "handleEnter(): looping to find cursor element." );
+
+    var prodigal = 0;
+    while ( holdEnd.parentNode.childNodes.item(prodigal) != holdEnd )
+			{
+			prodigal++;
+			}
+
+    sel.collapse( holdEnd.parentNode, prodigal);
+	  }
+  else
+		{
+
+		// holdEnd might be false.
+
+		try
+			{
+			sel.collapse(holdEnd, 0);
+
+			//this.ddt._ddtDumpNode( "enter-paragraphs.js", "1057", "handleEnter(): scrolling to element:", holdEnd );
+
+			// interestingly, scrollToElement() scroll so the top if holdEnd is a text node.
+
+			if ( holdEnd.nodeType == 3 )
+				{
+				holdEnd = holdEnd.parentNode;
+				}
+
+		  this.editor.scrollToElement(holdEnd);
+			}
+		catch (e)
+			{
+			// we could try to place the cursor at the end of the document.
+			}
+		}
+
+  this.editor.updateToolbar();
+
+	HTMLArea._stopEvent(ev);
+
+	return true;
+
+	};	// end of handleEnter()
+
+// END

Added: plog/trunk/js/xinha/plugins/FullScreen/full-screen.js
===================================================================
--- plog/trunk/js/xinha/plugins/FullScreen/full-screen.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/FullScreen/full-screen.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,203 @@
+function FullScreen(editor, args)
+{
+  this.editor = editor;
+  editor._superclean_on = false;
+  cfg = editor.config;
+
+  cfg.registerButton
+  ( 'fullscreen',
+    this._lc("Maximize/Minimize Editor"),
+    [_editor_url + cfg.imgURL + 'ed_buttons_main.gif',8,0], true,
+      function(e, objname, obj)
+      {
+        e._fullScreen();
+        if(e._isFullScreen)
+        {
+          obj.swapImage([_editor_url + cfg.imgURL + 'ed_buttons_main.gif',9,0]);
+        }
+        else
+        {
+          obj.swapImage([_editor_url + cfg.imgURL + 'ed_buttons_main.gif',8,0]);
+        }
+      }
+  );
+
+  // See if we can find 'popupeditor' and replace it with fullscreen
+  cfg.addToolbarElement("fullscreen", "popupeditor", 0);
+}
+
+FullScreen._pluginInfo =
+{
+  name     : "FullScreen",
+  version  : "1.0",
+  developer: "James Sleeman",
+  developer_url: "http://www.gogo.co.nz/",
+  c_owner      : "Gogo Internet Services",
+  license      : "htmlArea",
+  sponsor      : "Gogo Internet Services",
+  sponsor_url  : "http://www.gogo.co.nz/"
+};
+
+FullScreen.prototype._lc = function(string) {
+    return HTMLArea._lc(string, 'FullScreen');
+}
+
+/** fullScreen makes an editor take up the full window space (and resizes when the browser is resized)
+ *  the principle is the same as the "popupwindow" functionality in the original htmlArea, except
+ *  this one doesn't popup a window (it just uses to positioning hackery) so it's much more reliable
+ *  and much faster to switch between
+ */
+
+HTMLArea.prototype._fullScreen = function()
+{
+  var e = this;
+  function sizeItUp()
+  {
+    if(!e._isFullScreen || e._sizing) return false;
+    e._sizing = true;
+    // Width & Height of window
+    var x,y;
+    if (window.innerHeight) // all except Explorer
+    {
+      x = window.innerWidth;
+      y = window.innerHeight;
+    }
+    else if (document.documentElement && document.documentElement.clientHeight)
+      // Explorer 6 Strict Mode
+    {
+      x = document.documentElement.clientWidth;
+      y = document.documentElement.clientHeight;
+    }
+    else if (document.body) // other Explorers
+    {
+      x = document.body.clientWidth;
+      y = document.body.clientHeight;
+    }
+
+    e.sizeEditor(x + 'px',y + 'px',true,true);
+    e._sizing = false;
+  }
+
+  function sizeItDown()
+  {
+    if(e._isFullScreen || e._sizing) return false;
+    e._sizing = true;
+    e.initSize();
+    e._sizing = false;
+  }
+
+  /** It's not possible to reliably get scroll events, particularly when we are hiding the scrollbars
+   *   so we just reset the scroll ever so often while in fullscreen mode
+   */
+  function resetScroll()
+  {
+    if(e._isFullScreen)
+    {
+      window.scroll(0,0);
+      window.setTimeout(resetScroll,150);
+    }
+  }
+
+  if(typeof this._isFullScreen == 'undefined')
+  {
+    this._isFullScreen = false;
+    if(e.target != e._iframe)
+    {
+      HTMLArea._addEvent(window, 'resize', sizeItUp);
+    }
+  }
+
+  // Gecko has a bug where if you change position/display on a
+  // designMode iframe that designMode dies.
+  if(HTMLArea.is_gecko)
+  {
+    this.deactivateEditor();
+  }
+
+  if(this._isFullScreen)
+  {
+    // Unmaximize
+    this._htmlArea.style.position = '';
+    try
+    {
+      if(HTMLArea.is_ie)
+      {
+        var bod = document.getElementsByTagName('html');
+      }
+      else
+      {
+        var bod = document.getElementsByTagName('body');
+      }
+      bod[0].style.overflow='';
+    }
+    catch(e)
+    {
+      // Nutthin
+    }
+    this._isFullScreen = false;
+    sizeItDown();
+
+    // Restore all ancestor positions
+    var ancestor = this._htmlArea;
+    while((ancestor = ancestor.parentNode) && ancestor.style)
+    {
+      ancestor.style.position = ancestor._xinha_fullScreenOldPosition;
+      ancestor._xinha_fullScreenOldPosition = null;
+    }
+
+    window.scroll(this._unScroll.x, this._unScroll.y);
+  }
+  else
+  {
+
+    // Get the current Scroll Positions
+    this._unScroll =
+    {
+     x:(window.pageXOffset)?(window.pageXOffset):(document.documentElement)?document.documentElement.scrollLeft:document.body.scrollLeft,
+     y:(window.pageYOffset)?(window.pageYOffset):(document.documentElement)?document.documentElement.scrollTop:document.body.scrollTop
+    };
+
+
+    // Make all ancestors position = static
+    var ancestor = this._htmlArea;
+    while((ancestor = ancestor.parentNode) && ancestor.style)
+    {
+      ancestor._xinha_fullScreenOldPosition = ancestor.style.position;
+      ancestor.style.position = 'static';
+    }
+
+    // Maximize
+    window.scroll(0,0);
+    this._htmlArea.style.position = 'absolute';
+    this._htmlArea.style.zIndex   = 999;
+    this._htmlArea.style.left     = 0;
+    this._htmlArea.style.top      = 0;
+    this._isFullScreen = true;
+    resetScroll();
+
+    try
+    {
+      if(HTMLArea.is_ie)
+      {
+        var bod = document.getElementsByTagName('html');
+      }
+      else
+      {
+        var bod = document.getElementsByTagName('body');
+      }
+      bod[0].style.overflow='hidden';
+    }
+    catch(e)
+    {
+      // Nutthin
+    }
+
+    sizeItUp();
+  }
+
+  if(HTMLArea.is_gecko)
+  {
+    this.activateEditor();
+  }
+  this.focusEditor();
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/plugins/FullScreen/lang/de.js
===================================================================
--- plog/trunk/js/xinha/plugins/FullScreen/lang/de.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/FullScreen/lang/de.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,17 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8
+// translated: Raimund Meyer xinha at ray-of-light.org
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Maximize/Minimize Editor": "Editor maximieren/verkleinern"
+}

Added: plog/trunk/js/xinha/plugins/FullScreen/lang/fr.js
===================================================================
--- plog/trunk/js/xinha/plugins/FullScreen/lang/fr.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/FullScreen/lang/fr.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,17 @@
+// I18N constants
+
+// LANG: "fr", ENCODING: UTF-8
+// Author: Laurent Vilday, mokhet at mokhet.com
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+{
+  "Maximize/Minimize Editor": "Agrandir/Réduire l'éditeur"
+}

Added: plog/trunk/js/xinha/plugins/FullScreen/lang/no.js
===================================================================
--- plog/trunk/js/xinha/plugins/FullScreen/lang/no.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/plugins/FullScreen/lang/no.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,7 @@
+// I18N constants
+// LANG: "no", ENCODING: UTF-8
+// translated: Kim Steinhaug, http://www.steinhaug.com/, kim at steinhaug.com
+
+{
+  "Maximize/Minimize Editor": "Maksimer/Minimer WYSIWYG vindu"
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/popupdiv.js
===================================================================
--- plog/trunk/js/xinha/popupdiv.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popupdiv.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,369 @@
+/** This file is derived from PopupDiv, developed by Mihai Bazon for
+ * SamWare.net.  Modifications were needed to make it usable in HTMLArea.
+ * HTMLArea is a free WYSIWYG online HTML editor from InteractiveTools.com.
+ *
+ * This file does not function standalone.  It is dependent of global functions
+ * defined in HTMLArea-3.0 (htmlarea.js).
+ *
+ * Please see file htmlarea.js for further details.
+ **/
+
+var is_ie = ( (navigator.userAgent.toLowerCase().indexOf("msie") != -1) &&
+	      (navigator.userAgent.toLowerCase().indexOf("opera") == -1) );
+var is_compat = (document.compatMode == "BackCompat");
+
+function PopupDiv(editor, titleText, handler, initFunction) {
+	var self = this;
+
+	this.editor = editor;
+	this.doc = editor._mdoc;
+	this.handler = handler;
+
+	var el = this.doc.createElement("div");
+	el.className = "content";
+
+	var popup = this.doc.createElement("div");
+	popup.className = "dialog popupdiv";
+	this.element = popup;
+	var s = popup.style;
+	s.position = "absolute";
+	s.left = "0px";
+	s.top = "0px";
+
+	var title = this.doc.createElement("div");
+	title.className = "title";
+	this.title = title;
+	popup.appendChild(title);
+
+	HTMLArea._addEvent(title, "mousedown", function(ev) {
+		self._dragStart(is_ie ? window.event : ev);
+	});
+
+	var button = this.doc.createElement("div");
+	button.className = "button";
+	title.appendChild(button);
+	button.innerHTML = "&#x00d7;";
+	title.appendChild(this.doc.createTextNode(titleText));
+	this.titleText = titleText;
+
+	button.onmouseover = function() {
+		this.className += " button-hilite";
+	};
+	button.onmouseout = function() {
+		this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
+	};
+	button.onclick = function() {
+		this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
+		self.close();
+	};
+
+	popup.appendChild(el);
+	this.content = el;
+
+	this.doc.body.appendChild(popup);
+
+	this.dragging = false;
+	this.onShow = null;
+	this.onClose = null;
+	this.modal = false;
+
+	initFunction(this);
+};
+
+PopupDiv.currentPopup = null;
+
+PopupDiv.prototype.showAtElement = function(el, mode) {
+	this.defaultSize();
+	var pos, ew, eh;
+	var popup = this.element;
+	popup.style.display = "block";
+	var w = popup.offsetWidth;
+	var h = popup.offsetHeight;
+	popup.style.display = "none";
+	if (el != window) {
+		pos = PopupDiv.getAbsolutePos(el);
+		ew = el.offsetWidth;
+		eh = el.offsetHeight;
+	} else {
+		pos = {x:0, y:0};
+		var size = PopupDiv.getWindowSize();
+		ew = size.x;
+		eh = size.y;
+	}
+	var FX = false, FY = false;
+	if (mode.indexOf("l") != -1) {
+		pos.x -= w;
+		FX = true;
+	}
+	if (mode.indexOf("r") != -1) {
+		pos.x += ew;
+		FX = true;
+	}
+	if (mode.indexOf("t") != -1) {
+		pos.y -= h;
+		FY = true;
+	}
+	if (mode.indexOf("b") != -1) {
+		pos.y += eh;
+		FY = true;
+	}
+	if (mode.indexOf("c") != -1) {
+		FX || (pos.x += Math.round((ew - w) / 2));
+		FY || (pos.y += Math.round((eh - h) / 2));
+	}
+	this.showAt(pos.x, pos.y);
+};
+
+PopupDiv.prototype.defaultSize = function() {
+	var s = this.element.style;
+	var cs = this.element.currentStyle;
+	var addX = (is_ie && is_compat) ? (parseInt(cs.borderLeftWidth) +
+					   parseInt(cs.borderRightWidth) +
+					   parseInt(cs.paddingLeft) +
+					   parseInt(cs.paddingRight)) : 0;
+	var addY = (is_ie && is_compat) ? (parseInt(cs.borderTopWidth) +
+					   parseInt(cs.borderBottomWidth) +
+					   parseInt(cs.paddingTop) +
+					   parseInt(cs.paddingBottom)) : 0;
+	s.display = "block";
+	s.width = (this.content.offsetWidth + addX) + "px";
+	s.height = (this.content.offsetHeight + this.title.offsetHeight) + "px";
+	s.display = "none";
+};
+
+PopupDiv.prototype.showAt = function(x, y) {
+	this.defaultSize();
+	var s = this.element.style;
+	s.display = "block";
+	s.left = x + "px";
+	s.top = y + "px";
+	this.hideShowCovered();
+
+	PopupDiv.currentPopup = this;
+	HTMLArea._addEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+	HTMLArea._addEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+	if (is_ie && this.modal) {
+		this.doc.body.setCapture(false);
+		this.doc.body.onlosecapture = function() {
+			(PopupDiv.currentPopup) && (this.doc.body.setCapture(false));
+		};
+	}
+	window.event && HTMLArea._stopEvent(window.event);
+
+	if (typeof this.onShow == "function") {
+		this.onShow();
+	} else if (typeof this.onShow == "string") {
+		eval(this.onShow);
+	}
+
+	var field = this.element.getElementsByTagName("input")[0];
+	if (!field) {
+		field = this.element.getElementsByTagName("select")[0];
+	}
+	if (!field) {
+		field = this.element.getElementsByTagName("textarea")[0];
+	}
+	if (field) {
+		field.focus();
+	}
+};
+
+PopupDiv.prototype.close = function() {
+	this.element.style.display = "none";
+	PopupDiv.currentPopup = null;
+	this.hideShowCovered();
+	HTMLArea._removeEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+	HTMLArea._removeEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+	is_ie && this.modal && this.doc.body.releaseCapture();
+	if (typeof this.onClose == "function") {
+		this.onClose();
+	} else if (typeof this.onClose == "string") {
+		eval(this.onClose);
+	}
+	this.element.parentNode.removeChild(this.element);
+};
+
+PopupDiv.prototype.getForm = function() {
+	var forms = this.content.getElementsByTagName("form");
+	return (forms.length > 0) ? forms[0] : null;
+};
+
+PopupDiv.prototype.callHandler = function() {
+	var tags = ["input", "textarea", "select"];
+	var params = new Object();
+	for (var ti = tags.length; --ti >= 0;) {
+		var tag = tags[ti];
+		var els = this.content.getElementsByTagName(tag);
+		for (var j = 0; j < els.length; ++j) {
+			var el = els[j];
+			params[el.name] = el.value;
+		}
+	}
+	this.handler(this, params);
+	return false;
+};
+
+PopupDiv.getAbsolutePos = function(el) {
+	var r = { x: el.offsetLeft, y: el.offsetTop };
+	if (el.offsetParent) {
+		var tmp = PopupDiv.getAbsolutePos(el.offsetParent);
+		r.x += tmp.x;
+		r.y += tmp.y;
+	}
+	return r;
+};
+
+PopupDiv.getWindowSize = function() {
+	if (window.innerHeight) {
+		return { y: window.innerHeight, x: window.innerWidth };
+	}
+	if (this.doc.body.clientHeight) {
+		return { y: this.doc.body.clientHeight, x: this.doc.body.clientWidth };
+	}
+	return { y: this.doc.documentElement.clientHeight, x: this.doc.documentElement.clientWidth };
+};
+
+PopupDiv.prototype.hideShowCovered = function () {
+	var self = this;
+	function isContained(el) {
+		while (el) {
+			if (el == self.element) {
+				return true;
+			}
+			el = el.parentNode;
+		}
+		return false;
+	};
+	var tags = new Array("applet", "select");
+	var el = this.element;
+
+	var p = PopupDiv.getAbsolutePos(el);
+	var EX1 = p.x;
+	var EX2 = el.offsetWidth + EX1;
+	var EY1 = p.y;
+	var EY2 = el.offsetHeight + EY1;
+
+	if (el.style.display == "none") {
+		EX1 = EX2 = EY1 = EY2 = 0;
+	}
+
+	for (var k = tags.length; k > 0; ) {
+		var ar = this.doc.getElementsByTagName(tags[--k]);
+		var cc = null;
+
+		for (var i = ar.length; i > 0;) {
+			cc = ar[--i];
+			if (isContained(cc)) {
+				cc.style.visibility = "visible";
+				continue;
+			}
+
+			p = PopupDiv.getAbsolutePos(cc);
+			var CX1 = p.x;
+			var CX2 = cc.offsetWidth + CX1;
+			var CY1 = p.y;
+			var CY2 = cc.offsetHeight + CY1;
+
+			if ((CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
+				cc.style.visibility = "visible";
+			} else {
+				cc.style.visibility = "hidden";
+			}
+		}
+	}
+};
+
+PopupDiv.prototype._dragStart = function (ev) {
+	if (this.dragging) {
+		return false;
+	}
+	this.dragging = true;
+	PopupDiv.currentPopup = this;
+	var posX = ev.clientX;
+	var posY = ev.clientY;
+	if (is_ie) {
+		posY += this.doc.body.scrollTop;
+		posX += this.doc.body.scrollLeft;
+	} else {
+		posY += window.scrollY;
+		posX += window.scrollX;
+	}
+	var st = this.element.style;
+	this.xOffs = posX - parseInt(st.left);
+	this.yOffs = posY - parseInt(st.top);
+	HTMLArea._addEvent(this.doc, "mousemove", PopupDiv.dragIt);
+	HTMLArea._addEvent(this.doc, "mouseover", HTMLArea._stopEvent);
+	HTMLArea._addEvent(this.doc, "mouseup", PopupDiv.dragEnd);
+	HTMLArea._stopEvent(ev);
+};
+
+PopupDiv.dragIt = function (ev) {
+	var popup = PopupDiv.currentPopup;
+	if (!(popup && popup.dragging)) {
+		return false;
+	}
+	is_ie && (ev = window.event);
+	var posX = ev.clientX;
+	var posY = ev.clientY;
+	if (is_ie) {
+		posY += this.doc.body.scrollTop;
+		posX += this.doc.body.scrollLeft;
+	} else {
+		posY += window.scrollY;
+		posX += window.scrollX;
+	}
+	popup.hideShowCovered();
+	var st = popup.element.style;
+	st.left = (posX - popup.xOffs) + "px";
+	st.top = (posY - popup.yOffs) + "px";
+	HTMLArea._stopEvent(ev);
+};
+
+PopupDiv.dragEnd = function () {
+	var popup = PopupDiv.currentPopup;
+	if (!popup) {
+		return false;
+	}
+	popup.dragging = false;
+	HTMLArea._removeEvent(popup.doc, "mouseup", PopupDiv.dragEnd);
+	HTMLArea._removeEvent(popup.doc, "mouseover", HTMLArea._stopEvent);
+	HTMLArea._removeEvent(popup.doc, "mousemove", PopupDiv.dragIt);
+	popup.hideShowCovered();
+};
+
+PopupDiv.checkPopup = function (ev) {
+	is_ie && (ev = window.event);
+	var el = is_ie ? ev.srcElement : ev.target;
+	var cp = PopupDiv.currentPopup;
+	for (; (el != null) && (el != cp.element); el = el.parentNode);
+	if (el == null) {
+		cp.modal || ev.type == "mouseover" || cp.close();
+		HTMLArea._stopEvent(ev);
+	}
+};
+
+PopupDiv.prototype.addButtons = function() {
+	var self = this;
+	var div = this.doc.createElement("div");
+	this.content.appendChild(div);
+	div.className = "buttons";
+	for (var i = 0; i < arguments.length; ++i) {
+		var btn = arguments[i];
+		var button = this.doc.createElement("button");
+		div.appendChild(button);
+		button.innerHTML = HTMLArea._lc(buttons[btn], 'HTMLArea');
+		switch (btn) {
+		    case "ok":
+			button.onclick = function() {
+				self.callHandler();
+				self.close();
+			};
+			break;
+		    case "cancel":
+			button.onclick = function() {
+				self.close();
+			};
+			break;
+		}
+	}
+};

Added: plog/trunk/js/xinha/popups/about.html
===================================================================
--- plog/trunk/js/xinha/popups/about.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/about.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,295 @@
+<!--
+
+(c) dynarch.com, 2003-2004
+Author: Mihai Bazon, http://dynarch.com/mishoo
+Distributed as part of HTMLArea 3.0
+
+"You are not expected to understand this...  I don't neither."
+
+                      (from The Linux Kernel Source Code,
+                            ./arch/x86_64/ia32/ptrace.c:90)
+
+;-)
+
+-->
+
+<html style="height: 100%">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>About Xinha</title>
+<script type="text/javascript" src="popup.js"></script>
+<script type="text/javascript">
+window.resizeTo(450, 250);
+var TABS = [];
+var CURRENT_TAB = 0;
+var CONTENT_HEIGHT_DIFF = 0;
+var CONTENT_WIDTH_DIFF = 0;
+function selectTab(idx) {
+  var ct = TABS[CURRENT_TAB];
+  ct.className = ct.className.replace(/\s*tab-current\s*/, ' ');
+  ct = TABS[CURRENT_TAB = idx];
+  ct.className += ' tab-current';
+  for (var i = TABS.length; --i >= 0;) {
+    var area = document.getElementById("tab-area-" + i);
+    if (CURRENT_TAB == i) {
+      area.style.display = "block";
+    } else {
+      area.style.display = "none";
+    }
+  }
+  document.body.style.visibility = "hidden";
+  document.body.style.visibility = "visible";
+  document.cookie = "HTMLAREA-ABOUT-TAB=" + idx;
+}
+var editor = null;
+function initDocument() {
+  editor = window.dialogArguments;
+  HTMLArea = window.opener.HTMLArea;
+
+  var plugins = document.getElementById("plugins");
+  var j = 0;
+  var html = "<table width='99%' cellpadding='2' cellspacing=2 style='margin-top: 1em; collapse-borders: collapse; border: 1px solid black;'>" +
+    "<thead><tr>" +
+    "<td>Name</td>" +
+    "<td>Developer</td>" +
+    "<td>Sponsored by</td>" +
+    "<td>License</td>" +
+    "</tr></thead><tbody>";
+  for (var i in editor.plugins) {
+    var info = editor.plugins[i];
+    html += "<tr><td>" + info.name + " v" + info.version + "</td>" +
+            "<td><a href='" + info.developer_url + "' target='_blank' title='Visit developer website'>" +
+      info.developer + "</a></td>" +
+      "<td><a href='" + info.sponsor_url + "' target='_blank' title='Visit sponsor website'>" +
+      info.sponsor + "</a></td>" +
+      "<td>" + info.license + "</td></tr>";
+    ++j;
+  }
+
+  if (j) {
+          html += "</tbody></table>" +
+      "<p>License \"htmlArea\" means that the plugin is distributed under the same terms " +
+      "as Xinha itself.</p>";
+    plugins.innerHTML = "<p>The following plugins have been loaded.</p>" + html;
+  } else {
+    plugins.innerHTML = "<p>No plugins have been loaded</p>";
+  }
+
+  plugins.innerHTML += "<p>User agent reports:<br/>" + navigator.userAgent + "</p>";
+
+  var content = document.getElementById("content");
+  if (window.innerHeight) {
+    CONTENT_HEIGHT_DIFF = window.innerHeight - 250;
+    CONTENT_WIDTH_DIFF = window.innerWidth - content.offsetWidth;
+  } else {
+    CONTENT_HEIGHT_DIFF = document.body.offsetHeight - 250;
+    CONTENT_WIDTH_DIFF = document.body.offsetWidth - 400;
+  }
+  window.onresize();
+  var bar = document.getElementById("tabbar");
+  j = 0;
+  for (var i = bar.firstChild; i; i = i.nextSibling) {
+    TABS.push(i);
+    i.__msh_tab = j;
+    i.onmousedown = function(ev) { selectTab(this.__msh_tab); HTMLArea._stopEvent(ev || window.event); };
+    var area = document.getElementById("tab-area-" + j);
+    if (/tab-current/.test(i.className)) {
+      CURRENT_TAB = j;
+      area.style.display = "block";
+    } else {
+      area.style.display = "none";
+    }
+    ++j;
+  }
+  if (document.cookie.match(/HTMLAREA-ABOUT-TAB=([0-9]+)/))
+    selectTab(RegExp.$1);
+}
+window.onresize = function() {
+  var content = document.getElementById("content");
+  if (window.innerHeight) {
+    content.style.height = (window.innerHeight - CONTENT_HEIGHT_DIFF) + "px";
+    content.style.width = (window.innerWidth - CONTENT_WIDTH_DIFF) + "px";
+  } else {
+    content.style.height = (document.body.offsetHeight - CONTENT_HEIGHT_DIFF) + "px";
+    //content.style.width = (document.body.offsetWidth - CONTENT_WIDTH_DIFF) + "px";
+  }
+}
+</script>
+<style>
+  html,body,textarea,table
+  { font-family: helvetica,arial,sans-serif;
+    font-size: 11px; padding: 0px; margin: 0px;
+  }
+
+  body { padding: 0px; background: #f5f6f6; color: black; }
+  a:link, a:visited { color: #00f; }
+  a:hover           { color: #f00; }
+  a:active          { color: #f80; }
+  button            { font: 11px; border-width: 1px; background-color:#f5f6f6; color:black; }
+
+  p { margin: 0.5em 0px; }
+
+  #tdheader h1
+  { font: bold 40px "Staccato222 BT", cursive; margin: 0px; padding-left:4px; border-bottom: 1px solid #6a6; }
+  h1 { font: bold 20px; margin: 0px; border-bottom: 1px solid #6a6; }
+  h2 { font: bold 110%; margin: 0.7em 0px; }
+
+  thead {
+    font-weight: bold;
+    background-color: #CCC;
+  }
+
+  thead td { padding-left:4px; }
+
+  .buttons {
+    text-align: right; padding: 3px;
+    background-color: white;
+    border-top: 1px solid #555;
+  }
+
+  #tabbar {
+    position: relative;
+    left: 10px;
+  }
+  .tab {
+    color: #OOO;
+    cursor: pointer;
+    margin-left: -5px;
+    float: left; position: relative;
+    border: 1px solid #555;
+    top: -3px; left: -2px;
+    padding: 2px 10px 3px 10px;
+    border-top: none; background-color: #CCC;
+    -moz-border-radius: 0px 0px 4px 4px;
+    z-index: 0;
+  }
+  .tab-current
+  {
+    color: #000;
+    top: -4px;
+    background-color: #f5f6f6;
+    padding: 3px 10px 4px 10px;
+    z-index: 10;
+  }
+
+  li, ol, ul { margin-top: 0px; margin-bottom: 0px; }
+</style></head>
+<body onload="__dlg_init(); initDocument();"
+><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;
+      width: 100%; height: 100%;">
+
+<tr style="height: 1em"><td id="tdheader">
+
+<h1>Xinha</h1>
+
+</td></tr>
+<tr><td id="tdcontent" style="padding: 0.5em;">
+
+<div style="overflow: auto; height: 250px;" id="content">
+<div id="tab-areas">
+
+<div id="tab-area-0">
+
+  <p>A free WYSIWYG editor replacement for <tt>&lt;textarea&gt;</tt> fields.</p>
+  <p>Visit the <a href="http://xinha.gogo.co.nz/">Xinha Website</a> for more information.</p>
+
+  <p>
+   Use of Xinha is granted by the terms of the htmlArea License (based on BSD license)
+  </p>
+  <p>
+    Xinha was originally based on work by Mihai Bazon which is:
+  </p>
+  <blockquote><pre>Copyright (c) 2003-2004 dynarch.com.
+    Copyright (c) 2002-2003 interactivetools.com, inc.
+    This copyright notice MUST stay intact for use.</pre></blockquote>
+
+</div>
+
+<div id="tab-area-1">
+
+  <p>
+   The development of Xinha would not have been possible without the original work of <a href="http://dynarch.com/">Mihai Bazon</a>, <a href="http://interactivetools.com" target="_blank">InteractiveTools.com</a>, and the many sponsors and contributors from around the world.
+  </p>
+
+</div>
+
+<div id="tab-area-2">
+<pre>htmlArea License (based on BSD license)
+Copyright (c) 2002-2004, interactivetools.com, inc.
+Copyright (c) 2003-2004 dynarch.com
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1) Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2) Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3) Neither the name of interactivetools.com, inc. nor the names of its
+   contributors may be used to endorse or promote products derived from this
+   software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.</pre>
+</div>
+
+<div id="tab-area-3">
+<div id="plugins">
+</div>
+</div>
+
+
+<div id="tab-area-4">
+  <script type="text/javascript">
+    if(window.opener && window.opener.HTMLArea)
+    {
+      var ver = window.opener.HTMLArea.version;
+      document.write('<pre>'
+                      + '\nRelease: ' + ver.Release + ' (' + ver.Date + ')'
+                      + '\nHead: ' + ver.Head
+                      + '\nRevision: ' + ver.Revision
+                      + '\nLast Changed By: ' + ver.RevisionBy
+                      + '\n' +
+                      '</pre>');
+    }
+    else
+    {
+      document.write('<pre>Version information unavailable.</pre>');
+    }
+  </script>
+</div>
+
+</div></div>
+
+
+</td></tr>
+<tr style="height: 1em"><td id="tdfooter">
+
+
+<div class="buttons">
+<div id="tabbar"
+><div class="tab tab-current"
+>About</div><div class="tab"
+>Thanks</div><div class="tab"
+>License</div><div class="tab"
+>Plugins</div><div class="tab"
+>Version</div></div>
+<button type="button" onclick="__dlg_close(null);">Close</button>
+</div>
+
+</td></tr></table>
+
+</body></html>

Added: plog/trunk/js/xinha/popups/blank.html
===================================================================
--- plog/trunk/js/xinha/popups/blank.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/blank.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,2 @@
+<html>
+</html>
\ No newline at end of file

Added: plog/trunk/js/xinha/popups/color_picker.js
===================================================================
--- plog/trunk/js/xinha/popups/color_picker.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/color_picker.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,500 @@
+
+  /**
+   * Gogo Internet Services Color Picker Javascript Widget
+   * colorPicker for short.
+   *
+   * @author James Sleeman <james at gogo.co.nz>
+   * @date June, 2005
+   *
+   * The colorPicker class provides access to a color map for selecting
+   * colors which will be passed back to a callback (usually such a callback would
+   * write the RGB hex value returned into a field, but that's up to you).
+   *
+   * The color map presented is a standard rectangular pallate with 0->360 degrees of
+   * hue on the Y axis and 0->100% saturation on the X axis, the value (brightness) is
+   * selectable as a vertical column of grey values.  Also present is a one row of
+   * white->grey->black for easy selection of these colors.
+   *
+   * A checkbox is presented, which when checked will force the palatte into "web safe"
+   * mode, only colours in the "web safe palatte" of 216 colors will be shown, the palatte
+   * is adjusted so that the normal blend of colours are "rounded" to the nearest web safe
+   * one.  It should be noted that "web safe" colours really are a thing of the past,
+   * not only can pretty much every body display several million colours, but it's actually
+   * been found that of those 216 web safe colours only 20 to 30 are actually going to be
+   * displayed equally on the majority of monitors, and those are mostly yellows!
+   *
+   * =Usage Example=
+   * {{{
+   *  <!-- Here is the field -->         <!-- And we will use this button to open the picker"
+   *  <input type="text" id="myField" /> <input type="button" value="..." id="myButton" />
+   *  <script>
+   *    // now when the window loads link everything up
+   *    window.onload = function()
+   *    {
+   *
+   *      var myField  = document.getElementById('myField');  // Get our field
+   *      var myButton = document.getElementById('myButton'); // And the button
+   *      var myPicker = new colorPicker                      // Make a picker
+   *        (
+   *          {
+   *              // Cellsize is the width and height of each colour cell
+   *            cellsize: '5px',
+   *              // Callback is the function to execute when we are done,
+   *              // this one puts the color value into the field
+   *            callback: function(color){myField.value=color},
+   *              // Granularity defines the maximum number of colors per row/column
+   *              // more colors (high number) gives a smooth gradient of colors
+   *              // but it will take (much) longer to display, while a small number
+   *              // displays quickly, but doesn't show as many different colors.
+   *              // Experiement with it, 18 seems like a good number.
+   *            granularity: 18
+   *           }
+   *        );
+   *
+   *      // And now hookup the button to open the picker,
+   *      //  the function to do that is myPicker.open()
+   *      //  it accepts two parameters, the "anchorage" and the element to anchor to
+   *      //  to anchor to.
+   *      //
+   *      //  anchorage is made up of two of the keywords bottom,top,left and right
+   *      //    left:   the left edge of the picker will align to the left edge of the element
+   *      // or right:  the right edgeof the picker aligns to the right edge of the element
+   *      //    top:    the picker will appear above the element
+   *      // or bottom: the picker will appear below the element
+   *
+   *      myButton.onclick =
+   *        function()
+   *        {              // anchorage   , element to anchor to
+   *          myPicker.open('bottom,right', myPicker)
+   *        };
+   *    }
+   *  </script>
+   * }}}
+   */
+
+  function colorPicker(params)
+  {
+    var picker = this;
+    this.callback = params.callback?params.callback:function(color){alert('You picked ' + color )};
+
+    this.cellsize = params.cellsize?params.cellsize:'10px';
+    this.side     = params.granularity?params.granularity:18;
+
+    this.value = 1;
+    this.saved_cells = null;
+    this.table = document.createElement('table');
+    this.table.cellSpacing = this.table.cellPadding = 0;
+    this.tbody = document.createElement('tbody');
+    this.table.appendChild(this.tbody);
+    this.table.style.border = '1px solid WindowFrame';
+    this.table.style.backgroundColor = 'Window';
+    // Add a title bar and close button
+    var tr = document.createElement('tr');
+    var td = document.createElement('td');
+    var but = document.createElement('button');
+    but.onclick = function() { picker.close(); }
+    but.appendChild(document.createTextNode('x'));
+    td.appendChild(but);
+    td.style.position = 'relative';
+    td.style.verticalAlign = 'middle';
+    but.style.cssFloat = 'right';
+    but.style.styleFloat = 'right';
+
+
+    td.colSpan = this.side + 3;
+    td.style.backgroundColor = 'ActiveCaption';
+    td.style.color = 'CaptionText';
+    td.style.fontFamily = 'small-caption,caption,sans-serif';
+    td.style.fontSize = 'x-small';
+    td.appendChild(document.createTextNode('Click a color...'));
+    td.style.borderBottom = '1px solid WindowFrame';
+
+    tr.appendChild(td);
+    this.tbody.appendChild(tr);
+    but = tr = td = null;
+
+    this.constrain_cb = document.createElement('input');
+    this.constrain_cb.type = 'checkbox';
+
+    this.chosenColor     = document.createElement('input');
+    this.chosenColor.type = 'text';
+    this.chosenColor.size = '7';
+
+    this.backSample     = document.createElement('div');
+    this.backSample.appendChild(document.createTextNode('\u00A0'));
+    this.backSample.style.fontWeight = 'bold';
+    this.backSample.style.fontFamily = 'small-caption,caption,sans-serif';
+    this.backSample.fontSize = 'x-small';
+
+    this.foreSample     = document.createElement('div');
+    this.foreSample.appendChild(document.createTextNode('Sample'));
+    this.foreSample.style.fontWeight = 'bold';
+    this.foreSample.style.fontFamily = 'small-caption,caption,sans-serif';
+    this.foreSample.fontSize = 'x-small';
+
+    /** Convert a decimal number to a two byte hexadecimal representation.
+      * Zero-pads if necessary.
+      *
+      * @param integer dec Integer from 0 -> 255
+      * @returns string 2 character hexadecimal (zero padded)
+      */
+    function toHex(dec)
+    {
+      var h = dec.toString(16);
+      if(h.length < 2) h = '0' + h;
+      return h;
+    }
+
+    /** Convert a color object {red:x, green:x, blue:x} to an RGB hex triplet
+     * @param object tuple {red:0->255, green:0->255, blue:0->255}
+     * @returns string hex triplet (#rrggbb)
+     */
+
+    function tupleToColor(tuple)
+    {
+      return '#' + toHex(tuple.red) + toHex(tuple.green) + toHex(tuple.blue);
+    }
+
+    /** Determine the nearest power of a number to another number
+     * (eg nearest power of 4 to 5 => 4, of 4 to 7 => 8)
+     *
+     * @usedby rgbToWebsafe
+     * @param number num number to round to nearest power of <power>
+     * @param number power number to find the nearest power of
+     * @returns number Nearest power of <power> to num.
+     */
+
+    function nearestPowerOf(num,power)
+    {
+      return Math.round(Math.round(num / power) * power);
+    }
+
+    /** Concatenate the hex representation of dec to itself and return as an integer.
+     *  eg dec = 10 -> A -> AA -> 170
+     *
+     * @usedby rgbToWebsafe
+     * @param dec integer
+     * @returns integer
+     */
+
+    function doubleHexDec(dec)
+    {
+      return parseInt(dec.toString(16) + dec.toString(16), 16);
+    }
+
+    /** Convert a given RGB color to the nearest "Web-Safe" color.  A websafe color only has the values
+     *  00, 33, 66, 99, CC and FF for each of the red, green and blue components (thus 6 shades of each
+     *  in combination to produce 6 * 6 * 6 = 216 colors).
+     *
+     * @param    color object {red:0->255, green:0->255, blue:0->255}
+     * @returns  object {red:51|102|153|204|255, green:51|102|153|204|255, blue:51|102|153|204|255}
+     */
+    function rgbToWebsafe(color)
+    {
+      // For each take the high byte, divide by three, round and multiply by three before rounding again
+      color.red   = doubleHexDec(nearestPowerOf(parseInt(toHex(color.red).charAt(0), 16), 3));
+      color.blue  = doubleHexDec(nearestPowerOf(parseInt(toHex(color.blue).charAt(0), 16), 3));
+      color.green = doubleHexDec(nearestPowerOf(parseInt(toHex(color.green).charAt(0), 16), 3));
+      return color;
+    }
+
+    /** Convert a combination of hue, saturation and value into an RGB color.
+     *  Hue is defined in degrees, saturation and value as a floats between 0 and 1 (0% -> 100%)
+     *
+     * @param h float angle of hue around color wheel 0->360
+     * @param s float saturation of color (no color (grey)) 0->1 (vibrant)
+     * @param v float value (brightness) of color (black) 0->1 (bright)
+     * @returns object {red:0->255, green:0->255, blue:0->255}
+     * @seealso http://en.wikipedia.org/wiki/HSV_color_space
+     */
+    function hsvToRGB(h,s,v)
+    {
+      var colors;
+      if(s == 0)
+      {
+        // GREY
+        colors = {red:v,green:v,blue:v}
+      }
+      else
+      {
+        h /= 60;
+        var i = Math.floor(h);
+        var f = h - i;
+        var p = v * (1 - s);
+        var q = v * (1 - s * f);
+        var t = v * (1 - s * (1 - f) );
+        switch(i)
+        {
+          case 0: colors =  {red:v, green:t, blue:p}; break;
+          case 1: colors =  {red:q, green:v, blue:p}; break;
+          case 2: colors =  {red:p, green:v, blue:t}; break;
+          case 3: colors =  {red:p, green:q, blue:v}; break;
+          case 4: colors =  {red:t, green:p, blue:v}; break;
+          case 5:
+          default:colors =  {red:v, green:p, blue:q}; break;
+        }
+      }
+      colors.red = Math.ceil(colors.red * 255);
+      colors.green = Math.ceil(colors.green * 255);
+      colors.blue = Math.ceil(colors.blue * 255);
+      return colors;
+    }
+
+    /** Open the color picker
+     *
+     * @param string anchorage pair of sides of element to anchor the picker to
+     *   "top,left" "top,right" "bottom,left" or "bottom,right"
+     * @param HTML_ELEMENT element the element to anchor the picker to sides of
+     *
+     * @note The element is just referenced here for positioning (anchoring), it
+     * does not automatically get the color copied into it.  See the usage instructions
+     * for the class.
+     */
+
+    this.open = function(anchorage,element)
+    {
+      this.table.style.display = '';
+
+      this.pick_color();
+
+      // Find position of the element
+      this.table.style.position = 'absolute';
+      var e = element;
+      var top  = 0;
+      var left = 0;
+      do
+      {
+        top += e.offsetTop;
+        left += e.offsetLeft;
+        e = e.offsetParent;
+      }
+      while(e)
+
+      var x, y;
+      if(/top/.test(anchorage))
+      {
+        this.table.style.top = (top - this.table.offsetHeight) + 'px';
+      }
+      else
+      {
+        this.table.style.top = (top + element.offsetHeight) + 'px';
+      }
+
+      if(/left/.test(anchorage))
+      {
+        this.table.style.left = left + 'px';
+      }
+      else
+      {
+        this.table.style.left = (left - (this.table.offsetWidth - element.offsetWidth)) + 'px';
+      }
+    }
+
+    /** Draw the color picker. */
+    this.pick_color = function()
+    {
+      var rows, cols;
+      var picker = this;
+      var huestep = 359/this.side;
+      var saturstep = 1/this.side;
+      var valustep  = 1/this.side;
+      var constrain = this.constrain_cb.checked;
+
+      if(this.saved_cells == null)
+      {
+        this.saved_cells = new Array();
+
+        for(var row = 0; row <= this.side; row++)
+        {
+          var tr = document.createElement('tr');
+          this.saved_cells[row] = new Array();
+          for(var col = 0; col <= this.side; col++)
+          {
+            var td = document.createElement('td');
+            if(constrain)
+            {
+              td.colorCode = tupleToColor(rgbToWebsafe(hsvToRGB(huestep*row, saturstep*col, this.value)));
+            }
+            else
+            {
+              td.colorCode = tupleToColor(hsvToRGB(huestep*row, saturstep*col, this.value));
+            }
+            this.saved_cells[row][col] = td;
+            td.style.height = td.style.width = this.cellsize;
+            td.style.backgroundColor = td.colorCode;
+            td.hue = huestep * row;
+            td.saturation = saturstep*col;
+            td.onmouseover = function()
+            {
+              picker.chosenColor.value = this.colorCode;
+              picker.backSample.style.backgroundColor = this.colorCode;
+              picker.foreSample.style.color = this.colorCode;
+              if((this.hue >= 195  && this.saturation > 0.25) || picker.value < 0.75)
+              {
+                picker.backSample.style.color = 'white';
+              }
+              else
+              {
+                picker.backSample.style.color = 'black';
+              }
+            }
+            td.onclick = function() { picker.callback(this.colorCode); picker.close(); }
+            td.appendChild(document.createTextNode(' '));
+            td.style.cursor = 'pointer';
+            tr.appendChild(td);
+            td = null;
+          }
+
+          // Add a blank and thena value column
+          var td = document.createElement('td');
+          td.appendChild(document.createTextNode(' '));
+          td.style.width = this.cellsize;
+          tr.appendChild(td);
+          td = null;
+
+          var td = document.createElement('td');
+          td.appendChild(document.createTextNode(' '));
+          td.style.width  = this.cellsize;
+          td.style.height = this.cellsize;
+          td.constrainedColorCode  = tupleToColor(rgbToWebsafe(hsvToRGB(0,0,valustep*row)));
+          td.style.backgroundColor = td.colorCode = tupleToColor(hsvToRGB(0,0,valustep*row));
+          td.hue = huestep * row;
+          td.saturation = saturstep*col;
+          td.hsv_value = valustep*row;
+          td.onclick = function() {
+            picker.value = this.hsv_value; picker.pick_color();
+            if(picker.constrain_cb.checked)
+            {
+              picker.chosenColor.value = this.constrainedColorCode;
+            }
+            else
+            {
+              picker.chosenColor.value = this.colorCode;
+            }
+          }
+          td.style.cursor = 'pointer';
+          tr.appendChild(td);
+          td = null;
+
+          this.tbody.appendChild(tr);
+          tr = null;
+        }
+
+        // Add one row of greys
+        var tr = document.createElement('tr');
+        this.saved_cells[row] = new Array();
+        for(var col = 0; col <= this.side; col++)
+        {
+          var td = document.createElement('td');
+          if(constrain)
+          {
+            td.colorCode = tupleToColor(rgbToWebsafe(hsvToRGB(0, 0, valustep*(this.side-col))));
+          }
+          else
+          {
+            td.colorCode = tupleToColor(hsvToRGB(0, 0, valustep*(this.side-col)));
+          }
+          this.saved_cells[row][col] = td;
+          td.style.height = td.style.width = this.cellsize;
+          td.style.backgroundColor = td.colorCode;
+          td.hue = 0;
+          td.saturation = 0;
+          td.onmouseover = function()
+          {
+            picker.chosenColor.value = this.colorCode;
+            picker.backSample.style.backgroundColor = this.colorCode;
+            picker.foreSample.style.color = this.colorCode;
+            if((this.hue >= 195  && this.saturation > 0.25) || picker.value < 0.75)
+            {
+              picker.backSample.style.color = 'white';
+            }
+            else
+            {
+              picker.backSample.style.color = 'black';
+            }
+          }
+          td.onclick = function() { picker.callback(this.colorCode); picker.close(); }
+          td.appendChild(document.createTextNode(' '));
+          td.style.cursor = 'pointer';
+          tr.appendChild(td);
+          td = null;
+        }
+        this.tbody.appendChild(tr);
+        tr = null;
+
+
+        var tr = document.createElement('tr');
+        var td = document.createElement('td');
+        tr.appendChild(td);
+        td.colSpan = this.side + 3;
+        td.style.padding = '3px';
+
+        var div = document.createElement('div');
+        var label = document.createElement('label');
+        label.appendChild(document.createTextNode('Web Safe: '));
+
+        this.constrain_cb.onclick = function() { picker.pick_color() };
+        label.appendChild(this.constrain_cb);
+        label.style.fontFamily = 'small-caption,caption,sans-serif';
+        label.style.fontSize = 'x-small';
+        div.appendChild(label);
+        td.appendChild(div);
+
+        var div = document.createElement('div');
+        var label = document.createElement('label');
+        label.style.fontFamily = 'small-caption,caption,sans-serif';
+        label.style.fontSize = 'x-small';
+        label.appendChild(document.createTextNode('Color: '));
+        label.appendChild(this.chosenColor);
+        div.appendChild(label);
+        td.appendChild(div);
+
+        var sampleTable = document.createElement('table');
+        sampleTable.style.width = '100%';
+        var sampleBody = document.createElement('tbody');
+        sampleTable.appendChild(sampleBody);
+        var sampleRow = document.createElement('tr');
+        sampleBody.appendChild(sampleRow);
+        var leftSampleCell = document.createElement('td');
+        sampleRow.appendChild(leftSampleCell);
+        leftSampleCell.appendChild(this.backSample);
+        leftSampleCell.style.width = '50%';
+        var rightSampleCell = document.createElement('td');
+        sampleRow.appendChild(rightSampleCell);
+        rightSampleCell.appendChild(this.foreSample);
+        rightSampleCell.style.width = '50%';
+
+        td.appendChild(sampleTable);
+
+
+        this.tbody.appendChild(tr);
+        document.body.appendChild(this.table);
+
+      }
+      else
+      {
+        for(var row = 0; row <= this.side; row++)
+        {
+          for(var col = 0; col <= this.side; col++)
+          {
+            if(constrain)
+            {
+              this.saved_cells[row][col].colorCode = tupleToColor(rgbToWebsafe(hsvToRGB(huestep*row, saturstep*col, this.value)));
+            }
+            else
+            {
+              this.saved_cells[row][col].colorCode = tupleToColor(hsvToRGB(huestep*row, saturstep*col, this.value));
+            }
+            this.saved_cells[row][col].style.backgroundColor = this.saved_cells[row][col].colorCode;
+          }
+        }
+      }
+    }
+
+    /** Close the color picker */
+    this.close = function()
+    {
+      this.table.style.display = 'none';
+    }
+
+  }

Added: plog/trunk/js/xinha/popups/custom2.html
===================================================================
--- plog/trunk/js/xinha/popups/custom2.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/custom2.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,35 @@
+<html style="width:300px; Height: 60px;">
+ <head>
+  <title>Select Phrase</title>
+<script language="javascript">
+
+var myTitle = window.dialogArguments;
+document.title = myTitle;
+
+
+function returnSelected() {
+  var idx  = document.all.textPulldown.selectedIndex;
+  var text = document.all.textPulldown[idx].text;
+
+  window.returnValue = text;          // set return value
+  window.close();                     // close dialog
+}
+
+</script>
+</head>
+<body bgcolor="#FFFFFF" topmargin=15 leftmargin=0>
+
+<form method=get onSubmit="Set(document.all.ColorHex.value); return false;">
+<div align=center>
+
+<select name="textPulldown">
+<option>The quick brown</option>
+<option>fox jumps over</option>
+<option>the lazy dog.</option>
+</select>
+
+<input type="button" value=" Go " onClick="returnSelected()">
+
+</div>
+</form>
+</body></html>
\ No newline at end of file

Added: plog/trunk/js/xinha/popups/editor_help.html
===================================================================
--- plog/trunk/js/xinha/popups/editor_help.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/editor_help.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,16 @@
+<html>
+ <head>
+  <title>Editor Help</title>
+  <style>
+    body, td, p, div { font-family: arial; font-size: x-small; }
+  </style>
+ </head>
+<body>
+
+<h2>Editor Help<hr></h2>
+
+Todo...
+
+
+</body>
+</html>
\ No newline at end of file

Added: plog/trunk/js/xinha/popups/insert_image.html
===================================================================
--- plog/trunk/js/xinha/popups/insert_image.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/insert_image.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,172 @@
+<html>
+
+<head>
+  <title>Insert Image</title>
+
+<script type="text/javascript" src="popup.js"></script>
+<link rel="stylesheet" type="text/css" href="popup.css" />
+
+<script type="text/javascript">
+
+window.resizeTo(400, 100);
+
+HTMLArea = window.opener.HTMLArea;
+function i18n(str) {
+  return (HTMLArea._lc(str, 'HTMLArea'));
+};
+
+function Init() {
+  __dlg_translate('HTMLArea');
+  __dlg_init();
+  // Make sure the translated string appears in the drop down. (for gecko)
+  document.getElementById("f_align").selectedIndex = 1;
+  document.getElementById("f_align").selectedIndex = 5;
+  var param = window.dialogArguments;
+  if (param) {
+      document.getElementById("f_url").value = param["f_url"];
+      document.getElementById("f_alt").value = param["f_alt"];
+      document.getElementById("f_border").value = param["f_border"];
+      document.getElementById("f_align").value = param["f_align"];
+      document.getElementById("f_vert").value = param["f_vert"];
+      document.getElementById("f_horiz").value = param["f_horiz"];
+      window.ipreview.location.replace(param.f_url);
+  }
+  document.getElementById("f_url").focus();
+};
+
+function onOK() {
+  var required = {
+    "f_url": i18n("You must enter the URL")
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  // pass data back to the calling window
+  var fields = ["f_url", "f_alt", "f_align", "f_border",
+                "f_horiz", "f_vert"];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+function onPreview() {
+  var f_url = document.getElementById("f_url");
+  var url = f_url.value;
+  if (!url) {
+    alert(i18n("You must enter the URL"));
+    f_url.focus();
+    return false;
+  }
+  window.ipreview.location.replace(url);
+  return false;
+};
+</script>
+
+</head>
+
+<body class="dialog" onload="Init()">
+
+<div class="title">Insert Image</div>
+<!--- new stuff --->
+<form action="" method="get">
+<table border="0" width="100%" style="padding: 0px; margin: 0px">
+  <tbody>
+
+  <tr>
+    <td style="width: 7em; text-align: right">Image URL:</td>
+    <td><input type="text" name="url" id="f_url" style="width:75%"
+      title="Enter the image URL here" />
+      <button name="preview" onclick="return onPreview();"
+      title="Preview the image in a new window">Preview</button>
+    </td>
+  </tr>
+  <tr>
+    <td style="width: 7em; text-align: right">Alternate text:</td>
+    <td><input type="text" name="alt" id="f_alt" style="width:100%"
+      title="For browsers that don't support images" /></td>
+  </tr>
+
+  </tbody>
+</table>
+
+<p />
+
+<fieldset style="float: left; margin-left: 5px;">
+<legend>Layout</legend>
+
+<div class="space"></div>
+
+<div class="fl">Alignment:</div>
+<select size="1" name="align" id="f_align"
+  title="Positioning of this image">
+  <option value=""                             >Not set</option>
+  <option value="left"                         >Left</option>
+  <option value="right"                        >Right</option>
+  <option value="texttop"                      >Texttop</option>
+  <option value="absmiddle"                    >Absmiddle</option>
+  <option value="baseline" selected="1"        >Baseline</option>
+  <option value="absbottom"                    >Absbottom</option>
+  <option value="bottom"                       >Bottom</option>
+  <option value="middle"                       >Middle</option>
+  <option value="top"                          >Top</option>
+</select>
+
+<p />
+
+<div class="fl">Border thickness:</div>
+<input type="text" name="border" id="f_border" size="5"
+title="Leave empty for no border" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<fieldset style="float:right; margin-right: 5px;">
+<legend>Spacing</legend>
+
+<div class="space"></div>
+
+<div class="fr">Horizontal:</div>
+<input type="text" name="horiz" id="f_horiz" size="5"
+title="Horizontal padding" />
+
+<p />
+
+<div class="fr">Vertical:</div>
+<input type="text" name="vert" id="f_vert" size="5"
+title="Vertical padding" />
+
+<div class="space"></div>
+
+</fieldset>
+<br clear="all" />
+<table width="100%" style="margin-bottom: 0.2em">
+ <tr>
+  <td valign="bottom">
+    <div class="fr">Image Preview:</div>
+    <iframe name="ipreview" id="ipreview" frameborder="0" style="border : 1px solid gray;" height="200" width="300" src=""></iframe>
+  </td>
+  <td valign="bottom" style="text-align: right">
+    <button type="button" name="ok" onclick="return onOK();">OK</button><br>
+    <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+  </td>
+ </tr>
+</table>
+</form>
+</body>
+</html>
\ No newline at end of file

Added: plog/trunk/js/xinha/popups/insert_table.html
===================================================================
--- plog/trunk/js/xinha/popups/insert_table.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/insert_table.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,157 @@
+<html>
+
+<head>
+  <title>Insert Table</title>
+
+<script type="text/javascript" src="popup.js"></script>
+<link rel="stylesheet" type="text/css" href="popup.css" />
+
+<script type="text/javascript">
+
+window.resizeTo(400, 100);
+
+HTMLArea = window.opener.HTMLArea;
+function i18n(str) {
+  return (HTMLArea._lc(str, 'HTMLArea'));
+};
+
+function Init() {
+  HTMLArea = window.opener.HTMLArea; // load the HTMLArea plugin and lang file
+  __dlg_translate('HTMLArea');
+  __dlg_init();
+  // Make sure the translated string appears in the drop down. (for gecko)
+  document.getElementById("f_unit").selectedIndex = 1;
+  document.getElementById("f_unit").selectedIndex = 0;
+  document.getElementById("f_align").selectedIndex = 1;
+  document.getElementById("f_align").selectedIndex = 0;
+  document.getElementById("f_rows").focus();
+};
+
+function onOK() {
+  var required = {
+    "f_rows": i18n("You must enter a number of rows"),
+    "f_cols": i18n("You must enter a number of columns")
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  var fields = ["f_rows", "f_cols", "f_width", "f_unit", "f_fixed",
+                "f_align", "f_border", "f_spacing", "f_padding"];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = (el.type == "checkbox") ? el.checked : el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+</head>
+
+<body class="dialog" onload="Init()">
+
+<div class="title">Insert Table</div>
+
+<form action="" method="get">
+<table border="0" style="padding: 0px; margin: 0px">
+  <tbody>
+
+  <tr>
+    <td style="width: 4em; text-align: right">Rows:</td>
+    <td><input type="text" name="rows" id="f_rows" size="5" title="Number of rows" value="2" /></td>
+    <td style="width: 4em; text-align: right">Width:</td>
+    <td><input type="text" name="width" id="f_width" size="5" title="Width of the table" value="100" /></td>
+    <td><select size="1" name="unit" id="f_unit" title="Width unit">
+      <option value="%" selected="1"  >Percent</option>
+      <option value="px"              >Pixels</option>
+      <option value="em"              >Em</option>
+    </select></td>
+  </tr>
+  <tr>
+    <td style="width: 4em; text-align: right">Cols:</td>
+    <td><input type="text" name="cols" id="f_cols" size="5" title="Number of columns" value="4" /></td>
+    <td style="text-align: right"><input type="checkbox" checked="checked" name="fixed" id="f_fixed" /></td>
+    <td colspan="2"><label for="f_fixed"
+    >Fixed width columns</label></td>
+  </tr>
+  </tbody>
+</table>
+
+<p />
+
+<fieldset style="float: left; margin-left: 5px;">
+<legend>Layout</legend>
+
+<div class="space"></div>
+
+<div class="fl">Alignment:</div>
+<select size="1" name="align" id="f_align"
+  title="Positioning of this table">
+  <option value="" selected="1"                >Not set</option>
+  <option value="left"                         >Left</option>
+  <option value="right"                        >Right</option>
+  <option value="texttop"                      >Texttop</option>
+  <option value="absmiddle"                    >Absmiddle</option>
+  <option value="baseline"                     >Baseline</option>
+  <option value="absbottom"                    >Absbottom</option>
+  <option value="bottom"                       >Bottom</option>
+  <option value="middle"                       >Middle</option>
+  <option value="top"                          >Top</option>
+</select>
+
+<p />
+
+<div class="fl">Border thickness:</div>
+<input type="text" name="border" id="f_border" size="5" value="1"
+title="Leave empty for no border" />
+<!--
+<p />
+
+<div class="fl">Collapse borders:</div>
+<input type="checkbox" name="collapse" id="f_collapse" />
+-->
+<div class="space"></div>
+
+</fieldset>
+
+<fieldset style="float:right; margin-right: 5px;">
+<legend>Spacing</legend>
+
+<div class="space"></div>
+
+<div class="fr">Cell spacing:</div>
+<input type="text" name="spacing" id="f_spacing" size="5" value="1"
+title="Space between adjacent cells" />
+
+<p />
+
+<div class="fr">Cell padding:</div>
+<input type="text" name="padding" id="f_padding" size="5" value="1"
+title="Space between content and border in cell" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<div style="margin-top: 85px; border-top: 1px solid #999; padding: 2px; text-align: right;">
+<button type="button" name="ok" onclick="return onOK();">OK</button>
+<button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+
+</form>
+
+</body>
+</html>
\ No newline at end of file

Added: plog/trunk/js/xinha/popups/link.html
===================================================================
--- plog/trunk/js/xinha/popups/link.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/link.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,136 @@
+<html>
+
+<head>
+  <title>Insert/Modify Link</title>
+  <script type="text/javascript" src="popup.js"></script>
+  <link rel="stylesheet" type="text/css" href="popup.css" />
+
+  <script type="text/javascript">
+    window.resizeTo(400, 200);
+
+HTMLArea = window.opener.HTMLArea;
+
+function i18n(str) {
+  return (HTMLArea._lc(str, 'HTMLArea'));
+};
+
+function onTargetChanged() {
+  var f = document.getElementById("f_other_target");
+  if (this.value == "_other") {
+    f.style.visibility = "visible";
+    f.select();
+    f.focus();
+  } else f.style.visibility = "hidden";
+};
+
+function Init() {
+  __dlg_translate('HTMLArea');
+  __dlg_init();
+
+  // Make sure the translated string appears in the drop down. (for gecko)
+  document.getElementById("f_target").selectedIndex = 1;
+  document.getElementById("f_target").selectedIndex = 0;
+
+  var param = window.dialogArguments;
+  var target_select = document.getElementById("f_target");
+  var use_target = true;
+  if (param) {
+    if ( typeof param["f_usetarget"] != "undefined" ) {
+      use_target = param["f_usetarget"];
+    }
+    if ( typeof param["f_href"] != "undefined" ) {
+      document.getElementById("f_href").value = param["f_href"];
+      document.getElementById("f_title").value = param["f_title"];
+      comboSelectValue(target_select, param["f_target"]);
+      if (target_select.value != param.f_target) {
+        var opt = document.createElement("option");
+        opt.value = param.f_target;
+        opt.innerHTML = opt.value;
+        target_select.appendChild(opt);
+        opt.selected = true;
+      }
+    }
+  }
+  if (! use_target) {
+    document.getElementById("f_target_label").style.visibility = "hidden";
+    document.getElementById("f_target").style.visibility = "hidden";
+    document.getElementById("f_target_other").style.visibility = "hidden";
+  }
+  var opt = document.createElement("option");
+  opt.value = "_other";
+  opt.innerHTML = i18n("Other");
+  target_select.appendChild(opt);
+  target_select.onchange = onTargetChanged;
+  document.getElementById("f_href").focus();
+  document.getElementById("f_href").select();
+};
+
+function onOK() {
+  var required = {
+    // f_href shouldn't be required or otherwise removing the link by entering an empty
+    // url isn't possible anymore.
+    // "f_href": i18n("You must enter the URL where this link points to")
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  // pass data back to the calling window
+  var fields = ["f_href", "f_title", "f_target" ];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  if (param.f_target == "_other")
+    param.f_target = document.getElementById("f_other_target").value;
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+</head>
+
+<body class="dialog" onload="Init()">
+<div class="title">Insert/Modify Link</div>
+<form>
+<table border="0" style="width: 100%;">
+  <tr>
+    <td class="label">URL:</td>
+    <td><input type="text" id="f_href" style="width: 100%" /></td>
+  </tr>
+  <tr>
+    <td class="label">Title (tooltip):</td>
+    <td><input type="text" id="f_title" style="width: 100%" /></td>
+  </tr>
+  <tr>
+    <td class="label"><span id="f_target_label">Target:</span></td>
+    <td><select id="f_target">
+      <option value="">None (use implicit)</option>
+      <option value="_blank">New window (_blank)</option>
+      <option value="_self">Same frame (_self)</option>
+      <option value="_top">Top frame (_top)</option>
+    </select>
+    <input type="text" name="f_other_target" id="f_other_target" size="10" style="visibility: hidden" />
+    </td>
+  </tr>
+</table>
+
+<div id="buttons">
+  <button type="submit" name="ok" onclick="return onOK();">OK</button>
+  <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+</form>
+</body>
+</html>

Added: plog/trunk/js/xinha/popups/old_insert_image.html
===================================================================
--- plog/trunk/js/xinha/popups/old_insert_image.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/old_insert_image.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,206 @@
+<!-- based on insimage.dlg -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML 3.2//EN">
+<HTML  id=dlgImage STYLE="width: 432px; height: 194px; ">
+<HEAD>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="MSThemeCompatible" content="Yes">
+<TITLE>Insert Image</TITLE>
+<style>
+  html, body, button, div, input, select, fieldset { font-family: MS Shell Dlg; font-size: 8pt; position: absolute; };
+</style>
+<SCRIPT defer>
+
+function _CloseOnEsc() {
+  if (event.keyCode == 27) { window.close(); return; }
+}
+
+function _getTextRange(elm) {
+  var r = elm.parentTextEdit.createTextRange();
+  r.moveToElementText(elm);
+  return r;
+}
+
+window.onerror = HandleError
+
+function HandleError(message, url, line) {
+  var str = "An error has occurred in this dialog." + "\n\n"
+  + "Error: " + line + "\n" + message;
+  alert(str);
+  window.close();
+  return true;
+}
+
+function Init() {
+  var elmSelectedImage;
+  var htmlSelectionControl = "Control";
+  var globalDoc = window.dialogArguments;
+  var grngMaster = globalDoc.selection.createRange();
+  
+  // event handlers  
+  document.body.onkeypress = _CloseOnEsc;
+  btnOK.onclick = new Function("btnOKClick()");
+
+  txtFileName.fImageLoaded = false;
+  txtFileName.intImageWidth = 0;
+  txtFileName.intImageHeight = 0;
+
+  if (globalDoc.selection.type == htmlSelectionControl) {
+    if (grngMaster.length == 1) {
+      elmSelectedImage = grngMaster.item(0);
+      if (elmSelectedImage.tagName == "IMG") {
+        txtFileName.fImageLoaded = true;
+        if (elmSelectedImage.src) {
+          txtFileName.value          = elmSelectedImage.src.replace(/^[^*]*(\*\*\*)/, "$1");  // fix placeholder src values that editor converted to abs paths
+          txtFileName.intImageHeight = elmSelectedImage.height;
+          txtFileName.intImageWidth  = elmSelectedImage.width;
+          txtVertical.value          = elmSelectedImage.vspace;
+          txtHorizontal.value        = elmSelectedImage.hspace;
+          txtBorder.value            = elmSelectedImage.border;
+          txtAltText.value           = elmSelectedImage.alt;
+          selAlignment.value         = elmSelectedImage.align;
+        }
+      }
+    }
+  }
+  txtFileName.value = txtFileName.value || "http://";
+  txtFileName.focus();
+}
+
+function _isValidNumber(txtBox) {
+  var val = parseInt(txtBox);
+  if (isNaN(val) || val < 0 || val > 999) { return false; }
+  return true;
+}
+
+function btnOKClick() {
+  var elmImage;
+  var intAlignment;
+  var htmlSelectionControl = "Control";
+  var globalDoc = window.dialogArguments;
+  var grngMaster = globalDoc.selection.createRange();
+  
+  // error checking
+
+  if (!txtFileName.value || txtFileName.value == "http://") { 
+    alert("Image URL must be specified.");
+    txtFileName.focus();
+    return;
+  }
+  if (txtHorizontal.value && !_isValidNumber(txtHorizontal.value)) {
+    alert("Horizontal spacing must be a number between 0 and 999.");
+    txtHorizontal.focus();
+    return;
+  }
+  if (txtBorder.value && !_isValidNumber(txtBorder.value)) {
+    alert("Border thickness must be a number between 0 and 999.");
+    txtBorder.focus();
+    return;
+  }
+  if (txtVertical.value && !_isValidNumber(txtVertical.value)) {
+    alert("Vertical spacing must be a number between 0 and 999.");
+    txtVertical.focus();
+    return;
+  }
+
+  // delete selected content and replace with image
+  if (globalDoc.selection.type == htmlSelectionControl && !txtFileName.fImageLoaded) {
+    grngMaster.execCommand('Delete');
+    grngMaster = globalDoc.selection.createRange();
+  }
+    
+  idstr = "\" id=\"556e697175657e537472696e67";     // new image creation ID
+  if (!txtFileName.fImageLoaded) {
+    grngMaster.execCommand("InsertImage", false, idstr);
+    elmImage = globalDoc.all['556e697175657e537472696e67'];
+    elmImage.removeAttribute("id");
+    elmImage.removeAttribute("src");
+    grngMaster.moveStart("character", -1);
+  } else {
+    elmImage = grngMaster.item(0);
+    if (elmImage.src != txtFileName.value) {
+      grngMaster.execCommand('Delete');
+      grngMaster = globalDoc.selection.createRange();
+      grngMaster.execCommand("InsertImage", false, idstr);
+      elmImage = globalDoc.all['556e697175657e537472696e67'];
+      elmImage.removeAttribute("id");
+      elmImage.removeAttribute("src");
+      grngMaster.moveStart("character", -1);
+      txtFileName.fImageLoaded = false;
+    }
+    grngMaster = _getTextRange(elmImage);
+  }
+
+  if (txtFileName.fImageLoaded) {
+    elmImage.style.width = txtFileName.intImageWidth;
+    elmImage.style.height = txtFileName.intImageHeight;
+  }
+
+  if (txtFileName.value.length > 2040) {
+    txtFileName.value = txtFileName.value.substring(0,2040);
+  }
+  
+  elmImage.src = txtFileName.value;
+  
+  if (txtHorizontal.value != "") { elmImage.hspace = parseInt(txtHorizontal.value); }
+  else                           { elmImage.hspace = 0; }
+
+  if (txtVertical.value != "") { elmImage.vspace = parseInt(txtVertical.value); }
+  else                         { elmImage.vspace = 0; }
+  
+  elmImage.alt = txtAltText.value;
+
+  if (txtBorder.value != "") { elmImage.border = parseInt(txtBorder.value); }
+  else                       { elmImage.border = 0; }
+
+  elmImage.align = selAlignment.value;
+  grngMaster.collapse(false);
+  grngMaster.select();
+  window.close();
+}
+</SCRIPT>
+</HEAD>
+<BODY id=bdy onload="Init()" style="background: threedface; color: windowtext;" scroll=no>
+
+<DIV id=divFileName style="left: 0.98em; top: 1.2168em; width: 7em; height: 1.2168em; ">Image URL:</DIV>
+<INPUT ID=txtFileName type=text style="left: 8.54em; top: 1.0647em; width: 21.5em;height: 2.1294em; " tabIndex=10 onfocus="select()">
+
+<DIV id=divAltText style="left: 0.98em; top: 4.1067em; width: 6.58em; height: 1.2168em; ">Alternate Text:</DIV>
+<INPUT type=text ID=txtAltText tabIndex=15 style="left: 8.54em; top: 3.8025em; width: 21.5em; height: 2.1294em; " onfocus="select()">
+
+<FIELDSET id=fldLayout style="left: .9em; top: 7.1em; width: 17.08em; height: 7.6em;">
+<LEGEND id=lgdLayout>Layout</LEGEND>
+</FIELDSET>
+
+<FIELDSET id=fldSpacing style="left: 18.9em; top: 7.1em; width: 11em; height: 7.6em;">
+<LEGEND id=lgdSpacing>Spacing</LEGEND>
+</FIELDSET>
+
+<DIV id=divAlign style="left: 1.82em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Alignment:</DIV>
+<SELECT size=1 ID=selAlignment tabIndex=20 style="left: 10.36em; top: 8.8218em; width: 6.72em; height: 1.2168em; ">
+<OPTION id=optNotSet value=""> Not set </OPTION>
+<OPTION id=optLeft value=left> Left </OPTION>
+<OPTION id=optRight value=right> Right </OPTION>
+<OPTION id=optTexttop value=textTop> Texttop </OPTION>
+<OPTION id=optAbsMiddle value=absMiddle> Absmiddle </OPTION>
+<OPTION id=optBaseline value=baseline SELECTED> Baseline </OPTION>
+<OPTION id=optAbsBottom value=absBottom> Absbottom </OPTION>
+<OPTION id=optBottom value=bottom> Bottom </OPTION>
+<OPTION id=optMiddle value=middle> Middle </OPTION>
+<OPTION id=optTop value=top> Top </OPTION>
+</SELECT>
+
+<DIV id=divHoriz style="left: 19.88em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Horizontal:</DIV>
+<INPUT ID=txtHorizontal style="left: 24.92em; top: 8.8218em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=25 onfocus="select()">
+
+<DIV id=divBorder style="left: 1.82em; top: 12.0159em; width: 8.12em; height: 1.2168em; ">Border Thickness:</DIV>
+<INPUT ID=txtBorder style="left: 10.36em; top: 11.5596em; width: 6.72em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=21 onfocus="select()">
+
+<DIV id=divVert style="left: 19.88em; top: 12.0159em; width: 3.64em; height: 1.2168em; ">Vertical:</DIV>
+<INPUT ID=txtVertical style="left: 24.92em; top: 11.5596em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=30 onfocus="select()">
+
+<BUTTON ID=btnOK style="left: 31.36em; top: 1.0647em; width: 7em; height: 2.2em; " type=submit tabIndex=40>OK</BUTTON>
+<BUTTON ID=btnCancel style="left: 31.36em; top: 3.6504em; width: 7em; height: 2.2em; " type=reset tabIndex=45 onClick="window.close();">Cancel</BUTTON>
+
+</BODY>
+</HTML>
\ No newline at end of file

Added: plog/trunk/js/xinha/popups/popup.css
===================================================================
--- plog/trunk/js/xinha/popups/popup.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/popup.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,32 @@
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+form { padding: 0px; margin: 0px; }
+form p {
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+table .label { text-align: right; width: 8em; }
+
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }
+.fr { width: 7em; float: left; padding: 2px 5px; text-align: right; }
+fieldset { padding: 0px 10px 5px 5px; }
+.space { padding: 2px; }
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+
+#buttons {
+      margin-top: 1em; border-top: 1px solid #999;
+      padding: 2px; text-align: right;
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/popups/popup.js
===================================================================
--- plog/trunk/js/xinha/popups/popup.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/popup.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,121 @@
+// htmlArea v3.0 - Copyright (c) 2002, 2003 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: popup.js 239 2005-06-23 07:01:59Z gocher $
+HTMLArea = window.opener.HTMLArea;
+
+function getAbsolutePos(el) {
+	var r = { x: el.offsetLeft, y: el.offsetTop };
+	if (el.offsetParent) {
+		var tmp = getAbsolutePos(el.offsetParent);
+		r.x += tmp.x;
+		r.y += tmp.y;
+	}
+	return r;
+};
+
+function comboSelectValue(c, val) {
+	var ops = c.getElementsByTagName("option");
+	for (var i = ops.length; --i >= 0;) {
+		var op = ops[i];
+		op.selected = (op.value == val);
+	}
+	c.value = val;
+};
+
+function __dlg_onclose() {
+	opener.Dialog._return(null);
+};
+
+function __dlg_init(bottom) {
+  if(window.opener._editor_skin != "") {
+    var head = document.getElementsByTagName("head")[0];
+    var link = document.createElement("link");
+    link.type = "text/css";
+    link.href = window.opener._editor_url + 'skins/' + window.opener._editor_skin + '/skin.css';
+    link.rel = "stylesheet";
+    head.appendChild(link);
+  }
+	var body = document.body;
+	var body_height = 0;
+	if (typeof bottom == "undefined") {
+		var div = document.createElement("div");
+		body.appendChild(div);
+		var pos = getAbsolutePos(div);
+		body_height = pos.y;
+	} else {
+		var pos = getAbsolutePos(bottom);
+		body_height = pos.y + bottom.offsetHeight;
+	}
+	window.dialogArguments = opener.Dialog._arguments;
+	if (!document.all) {
+		window.sizeToContent();
+		window.sizeToContent();	// for reasons beyond understanding,
+					// only if we call it twice we get the
+					// correct size.
+		window.addEventListener("unload", __dlg_onclose, true);
+		window.innerWidth = body.offsetWidth + 5;
+		window.innerHeight = body_height + 2;
+		// center on parent
+		var x = opener.screenX + (opener.outerWidth - window.outerWidth) / 2;
+		var y = opener.screenY + (opener.outerHeight - window.outerHeight) / 2;
+		window.moveTo(x, y);
+	} else {
+		// window.dialogHeight = body.offsetHeight + 50 + "px";
+		// window.dialogWidth = body.offsetWidth + "px";
+		window.resizeTo(body.offsetWidth, body_height);
+		var ch = body.clientHeight;
+		var cw = body.clientWidth;
+		window.resizeBy(body.offsetWidth - cw, body_height - ch);
+		var W = body.offsetWidth;
+		var H = 2 * body_height - ch;
+		var x = (screen.availWidth - W) / 2;
+		var y = (screen.availHeight - H) / 2;
+		window.moveTo(x, y);
+	}
+	HTMLArea.addDom0Event(document.body, 'keypress', __dlg_close_on_esc);
+};
+
+function __dlg_translate(context) {
+	var types = ["input", "select", "legend", "span", "option", "td", "button", "div", "label"];
+	for (var type = 0; type < types.length; ++type) {
+		var spans = document.getElementsByTagName(types[type]);
+		for (var i = spans.length; --i >= 0;) {
+			var span = spans[i];
+			if (span.firstChild && span.firstChild.data) {
+				var txt = HTMLArea._lc(span.firstChild.data, context);
+				if (txt)
+					span.firstChild.data = txt;
+			}
+                        if (span.title) {
+				var txt = HTMLArea._lc(span.title, context);
+				if (txt)
+					span.title = txt;
+                        }
+		}
+	}
+    document.title = HTMLArea._lc(document.title, context);
+};
+
+// closes the dialog and passes the return info upper.
+function __dlg_close(val) {
+	opener.Dialog._return(val);
+	window.close();
+};
+
+function __dlg_close_on_esc(ev) {
+	ev || (ev = window.event);
+	if (ev.keyCode == 27) {
+		window.close();
+		return false;
+	}
+	return true;
+};

Added: plog/trunk/js/xinha/popups/select_color.html
===================================================================
--- plog/trunk/js/xinha/popups/select_color.html	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popups/select_color.html	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,359 @@
+<!--<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">-->
+<html><head><title>Select Color</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<script type="text/javascript" src="popup.js"></script>
+<script type="text/javascript">
+window.resizeTo(240, 182);
+// run on page load
+function Init()
+{
+  __dlg_translate('HTMLArea');
+  __dlg_init();
+  HTMLArea.addDom0Event(document, 'keypress', __dlg_close_on_esc);
+
+  var color = window.dialogArguments;
+  color = ValidateColor(color) || '000000';
+  View(color);
+}
+// preview color
+function View(color)
+{
+  document.getElementById("ColorPreview").style.backgroundColor = '#' + color;
+  document.getElementById("ColorHex").value = '#' + color;
+}
+// select color
+function Set(string)
+{
+  var color = ValidateColor(string);
+  if (color == null)
+  {
+    alert("Invalid color code: " + string);
+  }
+  else
+  {
+    View(color);
+    __dlg_close(color);
+  }
+}
+// return valid color code
+function ValidateColor(string)
+{
+  string = string || '';
+  string = string + "";
+  string = string.toUpperCase();
+  var chars = '0123456789ABCDEF';
+  var out   = '';
+  // remove invalid color chars
+  for (var i=0; i<string.length; i++)
+  {
+    var schar = string.charAt(i);
+    if (chars.indexOf(schar) != -1) out += schar;
+  }
+  // check length
+  if (out.length != 6) return null;
+  return out;
+}
+</script>
+<style type="text/css">
+body { background:buttonface; margin:0; padding:0; }
+form { margin:0; padding:0; }
+#containerpreview td { background:buttonface; }
+#preview { background-color:#000000; padding:1px; height:21px; width:50px; }
+#ColorPreview { height:100%; width:100%; }
+#ColorHex { font-size:12px; background:buttonface; border:0; }
+#palettecolor { cursor:pointer; }
+#palettecolor td { width:10px; height:10px; }
+</style>
+</head>
+<body class="dialog" onload="Init()">
+
+<form action="#" method="get" onsubmit="Set(document.getElementById('ColorHex').value); return false;">
+<table border="0" cellspacing="0" cellpadding="4" width="100%" id="containerpreview">
+ <tr>
+  <td valign="middle"><div id="preview"><div id="ColorPreview"></div></div></td>
+  <td valign="middle" width="100%"><input type="text" name="ColorHex"
+    id="ColorHex" value="" size=15></td>
+ </tr>
+</table>
+</form>
+
+<table id="palettecolor" border="0" cellspacing="1" cellpadding="0" width="100%" bgcolor="#000000">
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#003300" onmouseover="View('003300')" onclick="Set('003300')"></td>
+<td bgcolor="#006600" onmouseover="View('006600')" onclick="Set('006600')"></td>
+<td bgcolor="#009900" onmouseover="View('009900')" onclick="Set('009900')"></td>
+<td bgcolor="#00CC00" onmouseover="View('00CC00')" onclick="Set('00CC00')"></td>
+<td bgcolor="#00FF00" onmouseover="View('00FF00')" onclick="Set('00FF00')"></td>
+<td bgcolor="#330000" onmouseover="View('330000')" onclick="Set('330000')"></td>
+<td bgcolor="#333300" onmouseover="View('333300')" onclick="Set('333300')"></td>
+<td bgcolor="#336600" onmouseover="View('336600')" onclick="Set('336600')"></td>
+<td bgcolor="#339900" onmouseover="View('339900')" onclick="Set('339900')"></td>
+<td bgcolor="#33CC00" onmouseover="View('33CC00')" onclick="Set('33CC00')"></td>
+<td bgcolor="#33FF00" onmouseover="View('33FF00')" onclick="Set('33FF00')"></td>
+<td bgcolor="#660000" onmouseover="View('660000')" onclick="Set('660000')"></td>
+<td bgcolor="#663300" onmouseover="View('663300')" onclick="Set('663300')"></td>
+<td bgcolor="#666600" onmouseover="View('666600')" onclick="Set('666600')"></td>
+<td bgcolor="#669900" onmouseover="View('669900')" onclick="Set('669900')"></td>
+<td bgcolor="#66CC00" onmouseover="View('66CC00')" onclick="Set('66CC00')"></td>
+<td bgcolor="#66FF00" onmouseover="View('66FF00')" onclick="Set('66FF00')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#333333" onmouseover="View('333333')" onclick="Set('333333')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#000033" onmouseover="View('000033')" onclick="Set('000033')"></td>
+<td bgcolor="#003333" onmouseover="View('003333')" onclick="Set('003333')"></td>
+<td bgcolor="#006633" onmouseover="View('006633')" onclick="Set('006633')"></td>
+<td bgcolor="#009933" onmouseover="View('009933')" onclick="Set('009933')"></td>
+<td bgcolor="#00CC33" onmouseover="View('00CC33')" onclick="Set('00CC33')"></td>
+<td bgcolor="#00FF33" onmouseover="View('00FF33')" onclick="Set('00FF33')"></td>
+<td bgcolor="#330033" onmouseover="View('330033')" onclick="Set('330033')"></td>
+<td bgcolor="#333333" onmouseover="View('333333')" onclick="Set('333333')"></td>
+<td bgcolor="#336633" onmouseover="View('336633')" onclick="Set('336633')"></td>
+<td bgcolor="#339933" onmouseover="View('339933')" onclick="Set('339933')"></td>
+<td bgcolor="#33CC33" onmouseover="View('33CC33')" onclick="Set('33CC33')"></td>
+<td bgcolor="#33FF33" onmouseover="View('33FF33')" onclick="Set('33FF33')"></td>
+<td bgcolor="#660033" onmouseover="View('660033')" onclick="Set('660033')"></td>
+<td bgcolor="#663333" onmouseover="View('663333')" onclick="Set('663333')"></td>
+<td bgcolor="#666633" onmouseover="View('666633')" onclick="Set('666633')"></td>
+<td bgcolor="#669933" onmouseover="View('669933')" onclick="Set('669933')"></td>
+<td bgcolor="#66CC33" onmouseover="View('66CC33')" onclick="Set('66CC33')"></td>
+<td bgcolor="#66FF33" onmouseover="View('66FF33')" onclick="Set('66FF33')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#666666" onmouseover="View('666666')" onclick="Set('666666')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#000066" onmouseover="View('000066')" onclick="Set('000066')"></td>
+<td bgcolor="#003366" onmouseover="View('003366')" onclick="Set('003366')"></td>
+<td bgcolor="#006666" onmouseover="View('006666')" onclick="Set('006666')"></td>
+<td bgcolor="#009966" onmouseover="View('009966')" onclick="Set('009966')"></td>
+<td bgcolor="#00CC66" onmouseover="View('00CC66')" onclick="Set('00CC66')"></td>
+<td bgcolor="#00FF66" onmouseover="View('00FF66')" onclick="Set('00FF66')"></td>
+<td bgcolor="#330066" onmouseover="View('330066')" onclick="Set('330066')"></td>
+<td bgcolor="#333366" onmouseover="View('333366')" onclick="Set('333366')"></td>
+<td bgcolor="#336666" onmouseover="View('336666')" onclick="Set('336666')"></td>
+<td bgcolor="#339966" onmouseover="View('339966')" onclick="Set('339966')"></td>
+<td bgcolor="#33CC66" onmouseover="View('33CC66')" onclick="Set('33CC66')"></td>
+<td bgcolor="#33FF66" onmouseover="View('33FF66')" onclick="Set('33FF66')"></td>
+<td bgcolor="#660066" onmouseover="View('660066')" onclick="Set('660066')"></td>
+<td bgcolor="#663366" onmouseover="View('663366')" onclick="Set('663366')"></td>
+<td bgcolor="#666666" onmouseover="View('666666')" onclick="Set('666666')"></td>
+<td bgcolor="#669966" onmouseover="View('669966')" onclick="Set('669966')"></td>
+<td bgcolor="#66CC66" onmouseover="View('66CC66')" onclick="Set('66CC66')"></td>
+<td bgcolor="#66FF66" onmouseover="View('66FF66')" onclick="Set('66FF66')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#999999" onmouseover="View('999999')" onclick="Set('999999')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#000099" onmouseover="View('000099')" onclick="Set('000099')"></td>
+<td bgcolor="#003399" onmouseover="View('003399')" onclick="Set('003399')"></td>
+<td bgcolor="#006699" onmouseover="View('006699')" onclick="Set('006699')"></td>
+<td bgcolor="#009999" onmouseover="View('009999')" onclick="Set('009999')"></td>
+<td bgcolor="#00CC99" onmouseover="View('00CC99')" onclick="Set('00CC99')"></td>
+<td bgcolor="#00FF99" onmouseover="View('00FF99')" onclick="Set('00FF99')"></td>
+<td bgcolor="#330099" onmouseover="View('330099')" onclick="Set('330099')"></td>
+<td bgcolor="#333399" onmouseover="View('333399')" onclick="Set('333399')"></td>
+<td bgcolor="#336699" onmouseover="View('336699')" onclick="Set('336699')"></td>
+<td bgcolor="#339999" onmouseover="View('339999')" onclick="Set('339999')"></td>
+<td bgcolor="#33CC99" onmouseover="View('33CC99')" onclick="Set('33CC99')"></td>
+<td bgcolor="#33FF99" onmouseover="View('33FF99')" onclick="Set('33FF99')"></td>
+<td bgcolor="#660099" onmouseover="View('660099')" onclick="Set('660099')"></td>
+<td bgcolor="#663399" onmouseover="View('663399')" onclick="Set('663399')"></td>
+<td bgcolor="#666699" onmouseover="View('666699')" onclick="Set('666699')"></td>
+<td bgcolor="#669999" onmouseover="View('669999')" onclick="Set('669999')"></td>
+<td bgcolor="#66CC99" onmouseover="View('66CC99')" onclick="Set('66CC99')"></td>
+<td bgcolor="#66FF99" onmouseover="View('66FF99')" onclick="Set('66FF99')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#CCCCCC" onmouseover="View('CCCCCC')" onclick="Set('CCCCCC')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#0000CC" onmouseover="View('0000CC')" onclick="Set('0000CC')"></td>
+<td bgcolor="#0033CC" onmouseover="View('0033CC')" onclick="Set('0033CC')"></td>
+<td bgcolor="#0066CC" onmouseover="View('0066CC')" onclick="Set('0066CC')"></td>
+<td bgcolor="#0099CC" onmouseover="View('0099CC')" onclick="Set('0099CC')"></td>
+<td bgcolor="#00CCCC" onmouseover="View('00CCCC')" onclick="Set('00CCCC')"></td>
+<td bgcolor="#00FFCC" onmouseover="View('00FFCC')" onclick="Set('00FFCC')"></td>
+<td bgcolor="#3300CC" onmouseover="View('3300CC')" onclick="Set('3300CC')"></td>
+<td bgcolor="#3333CC" onmouseover="View('3333CC')" onclick="Set('3333CC')"></td>
+<td bgcolor="#3366CC" onmouseover="View('3366CC')" onclick="Set('3366CC')"></td>
+<td bgcolor="#3399CC" onmouseover="View('3399CC')" onclick="Set('3399CC')"></td>
+<td bgcolor="#33CCCC" onmouseover="View('33CCCC')" onclick="Set('33CCCC')"></td>
+<td bgcolor="#33FFCC" onmouseover="View('33FFCC')" onclick="Set('33FFCC')"></td>
+<td bgcolor="#6600CC" onmouseover="View('6600CC')" onclick="Set('6600CC')"></td>
+<td bgcolor="#6633CC" onmouseover="View('6633CC')" onclick="Set('6633CC')"></td>
+<td bgcolor="#6666CC" onmouseover="View('6666CC')" onclick="Set('6666CC')"></td>
+<td bgcolor="#6699CC" onmouseover="View('6699CC')" onclick="Set('6699CC')"></td>
+<td bgcolor="#66CCCC" onmouseover="View('66CCCC')" onclick="Set('66CCCC')"></td>
+<td bgcolor="#66FFCC" onmouseover="View('66FFCC')" onclick="Set('66FFCC')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#FFFFFF" onmouseover="View('FFFFFF')" onclick="Set('FFFFFF')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#0000FF" onmouseover="View('0000FF')" onclick="Set('0000FF')"></td>
+<td bgcolor="#0033FF" onmouseover="View('0033FF')" onclick="Set('0033FF')"></td>
+<td bgcolor="#0066FF" onmouseover="View('0066FF')" onclick="Set('0066FF')"></td>
+<td bgcolor="#0099FF" onmouseover="View('0099FF')" onclick="Set('0099FF')"></td>
+<td bgcolor="#00CCFF" onmouseover="View('00CCFF')" onclick="Set('00CCFF')"></td>
+<td bgcolor="#00FFFF" onmouseover="View('00FFFF')" onclick="Set('00FFFF')"></td>
+<td bgcolor="#3300FF" onmouseover="View('3300FF')" onclick="Set('3300FF')"></td>
+<td bgcolor="#3333FF" onmouseover="View('3333FF')" onclick="Set('3333FF')"></td>
+<td bgcolor="#3366FF" onmouseover="View('3366FF')" onclick="Set('3366FF')"></td>
+<td bgcolor="#3399FF" onmouseover="View('3399FF')" onclick="Set('3399FF')"></td>
+<td bgcolor="#33CCFF" onmouseover="View('33CCFF')" onclick="Set('33CCFF')"></td>
+<td bgcolor="#33FFFF" onmouseover="View('33FFFF')" onclick="Set('33FFFF')"></td>
+<td bgcolor="#6600FF" onmouseover="View('6600FF')" onclick="Set('6600FF')"></td>
+<td bgcolor="#6633FF" onmouseover="View('6633FF')" onclick="Set('6633FF')"></td>
+<td bgcolor="#6666FF" onmouseover="View('6666FF')" onclick="Set('6666FF')"></td>
+<td bgcolor="#6699FF" onmouseover="View('6699FF')" onclick="Set('6699FF')"></td>
+<td bgcolor="#66CCFF" onmouseover="View('66CCFF')" onclick="Set('66CCFF')"></td>
+<td bgcolor="#66FFFF" onmouseover="View('66FFFF')" onclick="Set('66FFFF')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#FF0000" onmouseover="View('FF0000')" onclick="Set('FF0000')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#990000" onmouseover="View('990000')" onclick="Set('990000')"></td>
+<td bgcolor="#993300" onmouseover="View('993300')" onclick="Set('993300')"></td>
+<td bgcolor="#996600" onmouseover="View('996600')" onclick="Set('996600')"></td>
+<td bgcolor="#999900" onmouseover="View('999900')" onclick="Set('999900')"></td>
+<td bgcolor="#99CC00" onmouseover="View('99CC00')" onclick="Set('99CC00')"></td>
+<td bgcolor="#99FF00" onmouseover="View('99FF00')" onclick="Set('99FF00')"></td>
+<td bgcolor="#CC0000" onmouseover="View('CC0000')" onclick="Set('CC0000')"></td>
+<td bgcolor="#CC3300" onmouseover="View('CC3300')" onclick="Set('CC3300')"></td>
+<td bgcolor="#CC6600" onmouseover="View('CC6600')" onclick="Set('CC6600')"></td>
+<td bgcolor="#CC9900" onmouseover="View('CC9900')" onclick="Set('CC9900')"></td>
+<td bgcolor="#CCCC00" onmouseover="View('CCCC00')" onclick="Set('CCCC00')"></td>
+<td bgcolor="#CCFF00" onmouseover="View('CCFF00')" onclick="Set('CCFF00')"></td>
+<td bgcolor="#FF0000" onmouseover="View('FF0000')" onclick="Set('FF0000')"></td>
+<td bgcolor="#FF3300" onmouseover="View('FF3300')" onclick="Set('FF3300')"></td>
+<td bgcolor="#FF6600" onmouseover="View('FF6600')" onclick="Set('FF6600')"></td>
+<td bgcolor="#FF9900" onmouseover="View('FF9900')" onclick="Set('FF9900')"></td>
+<td bgcolor="#FFCC00" onmouseover="View('FFCC00')" onclick="Set('FFCC00')"></td>
+<td bgcolor="#FFFF00" onmouseover="View('FFFF00')" onclick="Set('FFFF00')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#00FF00" onmouseover="View('00FF00')" onclick="Set('00FF00')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#990033" onmouseover="View('990033')" onclick="Set('990033')"></td>
+<td bgcolor="#993333" onmouseover="View('993333')" onclick="Set('993333')"></td>
+<td bgcolor="#996633" onmouseover="View('996633')" onclick="Set('996633')"></td>
+<td bgcolor="#999933" onmouseover="View('999933')" onclick="Set('999933')"></td>
+<td bgcolor="#99CC33" onmouseover="View('99CC33')" onclick="Set('99CC33')"></td>
+<td bgcolor="#99FF33" onmouseover="View('99FF33')" onclick="Set('99FF33')"></td>
+<td bgcolor="#CC0033" onmouseover="View('CC0033')" onclick="Set('CC0033')"></td>
+<td bgcolor="#CC3333" onmouseover="View('CC3333')" onclick="Set('CC3333')"></td>
+<td bgcolor="#CC6633" onmouseover="View('CC6633')" onclick="Set('CC6633')"></td>
+<td bgcolor="#CC9933" onmouseover="View('CC9933')" onclick="Set('CC9933')"></td>
+<td bgcolor="#CCCC33" onmouseover="View('CCCC33')" onclick="Set('CCCC33')"></td>
+<td bgcolor="#CCFF33" onmouseover="View('CCFF33')" onclick="Set('CCFF33')"></td>
+<td bgcolor="#FF0033" onmouseover="View('FF0033')" onclick="Set('FF0033')"></td>
+<td bgcolor="#FF3333" onmouseover="View('FF3333')" onclick="Set('FF3333')"></td>
+<td bgcolor="#FF6633" onmouseover="View('FF6633')" onclick="Set('FF6633')"></td>
+<td bgcolor="#FF9933" onmouseover="View('FF9933')" onclick="Set('FF9933')"></td>
+<td bgcolor="#FFCC33" onmouseover="View('FFCC33')" onclick="Set('FFCC33')"></td>
+<td bgcolor="#FFFF33" onmouseover="View('FFFF33')" onclick="Set('FFFF33')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#0000FF" onmouseover="View('0000FF')" onclick="Set('0000FF')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#990066" onmouseover="View('990066')" onclick="Set('990066')"></td>
+<td bgcolor="#993366" onmouseover="View('993366')" onclick="Set('993366')"></td>
+<td bgcolor="#996666" onmouseover="View('996666')" onclick="Set('996666')"></td>
+<td bgcolor="#999966" onmouseover="View('999966')" onclick="Set('999966')"></td>
+<td bgcolor="#99CC66" onmouseover="View('99CC66')" onclick="Set('99CC66')"></td>
+<td bgcolor="#99FF66" onmouseover="View('99FF66')" onclick="Set('99FF66')"></td>
+<td bgcolor="#CC0066" onmouseover="View('CC0066')" onclick="Set('CC0066')"></td>
+<td bgcolor="#CC3366" onmouseover="View('CC3366')" onclick="Set('CC3366')"></td>
+<td bgcolor="#CC6666" onmouseover="View('CC6666')" onclick="Set('CC6666')"></td>
+<td bgcolor="#CC9966" onmouseover="View('CC9966')" onclick="Set('CC9966')"></td>
+<td bgcolor="#CCCC66" onmouseover="View('CCCC66')" onclick="Set('CCCC66')"></td>
+<td bgcolor="#CCFF66" onmouseover="View('CCFF66')" onclick="Set('CCFF66')"></td>
+<td bgcolor="#FF0066" onmouseover="View('FF0066')" onclick="Set('FF0066')"></td>
+<td bgcolor="#FF3366" onmouseover="View('FF3366')" onclick="Set('FF3366')"></td>
+<td bgcolor="#FF6666" onmouseover="View('FF6666')" onclick="Set('FF6666')"></td>
+<td bgcolor="#FF9966" onmouseover="View('FF9966')" onclick="Set('FF9966')"></td>
+<td bgcolor="#FFCC66" onmouseover="View('FFCC66')" onclick="Set('FFCC66')"></td>
+<td bgcolor="#FFFF66" onmouseover="View('FFFF66')" onclick="Set('FFFF66')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#FFFF00" onmouseover="View('FFFF00')" onclick="Set('FFFF00')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#990099" onmouseover="View('990099')" onclick="Set('990099')"></td>
+<td bgcolor="#993399" onmouseover="View('993399')" onclick="Set('993399')"></td>
+<td bgcolor="#996699" onmouseover="View('996699')" onclick="Set('996699')"></td>
+<td bgcolor="#999999" onmouseover="View('999999')" onclick="Set('999999')"></td>
+<td bgcolor="#99CC99" onmouseover="View('99CC99')" onclick="Set('99CC99')"></td>
+<td bgcolor="#99FF99" onmouseover="View('99FF99')" onclick="Set('99FF99')"></td>
+<td bgcolor="#CC0099" onmouseover="View('CC0099')" onclick="Set('CC0099')"></td>
+<td bgcolor="#CC3399" onmouseover="View('CC3399')" onclick="Set('CC3399')"></td>
+<td bgcolor="#CC6699" onmouseover="View('CC6699')" onclick="Set('CC6699')"></td>
+<td bgcolor="#CC9999" onmouseover="View('CC9999')" onclick="Set('CC9999')"></td>
+<td bgcolor="#CCCC99" onmouseover="View('CCCC99')" onclick="Set('CCCC99')"></td>
+<td bgcolor="#CCFF99" onmouseover="View('CCFF99')" onclick="Set('CCFF99')"></td>
+<td bgcolor="#FF0099" onmouseover="View('FF0099')" onclick="Set('FF0099')"></td>
+<td bgcolor="#FF3399" onmouseover="View('FF3399')" onclick="Set('FF3399')"></td>
+<td bgcolor="#FF6699" onmouseover="View('FF6699')" onclick="Set('FF6699')"></td>
+<td bgcolor="#FF9999" onmouseover="View('FF9999')" onclick="Set('FF9999')"></td>
+<td bgcolor="#FFCC99" onmouseover="View('FFCC99')" onclick="Set('FFCC99')"></td>
+<td bgcolor="#FFFF99" onmouseover="View('FFFF99')" onclick="Set('FFFF99')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#00FFFF" onmouseover="View('00FFFF')" onclick="Set('00FFFF')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#9900CC" onmouseover="View('9900CC')" onclick="Set('9900CC')"></td>
+<td bgcolor="#9933CC" onmouseover="View('9933CC')" onclick="Set('9933CC')"></td>
+<td bgcolor="#9966CC" onmouseover="View('9966CC')" onclick="Set('9966CC')"></td>
+<td bgcolor="#9999CC" onmouseover="View('9999CC')" onclick="Set('9999CC')"></td>
+<td bgcolor="#99CCCC" onmouseover="View('99CCCC')" onclick="Set('99CCCC')"></td>
+<td bgcolor="#99FFCC" onmouseover="View('99FFCC')" onclick="Set('99FFCC')"></td>
+<td bgcolor="#CC00CC" onmouseover="View('CC00CC')" onclick="Set('CC00CC')"></td>
+<td bgcolor="#CC33CC" onmouseover="View('CC33CC')" onclick="Set('CC33CC')"></td>
+<td bgcolor="#CC66CC" onmouseover="View('CC66CC')" onclick="Set('CC66CC')"></td>
+<td bgcolor="#CC99CC" onmouseover="View('CC99CC')" onclick="Set('CC99CC')"></td>
+<td bgcolor="#CCCCCC" onmouseover="View('CCCCCC')" onclick="Set('CCCCCC')"></td>
+<td bgcolor="#CCFFCC" onmouseover="View('CCFFCC')" onclick="Set('CCFFCC')"></td>
+<td bgcolor="#FF00CC" onmouseover="View('FF00CC')" onclick="Set('FF00CC')"></td>
+<td bgcolor="#FF33CC" onmouseover="View('FF33CC')" onclick="Set('FF33CC')"></td>
+<td bgcolor="#FF66CC" onmouseover="View('FF66CC')" onclick="Set('FF66CC')"></td>
+<td bgcolor="#FF99CC" onmouseover="View('FF99CC')" onclick="Set('FF99CC')"></td>
+<td bgcolor="#FFCCCC" onmouseover="View('FFCCCC')" onclick="Set('FFCCCC')"></td>
+<td bgcolor="#FFFFCC" onmouseover="View('FFFFCC')" onclick="Set('FFFFCC')"></td>
+</tr>
+<tr>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#FF00FF" onmouseover="View('FF00FF')" onclick="Set('FF00FF')"></td>
+<td bgcolor="#000000" onmouseover="View('000000')" onclick="Set('000000')"></td>
+<td bgcolor="#9900FF" onmouseover="View('9900FF')" onclick="Set('9900FF')"></td>
+<td bgcolor="#9933FF" onmouseover="View('9933FF')" onclick="Set('9933FF')"></td>
+<td bgcolor="#9966FF" onmouseover="View('9966FF')" onclick="Set('9966FF')"></td>
+<td bgcolor="#9999FF" onmouseover="View('9999FF')" onclick="Set('9999FF')"></td>
+<td bgcolor="#99CCFF" onmouseover="View('99CCFF')" onclick="Set('99CCFF')"></td>
+<td bgcolor="#99FFFF" onmouseover="View('99FFFF')" onclick="Set('99FFFF')"></td>
+<td bgcolor="#CC00FF" onmouseover="View('CC00FF')" onclick="Set('CC00FF')"></td>
+<td bgcolor="#CC33FF" onmouseover="View('CC33FF')" onclick="Set('CC33FF')"></td>
+<td bgcolor="#CC66FF" onmouseover="View('CC66FF')" onclick="Set('CC66FF')"></td>
+<td bgcolor="#CC99FF" onmouseover="View('CC99FF')" onclick="Set('CC99FF')"></td>
+<td bgcolor="#CCCCFF" onmouseover="View('CCCCFF')" onclick="Set('CCCCFF')"></td>
+<td bgcolor="#CCFFFF" onmouseover="View('CCFFFF')" onclick="Set('CCFFFF')"></td>
+<td bgcolor="#FF00FF" onmouseover="View('FF00FF')" onclick="Set('FF00FF')"></td>
+<td bgcolor="#FF33FF" onmouseover="View('FF33FF')" onclick="Set('FF33FF')"></td>
+<td bgcolor="#FF66FF" onmouseover="View('FF66FF')" onclick="Set('FF66FF')"></td>
+<td bgcolor="#FF99FF" onmouseover="View('FF99FF')" onclick="Set('FF99FF')"></td>
+<td bgcolor="#FFCCFF" onmouseover="View('FFCCFF')" onclick="Set('FFCCFF')"></td>
+<td bgcolor="#FFFFFF" onmouseover="View('FFFFFF')" onclick="Set('FFFFFF')"></td>
+</tr>
+</table>
+
+</body></html>
\ No newline at end of file

Added: plog/trunk/js/xinha/popupwin.js
===================================================================
--- plog/trunk/js/xinha/popupwin.js	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/popupwin.js	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,140 @@
+// (c) dynarch.com 2003-2004
+// Distributed under the same terms as HTMLArea itself.
+
+function PopupWin(editor, title, handler, initFunction) {
+	this.editor = editor;
+	this.handler = handler;
+	var dlg = window.open("", "__ha_dialog",
+			      "toolbar=no,menubar=no,personalbar=no,width=600,height=600,left=20,top=40" +
+			      "scrollbars=no,resizable=no");
+	this.window = dlg;
+	var doc = dlg.document;
+	this.doc = doc;
+	var self = this;
+
+	var base = document.baseURI || document.URL;
+	if (base && base.match(/(.*)\/([^\/]+)/)) {
+		base = RegExp.$1 + "/";
+	}
+	if (typeof _editor_url != "undefined" && !/^\//.test(_editor_url) && !/http:\/\//.test(_editor_url)) {
+		// _editor_url doesn't start with '/' which means it's relative
+		// FIXME: there's a problem here, it could be http:// which
+		// doesn't start with slash but it's not relative either.
+		base += _editor_url;
+	} else
+		base = _editor_url;
+	if (!/\/$/.test(base)) {
+		// base does not end in slash, add it now
+		base += '/';
+	}
+	this.baseURL = base;
+
+	doc.open();
+	var html = "<html><head><title>" + title + "</title>\n";
+	// html += "<base href='" + base + "htmlarea.js' />\n";
+	html += "<style type='text/css'>@import url(" + base + "htmlarea.css);</style></head>\n";
+	html += "<body class='dialog popupwin' id='--HA-body'></body></html>";
+	doc.write(html);
+	doc.close();
+
+	// sometimes I Hate Mozilla... ;-(
+	function init2() {
+		var body = doc.body;
+		if (!body) {
+			setTimeout(init2, 25);
+			return false;
+		}
+		dlg.title = title;
+		doc.documentElement.style.padding = "0px";
+		doc.documentElement.style.margin = "0px";
+		var content = doc.createElement("div");
+		content.className = "content";
+		self.content = content;
+		body.appendChild(content);
+		self.element = body;
+		initFunction(self);
+		dlg.focus();
+	};
+	init2();
+};
+
+PopupWin.prototype.callHandler = function() {
+	var tags = ["input", "textarea", "select"];
+	var params = new Object();
+	for (var ti = tags.length; --ti >= 0;) {
+		var tag = tags[ti];
+		var els = this.content.getElementsByTagName(tag);
+		for (var j = 0; j < els.length; ++j) {
+			var el = els[j];
+			var val = el.value;
+			if (el.tagName.toLowerCase() == "input") {
+				if (el.type == "checkbox") {
+					val = el.checked;
+				}
+			}
+			params[el.name] = val;
+		}
+	}
+	this.handler(this, params);
+	return false;
+};
+
+PopupWin.prototype.close = function() {
+	this.window.close();
+};
+
+PopupWin.prototype.addButtons = function() {
+	var self = this;
+	var div = this.doc.createElement("div");
+	this.content.appendChild(div);
+	div.className = "buttons";
+	for (var i = 0; i < arguments.length; ++i) {
+		var btn = arguments[i];
+		var button = this.doc.createElement("button");
+		div.appendChild(button);
+		button.innerHTML = HTMLArea._lc(btn, 'HTMLArea');
+		switch (btn.toLowerCase()) {
+		    case "ok":
+      HTMLArea.addDom0Event(button, 'click',
+			function() {
+				self.callHandler();
+				self.close();
+				return false;
+			});
+			break;
+		    case "cancel":
+			HTMLArea.addDom0Event(button, 'click',  function() {
+				self.close();
+				return false;
+			});
+			break;
+		}
+	}
+};
+
+PopupWin.prototype.showAtElement = function() {
+	var self = this;
+	// Mozilla needs some time to realize what's goin' on..
+	setTimeout(function() {
+		var w = self.content.offsetWidth + 4;
+		var h = self.content.offsetHeight + 4;
+		// size to content -- that's fuckin' buggy in all fuckin' browsers!!!
+		// so that we set a larger size for the dialog window and then center
+		// the element inside... phuck!
+
+		// center...
+		var el = self.content;
+		var s = el.style;
+		// s.width = el.offsetWidth + "px";
+		// s.height = el.offsetHeight + "px";
+		s.position = "absolute";
+		s.left = (w - el.offsetWidth) / 2 + "px";
+		s.top = (h - el.offsetHeight) / 2 + "px";
+		if (HTMLArea.is_gecko) {
+			self.window.innerWidth = w;
+			self.window.innerHeight = h;
+		} else {
+			self.window.resizeTo(w + 8, h + 35);
+		}
+	}, 25);
+};

Added: plog/trunk/js/xinha/skins/blue-look/button-background.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/blue-look/button-background.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/blue-look/separator.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/blue-look/separator.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/blue-look/skin.css
===================================================================
--- plog/trunk/js/xinha/skins/blue-look/skin.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/blue-look/skin.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,97 @@
+.htmlarea .toolbar, .htmlarea .toolbar .button
+{
+  background-color:#f7f8fd;
+}
+
+.htmlarea .toolbarRow
+{
+  margin-top:2px;
+  margin-bottom:2px;
+  border:1px dotted #DEDEDE;
+  padding:0px;
+  -moz-border-radius:3px;
+  margin:4px;
+}
+
+.htmlarea .toolbar .button
+{
+  background-image: url(button-background.png);
+  width:20px;
+  height:20px;
+  padding:0px;
+  border:1px solid #f7f8fd;
+}
+
+.buttonImageContainer
+{
+  position:relative;
+  left:1px;
+  top :1px;
+}
+
+.htmlarea .toolbar .separator {
+  margin:0px;
+  background-image: url(separator.gif);
+  border:1px #f7f8fd;
+  width:   7px;
+  height: 20px;
+  padding: 0px;
+}
+
+.htmlarea .toolbar a.button:hover
+{
+  border: 1px solid;
+  border-color: white #CCC #CCC white;
+}
+
+.htmlarea .toolbar a.buttonDisabled:hover
+{
+  border-color: #f7f8fd;
+}
+
+.htmlarea .toolbar .button.buttonActive,
+.htmlarea .toolbar .button.buttonPressed
+{
+  border: 1px solid;
+  border-color: #CCC white white #CCC;
+}
+
+.htmlarea .statusBar {
+  border-color: #CCC white white #CCC;
+  padding: 0px;
+  height:20px;
+  background-image: url(button-background.png);
+  background-repeat: repeat-x;
+  background-color: #f7f8fd;
+  color: ButtonText;
+  font: 11px helvetica,arial,sans-serif;
+}
+
+.htmlarea .statusBar .statusBarTree
+{
+  display:block;
+  margin: 3px;
+}
+
+.htmlarea .statusBar .statusBarTree a
+{
+  padding: 2px 5px;
+  color: #00f;
+  text-decoration:none;
+}
+
+.htmlarea .panel h1
+{
+  background-image: url('button-background.png');
+  background-repeat: repeat-x;
+  background-color: #f7f8fd;
+}
+.dialog {
+  background-color:#f7f8fd;
+}
+.dialog .title {
+  background-image: url(button-background.png);
+}  
+.dialog button{
+  background-image: url(button-background.png);
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/skins/blue-metallic/button-background.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/blue-metallic/button-background.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/blue-metallic/separator.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/blue-metallic/separator.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/blue-metallic/skin.css
===================================================================
--- plog/trunk/js/xinha/skins/blue-metallic/skin.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/blue-metallic/skin.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,106 @@
+.htmlarea .toolbar, .htmlarea .toolbar .button
+{
+  background-color:#f7f8fd;
+}
+
+.htmlarea .toolbarRow
+{
+  /*background-image: url(button-background.png);*/
+  background-color: #C5DCEC;
+  margin-top:2px;
+  margin-bottom:2px;
+  border:1px dotted #DEDEDE;
+  padding:0px;
+  -moz-border-radius:5px;
+  margin: 1px;
+  margin:4px;
+}
+
+.htmlarea .toolbar .button {
+  background-image: url(button-background.png);
+  width:20px;
+  height:20px;
+  padding:0px;
+  border:1px solid #f7f8fd;
+}
+
+.buttonImageContainer
+{
+  position:relative;
+  left:1px;
+  top :1px;
+}
+
+.htmlarea .toolbar .separator
+{
+  margin:0px;
+  background-image: url(separator.gif);
+  border:1px #f7f8fd;
+  width:   7px;
+  height: 20px;
+  padding: 0px;
+}
+
+.htmlarea .toolbar a.button:hover
+{
+  border: 1px solid;
+  border-color: #316AC5;
+  background-image: none !important;
+  background-color : #FFE1AC !important;
+}
+
+.htmlarea .toolbar a.buttonDisabled:hover
+{
+  border-color: #316AC5;
+  background-color : #FFE1AC;
+}
+
+.htmlarea .toolbar .button.buttonActive,
+.htmlarea .toolbar .button.buttonPressed
+{
+  border: 1px solid;
+  border-color: #79A4CC #FFFFFF #FFFFFF #79A4CC;
+  background-image: none !important;
+  background-color : #FFBE6D !important;
+}
+
+.htmlarea .statusBar {
+  border-color: #CCC white white #CCC;
+  padding: 0px;
+  height:20px;
+  background-image: url(button-background.png);
+  background-repeat: repeat-x;
+  background-color: #f7f8fd;
+  color: ButtonText;
+  font: 11px helvetica,arial,sans-serif;
+}
+
+.htmlarea .statusBar .statusBarTree
+{
+  display:block;
+  margin: 3px;
+}
+
+.htmlarea .statusBar .statusBarTree a
+{
+  padding: 2px 5px;
+  color: #00f;
+  text-decoration:none;
+}
+
+.htmlarea .panel h1
+{
+  background-image: url('button-background.png');
+  background-repeat: repeat-x;
+  background-color: #f7f8fd;
+}
+
+.dialog {
+  background-color:#f7f8fd;
+}
+.dialog .title {
+  background-image: url(button-background.png);
+}
+.dialog button{
+  background-image: url(button-background.png);
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/skins/green-look/button-background.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/green-look/button-background.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/green-look/button-background.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/green-look/button-background.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/green-look/separator.gif
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/green-look/separator.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/green-look/skin.css
===================================================================
--- plog/trunk/js/xinha/skins/green-look/skin.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/green-look/skin.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,87 @@
+.htmlarea .toolbar, .htmlarea .toolbar .button
+{
+  background-color:#f8fdf8;
+}
+.htmlarea .toolbarRow
+{
+  margin-top:2px;
+  margin-bottom:2px;
+  border:1px dotted #DEDEDE;
+  padding:0px;
+  -moz-border-radius:3px;
+  margin:4px;
+}
+.htmlarea .toolbar .button
+{
+  background-image:url(button-background.gif);
+  width:20px;
+  height:20px;
+  padding:0;
+  border:1px solid #f8fdf8;
+}
+.buttonImageContainer
+{
+  position:relative;
+  left:1px;
+  top:1px;
+}
+.htmlarea .toolbar .separator {
+  margin:0;
+  background-image:url(separator.gif);
+  border:1px #f8fdf8;
+  width:7px;
+  height:20px;
+  padding:0;
+}
+.htmlarea .toolbar a.button:hover
+{
+  border:1px solid;
+  border-color:#fff #ccc #ccc #fff;
+}
+.htmlarea .toolbar a.buttonDisabled:hover
+{
+  border-color:#f8fdf8;
+}
+.htmlarea .toolbar .buttonActive,
+.htmlarea .toolbar .buttonPressed
+{
+  border:1px solid;
+  border-color:#ccc #fff #fff #ccc;
+  background:#ffb166;
+}
+.htmlarea .statusBar {
+  border-color:#ccc #fff #fff #ccc;
+  padding:0;
+  height:20px;
+  background-image:url(button-background.gif);
+  background-repeat:repeat-x;
+  background-color:#f8fdf8;
+  color:ButtonText;
+  font:11px helvetica,arial,sans-serif;
+}
+.htmlarea .statusBar .statusBarTree
+{
+  display:block;
+  margin:3px;
+}
+.htmlarea .statusBar .statusBarTree a
+{
+  padding:2px 5px;
+  color:#00f;
+  text-decoration:none;
+}
+.htmlarea .panel h1
+{
+  background-image:url(button-background.gif);
+  background-repeat:repeat-x;
+  background-color:#f8fdf8;
+}
+.dialog {
+  background-color:#f8fdf8;
+}
+.dialog .title {
+  background-image: url(button-background.png);
+}  
+.dialog button{
+  background-image: url(button-background.png);
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/skins/inditreuse/README
===================================================================
--- plog/trunk/js/xinha/skins/inditreuse/README	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/inditreuse/README	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,9 @@
+Skin inditreuse
+Author: Kyle Kochis (http://completesiteservices.com/)
+This work is licensed under the Creative Commons Attribution-ShareAlike License.
+To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.0/
+or send a letter to
+Creative Commons,
+559 Nathan Abbott Way
+Stanford, California 94305
+USA
\ No newline at end of file

Added: plog/trunk/js/xinha/skins/inditreuse/back.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/inditreuse/back.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/inditreuse/button-background.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/inditreuse/button-background.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/inditreuse/hover.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/inditreuse/hover.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/inditreuse/selected.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/inditreuse/selected.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/inditreuse/separator.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/inditreuse/separator.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/inditreuse/skin.css
===================================================================
--- plog/trunk/js/xinha/skins/inditreuse/skin.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/inditreuse/skin.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,72 @@
+.htmlarea .toolbar {
+	background-color:#889fc9;
+  background-image:url(back.png);
+  background-repeat:repeat-y;
+}
+.htmlarea .toolbarRow {
+  margin-top:2px;
+  margin-bottom:2px;
+  background-image:url(button-background.png);
+}
+.htmlarea .toolbar .button {
+  width:20px;
+  height:20px;
+  padding:1px;
+  border:none;
+  background-image:url(button-background.png);
+}
+.buttonImageContainer {
+  position:relative;
+  left:1px;
+  top:1px;
+}
+.htmlarea .toolbar .separator {
+  margin:0;
+  background-image: url(separator.png);
+  width:7px;
+  height:20px;
+  padding:1px;
+  border:none;
+}
+.htmlarea .toolbar a.button:hover {
+  border:none !important;
+  padding:1px;
+  background-image:url(hover.png);
+}
+.htmlarea .toolbar .button.buttonPressed
+{
+  padding:1px;
+  background-image:url(selected.png);
+}
+.htmlarea .statusBar {
+  padding:0;
+  height:20px;
+  background-image:url(button-background.png);
+  background-repeat:repeat-x;
+  background-color:#889fc9;
+  color:ButtonText;
+  font:11px helvetica,arial,sans-serif;
+}
+.htmlarea .statusBar .statusBarTree {
+  display:block;
+  margin:3px;
+}
+.htmlarea .statusBar .statusBarTree a {
+  padding:2px 5px;
+  color:#00f;
+  text-decoration:none;
+}
+.htmlarea .panel h1 {
+  background-image:url(button-background.png);
+  background-repeat:repeat-x;
+  background-color:#889fc9;
+}
+.dialog {
+  background-color:#889fc9;
+}
+.dialog .title {
+  background-image: url(button-background.png);
+}  
+.dialog button{
+  background-image: url(button-background.png);
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/skins/titan/README
===================================================================
--- plog/trunk/js/xinha/skins/titan/README	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/titan/README	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,12 @@
+Skin Titan, a modification of Skin inditreuse by Mike Harris (www.jonesstandard.org)
+I simply changed the background to look more like nickel, and the dots on the separator have been replaced.  
+Everything else is the same.
+
+Skin inditreuse Author: Kyle Kochis (http://completesiteservices.com/)
+This work is licensed under the Creative Commons Attribution-ShareAlike License.
+To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.0/
+or send a letter to
+Creative Commons,
+559 Nathan Abbott Way
+Stanford, California 94305
+USA
\ No newline at end of file

Added: plog/trunk/js/xinha/skins/titan/back.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/titan/back.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/titan/button-background.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/titan/button-background.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/titan/hover.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/titan/hover.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/titan/selected.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/titan/selected.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/titan/separator.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/titan/separator.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/titan/skin.css
===================================================================
--- plog/trunk/js/xinha/skins/titan/skin.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/titan/skin.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,67 @@
+.htmlarea .toolbar {
+	background-color:#889fc9;
+  background-image:url(back.png);
+  background-repeat:repeat-y;
+}
+.htmlarea .toolbarRow {
+  margin-top:2px;
+  margin-bottom:2px;
+  background-image:url(button-background.png);
+}
+.htmlarea .toolbar .toolbarRow .button{
+  width:20px;
+  height:20px;
+  padding:1px;
+  border:none;
+  background-image:url(button-background.png);
+}
+.htmlarea .toolbar .toolbarRow .separator {
+  margin:0;
+  background-image: url(separator.png);
+  width:7px;
+  height:20px;
+  padding:1px;
+  border:none;
+}
+.htmlarea .toolbar .toolbarRow .buttonHover {
+  border:none !important;
+  padding:1px;
+  background-image:url(hover.png);
+}
+.htmlarea .toolbar .toolbarRow .button.buttonPressed
+{
+  padding:1px;
+  background-image:url(selected.png);
+}
+.htmlarea .statusBar {
+  padding:0;
+  height:20px;
+  background-image:url(button-background.png);
+  background-repeat:repeat-x;
+  background-color:#889fc9;
+  color:ButtonText;
+  font:11px helvetica,arial,sans-serif;
+}
+.htmlarea .statusBar .statusBarTree {
+  display:block;
+  margin:3px;
+}
+.htmlarea .statusBar .statusBarTree a {
+  padding:2px 5px;
+  color:#00f;
+  text-decoration:none;
+}
+.htmlarea .panel h1 {
+  background-image:url(button-background.png);
+  background-repeat:repeat-x;
+  background-color:#889fc9;
+}
+.dialog {
+  background-color:#f7f8fd;
+}
+.dialog .title {
+  background-image: url(button-background.png);
+}  
+.dialog button{
+  background-image: url(button-background.png);
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/skins/xp-blue/back.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-blue/back.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-blue/button-background.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-blue/button-background.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-blue/hover.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-blue/hover.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-blue/selected.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-blue/selected.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-blue/separator.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-blue/separator.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-blue/skin.css
===================================================================
--- plog/trunk/js/xinha/skins/xp-blue/skin.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/xp-blue/skin.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,75 @@
+.htmlarea .toolbar {
+	background-color:#c3daf9;
+  background-image:url(back.png);
+  background-repeat:repeat-y;
+}
+.htmlarea .toolbarRow {
+  margin-top:2px;
+  margin-bottom:2px;
+  background-image:url(button-background.png);
+}
+.htmlarea .toolbar .button {
+  width:20px;
+  height:20px;
+  padding:1px;
+  border:none;
+  background-image:url(button-background.png);
+}
+.buttonImageContainer {
+  position:relative;
+  left:1px;
+  top:1px;
+}
+.htmlarea .toolbar .separator {
+  margin:0;
+  background-image:url(separator.png);
+  width:7px;
+  height:20px;
+  padding:0;
+}
+.separator {
+  border:none;
+}
+.htmlarea .toolbar a.button:hover {
+  border:1px solid #003355;
+  padding:0;
+  background-image:url(hover.png);
+}
+.htmlarea .toolbar .button.buttonPressed
+{
+  border:1px solid #003355;
+  padding:0;
+  background-image:url(selected.png);
+}
+.htmlarea .statusBar {
+  padding:0;
+  height:20px;
+  background-image:url(button-background.png);
+  background-repeat:repeat-x;
+  background-color:#c3daf9;
+  color:ButtonText;
+  font:11px helvetica,arial,sans-serif;
+}
+.htmlarea .statusBar .statusBarTree {
+  display:block;
+  margin:3px;
+}
+.htmlarea .statusBar .statusBarTree a {
+  padding:2px 5px;
+  color:#00f;
+  text-decoration:none;
+}
+.htmlarea .panel h1 {
+  background-image:url(button-background.png);
+  background-repeat:repeat-x;
+  background-color:#c3daf9;
+}
+.dialog {
+  background-color:#c3daf9;
+}
+.dialog .title {
+  background-image: url(button-background.png);
+}  
+.dialog button{
+  background-image: url(button-background.png);
+}
\ No newline at end of file

Added: plog/trunk/js/xinha/skins/xp-green/back.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-green/back.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-green/button-background.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-green/button-background.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-green/hover.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-green/hover.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-green/selected.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-green/selected.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-green/separator.png
===================================================================
(Binary files differ)


Property changes on: plog/trunk/js/xinha/skins/xp-green/separator.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: plog/trunk/js/xinha/skins/xp-green/skin.css
===================================================================
--- plog/trunk/js/xinha/skins/xp-green/skin.css	2005-07-19 05:55:13 UTC (rev 2348)
+++ plog/trunk/js/xinha/skins/xp-green/skin.css	2005-07-20 05:55:47 UTC (rev 2349)
@@ -0,0 +1,75 @@
+.htmlarea .toolbar {
+  background-color:#f2f0e4;
+  background-image:url(back.png);
+  background-repeat:repeat-y;
+}
+.htmlarea .toolbarRow {
+  margin-top:2px;
+  margin-bottom:2px;
+  background-image:url(button-background.png);
+}
+.htmlarea .toolbar .button {
+  width:20px;
+  height:20px;
+  padding:1px;
+  border:none;
+  background-image:url(button-background.png);
+}
+.buttonImageContainer {
+  position:relative;
+  left:1px;
+  top:1px;
+}
+.htmlarea .toolbar .separator {
+  margin:0;
+  background-image:url(separator.png);
+  width:7px;
+  height:20px;
+  padding:0;
+}
+.separator {
+  border:none;
+}
+.htmlarea .toolbar a.button:hover {
+  border:1px solid #335500;
+  padding:0;
+  background-image:url(hover.png);
+}
+.htmlarea .toolbar .button.buttonPressed
+{
+  border:1px solid #335500;
+  padding:0;
+  background-image:url(selected.png);
+}
+.htmlarea .statusBar {
+  padding:0;
+  height:20px;
+  background-image:url(button-background.png);
+  background-repeat:repeat-x;
+  background-color:#f2f0e4;
+  color:ButtonText;
+  font:11px helvetica,arial,sans-serif;
+}
+.htmlarea .statusBar .statusBarTree {
+  display:block;
+  margin:3px;
+}
+.htmlarea .statusBar .statusBarTree a {
+  padding:2px 5px;
+  color:#00f;
+  text-decoration:none;
+}
+.htmlarea .panel h1 {
+  background-image:url(button-background.png);
+  background-repeat:repeat-x;
+  background-color:#f2f0e4;
+}
+.dialog {
+  background-color:#f2f0e4;
+}
+.dialog .title {
+  background-image: url(button-background.png);
+}  
+.dialog button{
+  background-image: url(button-background.png);
+}
\ No newline at end of file




More information about the pLog-svn mailing list