You are viewing a plain text version of this content. The canonical link for it is here.
Posted to graffito-commits@incubator.apache.org by cl...@apache.org on 2006/10/09 21:28:32 UTC

svn commit: r454522 [6/10] - in /incubator/graffito/trunk: applications/browser/src/java/org/apache/portals/graffito/servlets/ applications/browser/src/java/org/apache/portals/graffito/servlets/browser/ applications/browser/src/webapp/META-INF/ applica...

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/infrae_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/kupu_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/kupu_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/kupu_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/kupu_logo_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/kupu_logo_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/kupu_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/lenya_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/lenya_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/lenya_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/lenya_logo_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/lenya_logo_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/lenya_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/opensource.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/opensource.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/opensource.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/opensource_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/opensource_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/opensource_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom4_banner.gif
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom4_banner.gif?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom4_banner.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom4_banner_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom4_banner_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom4_banner_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom_logo_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom_logo_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/oscom_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/plone_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/plone_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/plone_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/plone_logo_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/plone_logo_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/plone_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/pypy_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/pypy_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/pypy_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/pypy_logo_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/pypy_logo_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/pypy_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/silva_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/silva_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/silva_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/silva_logo_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/silva_logo_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/silva_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/twiki_logo.gif
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/twiki_logo.gif?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/twiki_logo.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/twiki_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/twiki_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/twiki_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zea_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zea_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zea_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zea_logo_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zea_logo_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zea_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zope_logo.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zope_logo.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zope_logo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zope_logo_preview.png
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zope_logo_preview.png?view=auto&rev=454522
==============================================================================
Binary file - no diff available.

Propchange: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawers/logos/zope_logo_preview.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawerstyles.css
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawerstyles.css?view=auto&rev=454522
==============================================================================
--- incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawerstyles.css (added)
+++ incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupudrawerstyles.css Mon Oct  9 14:28:27 2006
@@ -0,0 +1,210 @@
+/*****************************************************************************
+ *
+ * Kupu drawer styles
+ *
+ * Copyright (c) 2003-2005 Kupu Contributors. See CREDITS.txt
+ *
+ * Instead of customizing this file, it is recommended to add your own
+ * CSS file.  Feel free to use whole or parts of this for your own
+ * designs, but give credit where credit is due.
+ *
+ *****************************************************************************/
+
+/* $Id: kupudrawerstyles.css 21177 2005-12-15 14:39:58Z duncan $ */
+
+.kupu-drawer {
+  position: absolute;
+  display: none;
+  border: solid 1px gray;
+  border-top: solid 10px #c0c0c0;
+  background-color: ButtonFace;
+  padding: 0 8px 8px 8px;
+  height: auto;
+  width: 640px;
+  z-index: 2;
+  color: black;
+}
+
+.kupu-tabledrawer {
+  width: 408px;
+  left: 320px;
+}
+.kupu-tabledrawer .kupu-panels,
+.kupu-tabledrawer .kupu-panels table,
+.kupu-tabledrawer div.kupu-dialogbuttons {
+  width: 400px;
+}
+
+.kupu-drawer h1 {
+   height: auto; width: auto;
+}
+
+input#kupu-searchbox-input {
+  width: 8em;
+  margin-bottom: 6px;
+  margin-top: 12px;
+  padding: 2px;
+}
+
+div.kupu-linkdrawer-addlink td {
+  border: 0;
+}
+input.kupu-linkdrawer-input {
+   width: 500px;
+}
+iframe.kupu-linkdrawer-preview {
+   width: 100%;
+}
+
+div#kupu-librarydrawer h1, div.kupu-drawer h1 {
+  margin-top: 12px;
+}
+
+div.kupu-dialogbuttons {
+  text-align: right;
+  margin-top: 6px;
+  margin-bottom: 6px;
+  width: 640px; /* Mozilla bug */
+}
+
+div.kupu-drawer button {
+  margin-right: 0.3em;
+}
+
+div.kupu-panels {
+  width: 100%;
+  background-color: ButtonFace;
+  clear:both;
+}
+
+div.kupu-panels td {
+/*  font-size: 12px;*/
+  background-color: white;
+  vertical-align: top;
+}
+
+div.kupu-panels td.kupu-preview-button {
+  vertical-align: bottom;
+}
+
+div.kupu-panels table {
+ width: 100%;
+ margin: 0; 
+ padding: 0; 
+ border: 0;
+}
+
+td.panel {
+  height: 260px;
+}
+
+td#kupu-librariespanel {
+  overflow: auto;
+  width: 105px;
+}
+
+div#kupu-librariesitems {
+  width: 105px;
+  white-space: pre;
+  height: 100%;
+}
+
+td#kupu-resourcespanel {
+  overflow: auto;
+  width: 185px;
+}
+
+div#kupu-resourceitems {
+  white-space: pre;
+  width: 200px;
+  height: 100%;
+}
+
+div#kupu-properties {
+  height: 100%;
+}
+
+div#kupu-librariesitems, div#kupu-resourceitems, div#kupu-properties {
+  padding: 6px;
+}
+
+.overflow {
+  overflow: auto;
+  height: 100%;
+}
+
+div.response, div.collection {
+  background-repeat: no-repeat;
+  padding-left: 20px;
+  height: 15px;
+  margin-top: 0.1em;
+  overflow: hidden;
+  padding-top: 4px;
+}
+
+div.kupu-libsource, div.kupu-libsource-selected,
+div.kupu-resource, div.kupu-collection, div.kupu-upload {
+  cursor: pointer;
+  margin-bottom: 2px;
+  vertical-align: text-bottom;
+  white-space: pre;
+}
+div.kupu-upload {
+   text-align: right; font-style: italic;
+}
+
+/*div.kupu-libsource-selected {
+  background-repeat: no-repeat;
+}*/
+
+/*div.kupu-libsource-selected span,
+ div.kupu-libsource span{
+  margin-top: 3px;
+  display: inline;
+}*/
+
+div.kupu-libsource-selected span {
+  background-color: ButtonFace;  
+}
+
+#kupu-tabledrawer-edittable {
+  display: none;
+}
+
+img.library-icon-collection, img.library-icon-resource {
+  margin-right: 5px;
+  height: 16px;
+  width: 16px;
+}
+
+span.drawer-item-title {
+  padding-left: 2px;
+  padding-right: 2px;
+  padding-top: 2px;
+}
+
+span.drawer-item-title.selected-item {
+  background-color:#C0C0C0;
+}
+
+/* Local image upload form */
+
+#kupu-upload-file, #kupu-upload-title {
+  margin-top: 0.1em;
+  margin-bottom: 0.5em;
+  width: 95%;
+  clear:both;
+}
+
+#kupu-upload-instructions {
+  margin-top: 0.5em;
+  margin-bottom: 1em;
+  clear:both;
+  line-height: normal;
+}
+
+th.kupu-toolbox-label {
+   text-align:right;
+   width: 5%;
+   white-space: nowrap;
+}
\ No newline at end of file

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupueditor.js
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupueditor.js?view=auto&rev=454522
==============================================================================
--- incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupueditor.js (added)
+++ incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupueditor.js Mon Oct  9 14:28:27 2006
@@ -0,0 +1,819 @@
+/*****************************************************************************
+ *
+ * Copyright (c) 2003-2005 Kupu Contributors. All rights reserved.
+ *
+ * This software is distributed under the terms of the Kupu
+ * License. See LICENSE.txt for license text. For a list of Kupu
+ * Contributors see CREDITS.txt.
+ *
+ *****************************************************************************/
+
+// $Id: kupueditor.js 18104 2005-10-03 14:10:11Z duncan $
+
+//----------------------------------------------------------------------------
+// Main classes
+//----------------------------------------------------------------------------
+
+/* KupuDocument
+    
+    This essentially wraps the iframe.
+    XXX Is this overkill?
+    
+*/
+
+function KupuDocument(iframe) {
+    /* Model */
+    
+    // attrs
+    this.editable = iframe; // the iframe
+    this.window = this.editable.contentWindow;
+    this.document = this.window.document;
+
+    this._browser = _SARISSA_IS_IE ? 'IE' : 'Mozilla';
+    
+    // methods
+    this.execCommand = function(command, arg) {
+        /* delegate execCommand */
+        if (arg === undefined) arg = null;
+        this.document.execCommand(command, false, arg);
+    };
+    
+    this.reloadSource = function() {
+        /* reload the source */
+        
+        // XXX To temporarily work around problems with resetting the
+        // state after a reload, currently the whole page is reloaded.
+        // XXX Nasty workaround!! to solve refresh problems...
+        document.location = document.location;
+    };
+
+    this.getDocument = function() {
+        /* returns a reference to the window.document object of the iframe */
+        return this.document;
+    };
+
+    this.getWindow = function() {
+        /* returns a reference to the window object of the iframe */
+        return this.window;
+    };
+
+    this.getSelection = function() {
+        if (this._browser == 'Mozilla') {
+            return new MozillaSelection(this);
+        } else {
+            return new IESelection(this);
+        };
+    };
+
+    this.getEditable = function() {
+        return this.editable;
+    };
+};
+
+/* KupuEditor
+
+    This controls the document, should be used from the UI.
+    
+*/
+
+function KupuEditor(document, config, logger) {
+    /* Controller */
+    
+    // attrs
+    this.document = document; // the model
+    this.config = config; // an object that holds the config values
+    this.log = logger; // simple logger object
+    this.tools = {}; // mapping id->tool
+    this.filters = new Array(); // contentfilters
+    
+    this._designModeSetAttempts = 0;
+    this._initialized = false;
+
+    // some properties to save the selection, required for IE to remember 
+    // where in the iframe the selection was
+    this._previous_range = null;
+
+    // this property is true if the content is changed, false if no changes 
+    // are made yet
+    this.content_changed = false;
+
+    // methods
+    this.initialize = function() {
+        /* Should be called on iframe.onload, will initialize the editor */
+        //DOM2Event.initRegistration();
+        this._initializeEventHandlers();
+        if (this.getBrowserName() == "IE") {
+            var body = this.getInnerDocument().getElementsByTagName('body')[0];
+            body.setAttribute('contentEditable', 'true');
+            // provide an 'afterInit' method on KupuEditor.prototype
+            // for additional bootstrapping (after editor init)
+            this._initialized = true;
+            if (this.afterInit) {
+                this.afterInit();
+            };
+            this._saveSelection();
+        } else {
+            this._setDesignModeWhenReady();
+        };
+        this.logMessage(_('Editor initialized'));
+    };
+
+    this.setContextMenu = function(menu) {
+        /* initialize the contextmenu */
+        menu.initialize(this);
+    };
+
+    this.registerTool = function(id, tool) {
+        /* register a tool */
+        this.tools[id] = tool;
+        tool.initialize(this);
+    };
+
+    this.getTool = function(id) {
+        /* get a tool by id */
+        return this.tools[id];
+    };
+
+    this.registerFilter = function(filter) {
+        /* register a content filter method
+
+            the method will be called together with any other registered
+            filters before the content is saved to the server, the methods
+            can be used to filter any trash out of the content. they are
+            called with 1 argument, which is a reference to the rootnode
+            of the content tree (the html node)
+        */
+        this.filters.push(filter);
+        filter.initialize(this);
+    };
+
+    this.updateStateHandler = function(event) {
+        /* check whether the event is interesting enough to trigger the 
+        updateState machinery and act accordingly */
+        var interesting_codes = new Array(8, 13, 37, 38, 39, 40, 46);
+        // unfortunately it's not possible to do this on blur, since that's
+        // too late. also (some versions of?) IE 5.5 doesn't support the
+        // onbeforedeactivate event, which would be ideal here...
+        this._saveSelection();
+
+        if (event.type == 'click' || event.type=='mouseup' ||
+                (event.type == 'keyup' && 
+                    interesting_codes.contains(event.keyCode))) {
+            // Filthy trick to make the updateState method get called *after*
+            // the event has been resolved. This way the updateState methods can
+            // react to the situation *after* any actions have been performed (so
+            // can actually stay up to date).
+            this.updateState(event);
+        }
+    };
+    
+    this.updateState = function(event) {
+        /* let each tool change state if required */
+        // first see if the event is interesting enough to trigger
+        // the whole updateState machinery
+        var selNode = this.getSelectedNode();
+        for (var id in this.tools) {
+            try {
+                this.tools[id].updateState(selNode, event);
+            } catch (e) {
+                if (e == UpdateStateCancelBubble) {
+                    this.updateState(event);
+                    break;
+                } else {
+                    this.logMessage(
+                        _('Exception while processing updateState on ' +
+                            '${id}: ${msg}', {'id': id, 'msg': e}), 2);
+                };
+            };
+        };
+    };
+    
+    this.saveDocument = function(redirect, synchronous) {
+        /* save the document
+
+            the (optional) redirect argument can be used to make the client 
+            jump to another URL when the save action was successful.
+
+            synchronous is a boolean to allow sync saving (usually better to
+            not save synchronous, since it may make browsers freeze on errors,
+            this is used for saveOnPart, though)
+        */
+        
+
+        // if no dst is available, bail out
+        if (!this.config.dst) {
+            this.logMessage(_('No destination URL available!'), 2);
+            alert("NO DST");
+            return;
+        }
+        var sourcetool = this.getTool('sourceedittool');
+        if (sourcetool) {sourcetool.cancelSourceMode();};
+
+        // make sure people can't edit or save during saving
+        if (!this._initialized) {
+            return;
+        }
+        this._initialized = false;
+        
+        // set the window status so people can see we're actually saving
+        window.status= _("Please wait while saving document...");
+
+        // call (optional) beforeSave() method on all tools
+        for (var id in this.tools) {
+            var tool = this.tools[id];
+            if (tool.beforeSave) {
+                try {
+                    tool.beforeSave();
+                } catch(e) {
+                    alert(e);
+                    this._initialized = true;
+                    return;
+                };
+            };
+        };
+        
+        // pass the content through the filters
+        this.logMessage(_("Starting HTML cleanup"));
+        var transform = this._filterContent(this.getInnerDocument().documentElement);
+
+        // serialize to a string
+        var contents = this._serializeOutputToString(transform);
+        
+        this.logMessage(_("Cleanup done, sending document to server"));
+        var request = new XMLHttpRequest();
+    
+        if (!synchronous) {
+            request.onreadystatechange = (new ContextFixer(this._saveCallback, 
+                                               this, request, redirect)).execute;
+            
+            request.open("PUT", this.config.dst, true);
+            request.setRequestHeader("Content-type", this.config.content_type);
+            request.send(contents);
+            this.logMessage(_("Request sent to server"));
+        } else {
+            this.logMessage(_('Sending request to server'));
+            
+            request.open("PUT", this.config.dst, false);
+            request.setRequestHeader("Content-type", this.config.content_type);
+            request.send(contents);
+            this.handleSaveResponse(request,redirect)
+        };
+    };
+    
+    this.prepareForm = function(form, id) {
+        /* add a field to the form and place the contents in it
+
+            can be used for simple POST support where Kupu is part of a
+            form
+        */
+        var sourcetool = this.getTool('sourceedittool');
+        if (sourcetool) {sourcetool.cancelSourceMode();};
+
+        // make sure people can't edit or save during saving
+        if (!this._initialized) {
+            return;
+        }
+        this._initialized = false;
+        
+        // set the window status so people can see we're actually saving
+        window.status= _("Please wait while saving document...");
+
+        // call (optional) beforeSave() method on all tools
+        for (var tid in this.tools) {
+            var tool = this.tools[tid];
+            if (tool.beforeSave) {
+                try {
+                    tool.beforeSave();
+                } catch(e) {
+                    alert(e);
+                    this._initialized = true;
+                    return;
+                };
+            };
+        };
+        
+        // set a default id
+        if (!id) {
+            id = 'kupu';
+        };
+        
+        // pass the content through the filters
+        this.logMessage(_("Starting HTML cleanup"));
+        var transform = this._filterContent(this.getInnerDocument().documentElement);
+        
+        // XXX need to fix this.  Sometimes a spurious "\n\n" text 
+        // node appears in the transform, which breaks the Moz 
+        // serializer on .xml
+        var contents =  this._serializeOutputToString(transform);
+        
+        this.logMessage(_("Cleanup done, sending document to server"));
+        
+        // now create the form input, since IE 5.5 doesn't support the 
+        // ownerDocument property we use window.document as a fallback (which
+        // will almost by definition be correct).
+        var document = form.ownerDocument ? form.ownerDocument : window.document;
+        var ta = document.createElement('textarea');
+        ta.style.visibility = 'hidden';
+        var text = document.createTextNode(contents);
+        ta.appendChild(text);
+        ta.setAttribute('name', id);
+        
+        // and add it to the form
+        form.appendChild(ta);
+
+        // let the calling code know we have added the textarea
+        return true;
+    };
+
+    this.execCommand = function(command, param) {
+        /* general stuff like making current selection bold, italics etc. 
+            and adding basic elements such as lists
+            */
+        if (!this._initialized) {
+            this.logMessage(_('Editor not initialized yet!'));
+            return;
+        };
+        if (this.getBrowserName() == "IE") {
+            this._restoreSelection();
+        } else {
+            this.focusDocument();
+            if (command != 'useCSS') {
+                this.content_changed = true;
+                // note the negation: the argument doesn't work as
+                // expected...
+                // Done here otherwise it doesn't always work or gets lost
+                // after some commands
+                this.getDocument().execCommand('useCSS', !this.config.use_css);
+            };
+        };
+        this.getDocument().execCommand(command, param);
+        var message = _('Command ${command} executed', {'command': command});
+        if (param) {
+            message = _('Command ${command} executed with parameter ${param}',
+                            {'command': command, 'param': param});
+        }
+        this.updateState();
+        this.logMessage(message);
+    };
+
+    this.getSelection = function() {
+        /* returns a Selection object wrapping the current selection */
+        this._restoreSelection();
+        return this.getDocument().getSelection();
+    };
+
+    this.getSelectedNode = function() {
+        /* returns the selected node (read: parent) or none */
+        return this.getSelection().parentElement();
+    };
+
+    this.getNearestParentOfType = function(node, type) {
+        /* well the title says it all ;) */
+        var type = type.toLowerCase();
+        while (node) {
+            if (node.nodeName.toLowerCase() == type) {
+                return node
+            }   
+            var node = node.parentNode;
+        }
+        return false;
+    };
+
+    this.removeNearestParentOfType = function(node, type) {
+        var nearest = this.getNearestParentOfType(node, type);
+        if (!nearest) {
+            return false;
+        };
+        var parent = nearest.parentNode;
+        while (nearest.childNodes.length) {
+            var child = nearest.firstChild;
+            child = nearest.removeChild(child);
+            parent.insertBefore(child, nearest);
+        };
+        parent.removeChild(nearest);
+    };
+
+    this.getDocument = function() {
+        /* returns a reference to the document object that wraps the iframe */
+        return this.document;
+    };
+
+    this.getInnerDocument = function() {
+        /* returns a reference to the window.document object of the iframe */
+        return this.getDocument().getDocument();
+    };
+
+    this.insertNodeAtSelection = function(insertNode, selectNode) {
+        /* insert a newly created node into the document */
+        if (!this._initialized) {
+            this.logMessage(_('Editor not initialized yet!'));
+            return;
+        };
+
+        this.content_changed = true;
+
+        var browser = this.getBrowserName();
+        if (browser != "IE") {
+            this.focusDocument();
+        };
+        
+        var ret = this.getSelection().replaceWithNode(insertNode, selectNode);
+        this._saveSelection();
+
+        return ret;
+    };
+
+    this.focusDocument = function() {
+        this.getDocument().getWindow().focus();
+    }
+
+    this.logMessage = function(message, severity) {
+        /* log a message using the logger, severity can be 0 (message, default), 1 (warning) or 2 (error) */
+        this.log.log(message, severity);
+    };
+
+    this.registerContentChanger = function(element) {
+        /* set this.content_changed to true (marking the content changed) when the 
+            element's onchange is called
+        */
+        addEventHandler(element, 'change', function() {this.content_changed = true;}, this);
+    };
+    
+    // helper methods
+    this.getBrowserName = function() {
+        /* returns either 'Mozilla' (for Mozilla, Firebird, Netscape etc.) or 'IE' */
+        if (_SARISSA_IS_MOZ) {
+            return "Mozilla";
+        } else if (_SARISSA_IS_IE) {
+            return "IE";
+        } else {
+            throw _("Browser not supported!");
+        }
+    };
+    
+    this.handleSaveResponse = function(request, redirect) {
+        // mind the 1223 status, somehow IE gives that sometimes (on 204?)
+        // at first we didn't want to add it here, since it's a specific IE
+        // bug, but too many users had trouble with it...
+        if (request.status != '200' && request.status != '204' &&
+                request.status != '1223') {
+            var msg = _('Error saving your data.\nResponse status: ' + 
+                            '${status}.\nCheck your server log for more ' +
+                            'information.', {'status': request.status});
+            alert(msg);
+            window.status = _("Error saving document");
+        } else if (redirect) { // && (!request.status || request.status == '200' || request.status == '204'))
+            window.document.location = redirect;
+            this.content_changed = false;
+        } else {
+            // clear content_changed before reloadSrc so saveOnPart is not triggered
+            this.content_changed = false;
+            if (this.config.reload_after_save) {
+                this.reloadSrc();
+            };
+            // we're done so we can start editing again
+            window.status= _("Document saved");
+        };
+        this._initialized = true;
+    };
+
+    // private methods
+    this._addEventHandler = addEventHandler;
+
+    this._saveCallback = function(request, redirect) {
+        /* callback for Sarissa */
+        if (request.readyState == 4) {
+            this.handleSaveResponse(request, redirect)
+        };
+    };
+    
+    this.reloadSrc = function() {
+        /* reload the src, called after a save when reload_src is set to true */
+        // XXX Broken!!!
+        /*
+        if (this.getBrowserName() == "Mozilla") {
+            this.getInnerDocument().designMode = "Off";
+        }
+        */
+        // XXX call reloadSrc() which has a workaround, reloads the full page
+        // instead of just the iframe...
+        this.getDocument().reloadSource();
+        if (this.getBrowserName() == "Mozilla") {
+            this.getInnerDocument().designMode = "On";
+        };
+        /*
+        var selNode = this.getSelectedNode();
+        this.updateState(selNode);
+        */
+    };
+
+    this._initializeEventHandlers = function() {
+        /* attache the event handlers to the iframe */
+        // Initialize DOM2Event compatibility
+        // XXX should come back and change to passing in an element
+        this._addEventHandler(this.getInnerDocument(), "click", this.updateStateHandler, this);
+        this._addEventHandler(this.getInnerDocument(), "dblclick", this.updateStateHandler, this);
+        this._addEventHandler(this.getInnerDocument(), "keyup", this.updateStateHandler, this);
+        this._addEventHandler(this.getInnerDocument(), "keyup", function() {this.content_changed = true}, this);
+        this._addEventHandler(this.getInnerDocument(), "mouseup", this.updateStateHandler, this);
+    };
+
+    this._setDesignModeWhenReady = function() {
+        /* Rather dirty polling loop to see if Mozilla is done doing it's
+            initialization thing so design mode can be set.
+        */
+        this._designModeSetAttempts++;
+        if (this._designModeSetAttempts > 25) {
+            alert(_('Couldn\'t set design mode. Kupu will not work on this browser.'));
+            return;
+        };
+        var success = false;
+        try {
+            this._setDesignMode();
+            success = true;
+        } catch (e) {
+            // register a function to the timer_instance because 
+            // window.setTimeout can't refer to 'this'...
+            timer_instance.registerFunction(this, this._setDesignModeWhenReady, 100);
+        };
+        if (success) {
+            // provide an 'afterInit' method on KupuEditor.prototype
+            // for additional bootstrapping (after editor init)
+            if (this.afterInit) {
+                this.afterInit();
+            };
+        };
+    };
+
+    this._setDesignMode = function() {
+        this.getInnerDocument().designMode = "On";
+        this.execCommand("undo");
+        // note the negation: the argument doesn't work as expected...
+        this._initialized = true;
+    };
+
+    this._saveSelection = function() {
+        /* Save the selection, works around a problem with IE where the 
+         selection in the iframe gets lost. We only save if the current 
+         selection in the document */
+        if (this._isDocumentSelected()) {
+            var currange = this.getInnerDocument().selection.createRange();
+            this._previous_range = currange;
+        };
+    };
+
+    this._restoreSelection = function() {
+        /* re-selects the previous selection in IE. We only restore if the
+        current selection is not in the document.*/
+        if (this._previous_range && !this._isDocumentSelected()) {
+            try {
+                this._previous_range.select();
+            } catch (e) {
+                alert("Error placing back selection");
+                this.logMessage(_('Error placing back selection'));
+            };
+        };
+    };
+    
+    if (this.getBrowserName() != "IE") {
+        this._saveSelection = function() {};
+        this._restoreSelection = function() {};
+    }
+
+    this._isDocumentSelected = function() {
+        var editable_body = this.getInnerDocument().getElementsByTagName('body')[0];
+        try {
+            var selrange = this.getInnerDocument().selection.createRange();
+        } catch(e) {
+            return false;
+        }
+        var someelement = selrange.parentElement ? selrange.parentElement() : selrange.item(0);
+
+        while (someelement.nodeName.toLowerCase() != 'body') {
+            someelement = someelement.parentNode;
+        };
+        
+        return someelement == editable_body;
+    };
+
+    this._clearSelection = function() {
+        /* clear the last stored selection */
+        this._previous_range = null;
+    };
+
+    this._filterContent = function(documentElement) {            
+        /* pass the content through all the filters */
+        // first copy all nodes to a Sarissa document so it's usable
+        var xhtmldoc = Sarissa.getDomDocument();
+        var doc = this._convertToSarissaNode(xhtmldoc, documentElement);
+        // now pass it through all filters
+        for (var i=0; i < this.filters.length; i++) {
+            var doc = this.filters[i].filter(xhtmldoc, doc);
+        };
+        // fix some possible structural problems, such as an empty or missing head, title
+        // or script or textarea tags without closing tag...
+        this._fixXML(doc, xhtmldoc);
+        return doc;
+    };
+
+    this.getXMLBody = function(transform) {
+        var bodies = transform.getElementsByTagName('body');
+        var data = '';
+        for (var i = 0; i < bodies.length; i++) {
+            data += Sarissa.serialize(bodies[i]);
+        }
+        return this.escapeEntities(data);
+    };
+
+    this.getHTMLBody = function() {
+        var doc = this.getInnerDocument();
+        var docel = doc.documentElement;
+        var bodies = docel.getElementsByTagName('body');
+        var data = '';
+        for (var i = 0; i < bodies.length; i++) {
+            data += bodies[i].innerHTML;
+        }
+        return this.escapeEntities(data);
+    };
+
+    // If we have multiple bodies this needs to remove the extras.
+    this.setHTMLBody = function(text) {
+        var bodies = this.getInnerDocument().documentElement.getElementsByTagName('body');
+        for (var i = 0; i < bodies.length-1; i++) {
+            bodies[i].parentNode.removeChild(bodies[i]);
+        }
+        bodies[bodies.length-1].innerHTML = text;
+    };
+
+    this._fixXML = function(doc, document) {
+        /* fix some structural problems in the XML that make it invalid XTHML */
+        // find if we have a head and title, and if not add them
+        var heads = doc.getElementsByTagName('head');
+        var titles = doc.getElementsByTagName('title');
+        if (!heads.length) {
+            // assume we have a body, guess Kupu won't work without one anyway ;)
+            var body = doc.getElementsByTagName('body')[0];
+            var head = document.createElement('head');
+            body.parentNode.insertBefore(head, body);
+            var title = document.createElement('title');
+            var titletext = document.createTextNode('');
+            head.appendChild(title);
+            title.appendChild(titletext);
+        } else if (!titles.length) {
+            var head = heads[0];
+            var title = document.createElement('title');
+            var titletext = document.createTextNode('');
+            head.appendChild(title);
+            title.appendChild(titletext);
+        };
+        // create a closing element for all elements that require one in XHTML
+        var dualtons = new Array('a', 'abbr', 'acronym', 'address', 'applet', 
+                                    'b', 'bdo', 'big', 'blink', 'blockquote', 
+                                    'button', 'caption', 'center', 'cite', 
+                                    'comment', 'del', 'dfn', 'dir', 'div',
+                                    'dl', 'dt', 'em', 'embed', 'fieldset',
+                                    'font', 'form', 'frameset', 'h1', 'h2',
+                                    'h3', 'h4', 'h5', 'h6', 'i', 'iframe',
+                                    'ins', 'kbd', 'label', 'legend', 'li',
+                                    'listing', 'map', 'marquee', 'menu',
+                                    'multicol', 'nobr', 'noembed', 'noframes',
+                                    'noscript', 'object', 'ol', 'optgroup',
+                                    'option', 'p', 'pre', 'q', 's', 'script',
+                                    'select', 'small', 'span', 'strike', 
+                                    'strong', 'style', 'sub', 'sup', 'table',
+                                    'tbody', 'td', 'textarea', 'tfoot',
+                                    'th', 'thead', 'title', 'tr', 'tt', 'u',
+                                    'ul', 'xmp');
+        // XXX I reckon this is *way* slow, can we use XPath instead or
+        // something to speed this up?
+        for (var i=0; i < dualtons.length; i++) {
+            var elname = dualtons[i];
+            var els = doc.getElementsByTagName(elname);
+            for (var j=0; j < els.length; j++) {
+                var el = els[j];
+                if (!el.hasChildNodes()) {
+                    var child = document.createTextNode('');
+                    el.appendChild(child);
+                };
+            };
+        };
+    };
+
+    this.xhtmlvalid = new XhtmlValidation(this);
+
+    this._convertToSarissaNode = function(ownerdoc, htmlnode) {
+        /* Given a string of non-well-formed HTML, return a string of 
+           well-formed XHTML.
+
+           This function works by leveraging the already-excellent HTML 
+           parser inside the browser, which generally can turn a pile 
+           of crap into a DOM.  We iterate over the HTML DOM, appending 
+           new nodes (elements and attributes) into a node.
+
+           The primary problems this tries to solve for crappy HTML: mixed 
+           element names, elements that open but don't close, 
+           and attributes that aren't in quotes.  This can also be adapted 
+           to filter out tags that you don't want and clean up inline styles.
+
+           Inspired by Guido, adapted by Paul from something in usenet.
+           Tag and attribute tables added by Duncan
+        */
+        return this.xhtmlvalid._convertToSarissaNode(ownerdoc, htmlnode);
+    };
+
+    this._fixupSingletons = function(xml) {
+        return xml.replace(/<([^>]+)\/>/g, "<$1 />");
+    }
+    this._serializeOutputToString = function(transform) {
+        // XXX need to fix this.  Sometimes a spurious "\n\n" text 
+        // node appears in the transform, which breaks the Moz 
+        // serializer on .xml
+            
+        if (this.config.strict_output) {
+            var contents =  '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' + 
+                            '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n' + 
+                            '<html xmlns="http://www.w3.org/1999/xhtml">' +
+                            Sarissa.serialize(transform.getElementsByTagName("head")[0]) +
+                            Sarissa.serialize(transform.getElementsByTagName("body")[0]) +
+                            '</html>';
+        } else {
+            var contents = '<html>' + 
+                            Sarissa.serialize(transform.getElementsByTagName("head")[0]) +
+                            Sarissa.serialize(transform.getElementsByTagName("body")[0]) +
+                            '</html>';
+        };
+
+        contents = this.escapeEntities(contents);
+
+        if (this.config.compatible_singletons) {
+            contents = this._fixupSingletons(contents);
+        };
+        
+        return contents;
+    };
+    this.escapeEntities = function(xml) {
+        // XXX: temporarily disabled
+        return xml;
+        // Escape non-ascii characters as entities.
+        return xml.replace(/[^\r\n -\177]/g,
+            function(c) {
+            return '&#'+c.charCodeAt(0)+';';
+        });
+    }
+
+    this.getFullEditor = function() {
+        var fulleditor = this.getDocument().getEditable();
+        while (!/kupu-fulleditor/.test(fulleditor.className)) {
+            fulleditor = fulleditor.parentNode;
+        }
+        return fulleditor;
+    }
+    // Control the className and hence the style for the whole editor.
+    this.setClass = function(name) {
+        this.getFullEditor().className += ' '+name;
+    }
+    
+    this.clearClass = function(name) {
+        var fulleditor = this.getFullEditor();
+        fulleditor.className = fulleditor.className.replace(' '+name, '');
+    }
+
+    this.suspendEditing = function() {
+        this._previous_range = this.getSelection().getRange();
+        this.setClass('kupu-modal');
+        for (var id in this.tools) {
+            this.tools[id].disable();
+        }
+        if (this.getBrowserName() == "IE") {
+            var body = this.getInnerDocument().getElementsByTagName('body')[0];
+            body.setAttribute('contentEditable', 'false');
+        } else {
+
+            this.getInnerDocument().designMode = "Off";
+            var iframe = this.getDocument().getEditable();
+            iframe.style.position = iframe.style.position?"":"relative"; // Changing this disables designMode!
+        }
+        this.suspended = true;
+    }
+    
+    this.resumeEditing = function() {
+        if (!this.suspended) {
+            return;
+        }
+        this.suspended = false;
+        this.clearClass('kupu-modal');
+        for (var id in this.tools) {
+            this.tools[id].enable();
+        }
+        if (this.getBrowserName() == "IE") {
+            this._restoreSelection();
+            var body = this.getInnerDocument().getElementsByTagName('body')[0];
+            body.setAttribute('contentEditable', 'true');
+        } else {
+            var doc = this.getInnerDocument();
+            doc.designMode = "On";
+            this.getSelection().restoreRange(this._previous_range);
+        }
+    }
+}
+

Added: incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupuform.html
URL: http://svn.apache.org/viewvc/incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupuform.html?view=auto&rev=454522
==============================================================================
--- incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupuform.html (added)
+++ incubator/graffito/trunk/applications/browser/src/webapp/kupu-1.3.5/kupuform.html Mon Oct  9 14:28:27 2006
@@ -0,0 +1,531 @@
+
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:i18n="http://xml.zope.org/namespaces/i18n" i18n:domain="kupu">
+
+  
+    <head>
+      
+    <title>Test Editor</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+  
+    <link href="kupustyles.css" rel="stylesheet" type="text/css"/>
+  
+    <link href="kupudrawerstyles.css" rel="stylesheet" type="text/css"/>
+  
+    <script type="text/javascript" src="sarissa.js"> </script>
+    <script type="text/javascript" src="sarissa_ieemu_xpath.js"> </script>
+    <script type="text/javascript" src="kupuhelpers.js"> </script>
+    <script type="text/javascript" src="kupueditor.js"> </script>
+    <script type="text/javascript" src="kupubasetools.js"> </script>
+    <script type="text/javascript" src="kupuloggers.js"> </script>
+    <script type="text/javascript" src="kupunoi18n.js"> </script>
+    <script type="text/javascript" src="../../i18n.js/i18n.js"> </script>
+    <script type="text/javascript" src="kupucleanupexpressions.js"> </script>
+    <script type="text/javascript" src="kupucontentfilters.js"> </script>
+    <script type="text/javascript" src="kuputoolcollapser.js"> </script>
+  
+    <script type="text/javascript" src="kupucontextmenu.js"> </script>
+  
+    <script type="text/javascript" src="kupuinit_form.js"> </script>
+    <script type="text/javascript" src="kupustart_form.js"> </script>
+  
+    <script type="text/javascript" src="kupusourceedit.js"> </script>
+  
+    <script type="text/javascript" src="kupuspellchecker.js"> </script>
+  
+    <script type="text/javascript" src="kupudrawers.js"> </script>
+  
+    </head>
+  
+    <body onload="kupu = startKupu()">
+      <h1>Kupu Editor Test Page</h1>
+      <form action="http://debris.demon.nl/printpost" method="POST">
+        
+    <div style="display: none;">
+      <xml id="kupuconfig" class="kupuconfig">
+        <kupuconfig>
+          
+    <dst>fulldoc.html</dst>
+    <use_css>1</use_css>
+    <reload_after_save>0</reload_after_save>
+    <strict_output>1</strict_output>
+    <content_type>application/xhtml+xml</content_type>
+    <compatible_singletons>1</compatible_singletons>
+    <table_classes>
+      <class>plain</class>
+      <class>listing</class>
+      <class>grid</class>
+      <class>data</class>
+    </table_classes>
+
+    <cleanup_expressions>
+      <set>
+        <name>Convert single quotes to curly ones</name>
+        <expression>
+          <reg>
+            (\W)'
+          </reg>
+          <replacement>
+            \1&#8216;
+          </replacement>
+        </expression>
+        <expression>
+          <reg>
+            '
+          </reg>
+          <replacement>
+            &#8217;
+          </replacement>
+        </expression>
+      </set>
+      <set>
+        <name>Reduce whitespace</name>
+        <expression>
+          <reg>
+            [\n\r\t]
+          </reg>
+          <replacement>
+            \x20
+          </replacement>
+        </expression>
+        <expression>
+          <reg>
+            [ ]{2}
+          </reg>
+          <replacement>
+            \x20
+          </replacement>
+        </expression>
+      </set>
+    </cleanup_expressions>
+  
+    <image_xsl_uri>kupudrawers/drawer.xsl</image_xsl_uri>
+    <link_xsl_uri>kupudrawers/drawer.xsl</link_xsl_uri>
+    <image_libraries_uri>kupudrawers/imagelibrary.xml</image_libraries_uri>
+    <link_libraries_uri>kupudrawers/linklibrary.xml</link_libraries_uri>
+    <search_images_uri> </search_images_uri>
+    <search_links_uri> </search_links_uri>
+  
+        </kupuconfig>
+      </xml>
+    </div>
+  
+    <div class="kupu-fulleditor">
+      
+    <div class="kupu-tb" id="toolbar">
+      
+    <span id="kupu-tb-buttons" class="kupu-tb-buttons">
+      
+    <span class="kupu-tb-buttongroup kupu-logo" style="float: right" id="kupu-logo">
+      <button type="button" class="kupu-logo" title="Kupu 1.3.5" i18n:attributes="title" accesskey="k" onclick="window.open('http://kupu.oscom.org');">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup" style="float: right" id="kupu-zoom">
+      <button type="button" class="kupu-zoom" id="kupu-zoom-button" i18n:attributes="title" title="zoom: alt-x" accesskey="x">&#160;</button>
+    </span>
+  
+    <select id="kupu-tb-styles">
+      <option value="P" i18n:translate="">
+        Normal
+      </option>
+      <option value="H1">
+        <span i18n:translate="">Heading 1</span>
+      </option>
+      <option value="H2">
+        <span i18n:translate="">Heading 2</span>
+      </option>
+      <option value="H3">
+        <span i18n:translate="">Heading 3</span>
+      </option>
+      <option value="H4">
+        <span i18n:translate="">Heading 4</span>
+      </option>
+      <option value="H5">
+        <span i18n:translate="">Heading 5</span>
+      </option>
+      <option value="H6">
+        <span i18n:translate="">Heading 6</span>
+      </option>
+      <option value="PRE" i18n:translate="">
+        Formatted
+      </option>
+    </select>
+  
+    <span class="kupu-tb-buttongroup">
+      <button type="button" class="kupu-save" id="kupu-save-button" title="Save" i18n:attributes="title" accesskey="s">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup" id="kupu-bg-basicmarkup">
+      <button type="button" class="kupu-bold" id="kupu-bold-button" title="bold: alt-b" i18n:attributes="title" accesskey="b">&#160;</button>
+      <button type="button" class="kupu-italic" id="kupu-italic-button" title="italic: alt-i" i18n:attributes="title" accesskey="i">&#160;</button>
+      <button type="button" class="kupu-underline" id="kupu-underline-button" title="underline: alt-u" i18n:attributes="title" accesskey="u">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup" id="kupu-bg-subsuper">
+      <button type="button" class="kupu-subscript" id="kupu-subscript-button" title="subscript: alt--" i18n:attributes="title" accesskey="-">&#160;</button>
+      <button type="button" class="kupu-superscript" id="kupu-superscript-button" title="superscript: alt-+" i18n:attributes="title" accesskey="+">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup">
+      
+      <button type="button" class="kupu-forecolor" id="kupu-forecolor-button" title="text color: alt-f" i18n:attributes="title" accesskey="f">&#160;</button>
+      <button type="button" class="kupu-hilitecolor" id="kupu-hilitecolor-button" title="background color: alt-h" i18n:attributes="title" accesskey="h">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup" id="kupu-bg-justify">
+      <button type="button" class="kupu-justifyleft" id="kupu-justifyleft-button" title="left justify: alt-l" i18n:attributes="title" accesskey="l">&#160;</button>
+      <button type="button" class="kupu-justifycenter" id="kupu-justifycenter-button" title="center justify: alt-c" i18n:attributes="title" accesskey="c">&#160;</button>
+      <button type="button" class="kupu-justifyright" id="kupu-justifyright-button" title="right justify: alt-r" i18n:attributes="title" accesskey="r">&#160;</button>
+    </span>
+  
+              <span class="kupu-tb-buttongroup" id="kupu-bg-list">
+      
+      <button type="button" class="kupu-insertorderedlist" title="numbered list: alt-#" id="kupu-list-ol-addbutton" i18n:attributes="title" accesskey="#">&#160;</button>
+      <button type="button" class="kupu-insertunorderedlist" title="unordered list: alt-*" id="kupu-list-ul-addbutton" i18n:attributes="title" accesskey="*">&#160;</button>
+              </span>
+  
+    <span class="kupu-tb-buttongroup" id="kupu-bg-definitionlist">
+      
+      <button type="button" class="kupu-insertdefinitionlist" title="definition list: alt-=" id="kupu-list-dl-addbutton" i18n:attributes="title" accesskey="=">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup" id="kupu-bg-indent">
+      <button type="button" class="kupu-outdent" id="kupu-outdent-button" title="outdent: alt-&lt;" i18n:attributes="title" accesskey="&lt;">&#160;</button>
+      <button type="button" class="kupu-indent" id="kupu-indent-button" title="indent: alt-&gt;" i18n:attributes="title" accesskey="&gt;">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup">
+      <button type="button" class="kupu-image" id="kupu-imagelibdrawer-button" title="image" i18n:attributes="title">&#160;</button>
+      <button type="button" class="kupu-inthyperlink" id="kupu-linklibdrawer-button" title="internal link" i18n:attributes="title">&#160;</button>
+      <button type="button" class="kupu-exthyperlink" id="kupu-linkdrawer-button" title="external link" i18n:attributes="title">&#160;</button>
+      <button type="button" class="kupu-table" id="kupu-tabledrawer-button" title="table" i18n:attributes="title">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup" id="kupu-bg-remove">
+      <button type="button" class="kupu-removeimage invisible" id="kupu-removeimage-button" title="Remove image" i18n:attributes="title">&#160;</button>
+      <button type="button" class="kupu-removelink invisible" id="kupu-removelink-button" title="Remove link" i18n:attributes="title">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup" id="kupu-bg-undo">
+      <button type="button" class="kupu-undo" id="kupu-undo-button" title="undo: alt-z" i18n:attributes="title" accesskey="z">&#160;</button>
+      <button type="button" class="kupu-redo" id="kupu-redo-button" title="redo: alt-y" i18n:attributes="title" accesskey="y">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup kupu-spellchecker-span" id="kupu-spellchecker">
+      <button type="button" class="kupu-spellchecker" id="kupu-spellchecker-button" title="check spelling" i18n:attributes="title">&#160;</button>
+    </span>
+  
+    <span class="kupu-tb-buttongroup kupu-source-span" id="kupu-source">
+      <button type="button" class="kupu-source" id="kupu-source-button" title="edit HTML code" i18n:attributes="title" accesskey="h">&#160;</button>
+    </span>
+  
+    </span>
+  
+    <select id="kupu-ulstyles" class="kupu-ulstyles">
+      <option value="disc" i18n:translate="list-disc">&#9679;</option>
+      <option value="square" i18n:translate="list-square">&#9632;</option>
+      <option value="circle" i18n:translate="list-circle">&#9675;</option>
+      <option value="none" i18n:translate="list-nobullet">no bullet</option>
+    </select>
+    <select id="kupu-olstyles" class="kupu-olstyles">
+      <option value="decimal" i18n:translate="list-decimal">1</option>
+      <option value="upper-roman" i18n:translate="list-upperroman">I</option>
+      <option value="lower-roman" i18n:translate="list-lowerroman">i</option>
+      <option value="upper-alpha" i18n:translate="list-upperalpha">A</option>
+      <option value="lower-alpha" i18n:translate="list-loweralpha">a</option>
+    </select>
+  
+    
+    <div style="display:block;" class="kupu-librarydrawer-parent">
+
+    </div>
+  
+    <div id="kupu-linkdrawer" class="kupu-drawer kupu-linkdrawer">
+      <h1 i18n:translate="">External Link</h1>
+
+      <div id="kupu-linkdrawer-addlink" class="kupu-panels kupu-linkdrawer-addlink">
+        <table cellspacing="0">
+        <tr><td><div class="kupu-toolbox-label">
+          
+          <span i18n:translate="">
+            Link the highlighted text to this URL:
+          </span>
+        </div>
+
+        <input class="kupu-toolbox-st kupu-linkdrawer-input" type="text" onkeypress="return HandleDrawerEnter(event, 'linkdrawer-preview');"/>
+        </td>
+        <td class="kupu-preview-button">
+          <button class="kupu-dialog-button" type="button" id="linkdrawer-preview" onclick="drawertool.current_drawer.preview()" i18n:translate="">Preview</button>
+        </td></tr>
+        <tr><td colspan="2" align="center">
+        <iframe frameborder="1" scrolling="auto" width="440" height="198" class="kupu-linkdrawer-preview" src="kupublank.html">
+        </iframe>
+        </td></tr>
+        </table>
+
+        <div class="kupu-dialogbuttons">
+          <button class="kupu-dialog-button" type="button" onclick="drawertool.current_drawer.save()" i18n:translate="">Ok</button>
+          <button class="kupu-dialog-button" type="button" onclick="drawertool.closeDrawer()" i18n:translate="">Cancel</button>
+        </div>
+
+      </div>
+    </div>
+  
+    <div id="kupu-tabledrawer" class="kupu-drawer kupu-tabledrawer">
+    <h1 i18n:translate="tabledrawer_title">Table</h1>
+    <div class="kupu-panels">
+      <table width="300">
+        <tr class="kupu-panelsrow">
+          <td class="kupu-panel">
+            
+            <div class="kupu-tabledrawer-addtable">
+              <table>
+                <tr>
+                  <th i18n:translate="tabledrawer_class_label" class="kupu-toolbox-label">Table Class</th>
+                  <td>
+                    <select class="kupu-tabledrawer-addclasschooser">
+                      <option i18n:translate="" value="plain">Plain</option>
+                      <option i18n:translate="" value="listing">Listing</option>
+                      <option i18n:translate="" value="grid">Grid</option>
+                      <option i18n:translate="" value="data">Data</option>
+                    </select>
+                  </td>
+                </tr>
+                <tr>
+                  <th i18n:translate="tabledrawer_rows_label" class="kupu-toolbox-label">Rows</th>
+                  <td><input type="text" class="kupu-tabledrawer-newrows" onkeypress="return HandleDrawerEnter(event);"/></td>
+                </tr>
+                <tr>
+                  <th i18n:translate="tabledrawer_columns_label" class="kupu-toolbox-label">Columns</th>
+                  <td><input type="text" class="kupu-tabledrawer-newcols" onkeypress="return HandleDrawerEnter(event);"/></td>
+                </tr>
+                <tr>
+                  <th class="kupu-toolbox-label"> </th>
+                  <td>
+                    <label><input class="kupu-tabledrawer-makeheader" type="checkbox" onkeypress="return HandleDrawerEnter(event);"/>
+                    <span i18n:translate="tabledrawer_headings_label">Create Headings</span></label>
+                  </td>
+                </tr>
+                <tr>
+                  <th class="kupu-toolbox-label"> </th>
+                  <td>
+                      <button class="kupu-dialog-button" type="button" i18n:translate="tabledrawer_add_table_button" onclick="drawertool.current_drawer.createTable()">Add Table</button>
+                      <button class="kupu-dialog-button" type="button" i18n:translate="tabledrawer_fix_tables_button" onclick="drawertool.current_drawer.fixAllTables()">Fix All Tables</button>
+                  </td>
+                </tr>
+              </table>
+            </div>
+
+            
+            <div class="kupu-tabledrawer-edittable">
+              <table>
+                <tr>
+                  <th class="kupu-toolbox-label" i18n:translate="tabledrawer_class_label">Table Class</th>
+                  <td>
+                    <select class="kupu-tabledrawer-editclasschooser" onchange="drawertool.current_drawer.setTableClass(this.options[this.selectedIndex].value)">
+                      <option i18n:translate="" value="plain">Plain</option>
+                      <option i18n:translate="" value="listing">Listing</option>
+                      <option i18n:translate="" value="grid">Grid</option>
+                      <option i18n:translate="" value="data">Data</option>
+                    </select>
+                  </td>
+                </tr>
+                <tr>
+                  <th class="kupu-toolbox-label" i18n:translate="tabledrawer_alignment_label">Current column alignment</th>
+                  <td>
+                    <select id="kupu-tabledrawer-alignchooser" class="kupu-tabledrawer-alignchooser" onchange="drawertool.current_drawer.tool.setColumnAlign(this.options[this.selectedIndex].value)">
+                      <option i18n:translate="tabledrawer_left_option" value="left">Left</option>
+                      <option i18n:translate="tabledrawer_center_option" value="center">Center</option>
+                      <option i18n:translate="tabledrawer_right_option" value="right">Right</option>
+                      </select>
+                  </td>
+                </tr>
+                <tr>
+                  <th class="kupu-toolbox-label" i18n:translate="tabledrawer_column_label">Column</th>
+                  <td>
+                    <button class="kupu-dialog-button" type="button" i18n:translate="tabledrawer_add_button" onclick="drawertool.current_drawer.addTableColumn()">Add</button>
+                    <button class="kupu-dialog-button" type="button" i18n:translate="tabledrawer_remove_button" onclick="drawertool.current_drawer.delTableColumn()">Remove</button>
+                  </td>
+                </tr>
+                <tr>
+                  <th class="kupu-toolbox-label" i18n:translate="tabledrawer_row_label">Row</th>
+                  <td>
+                    <button class="kupu-dialog-button" type="button" i18n:translate="tabledrawer_add_button" onclick="drawertool.current_drawer.addTableRow()">Add</button> 
+                    <button class="kupu-dialog-button" type="button" i18n:translate="tabledrawer_remove_button" onclick="drawertool.current_drawer.delTableRow()">Remove</button>
+                  </td>
+                </tr>
+                <tr>
+                  <th class="kupu-toolbox-label" i18n:translate="tabledrawer_fix_table_label">Fix Table</th>
+                  <td>
+                    <button class="kupu-dialog-button" type="button" i18n:translate="tabledrawer_fix_button" onclick="drawertool.current_drawer.fixTable()">Fix</button> 
+                  </td>
+                </tr>
+              </table>
+            </div>
+          </td>
+        </tr>
+      </table>
+      <div class="kupu-dialogbuttons">
+        <button class="kupu-dialog-button" type="button" onfocus="window.status='focus';" onmousedown="window.status ='onmousedown';" i18n:translate="tabledrawer_close_button" onclick="drawertool.closeDrawer(this)">Close</button>
+      </div>
+    </div>
+    </div>
+
+  
+  
+    </div>
+  
+    <div class="kupu-toolboxes" id="kupu-toolboxes">
+      
+    <div class="kupu-toolbox" id="kupu-toolbox-properties">
+      <h1 class="kupu-toolbox-heading" i18n:translate="">Properties</h1>
+
+      <div>
+        <div class="kupu-toolbox-label" i18n:translate="">Title:</div>
+        <input class="wide" id="kupu-properties-title"/>
+        <div class="kupu-toolbox-label" i18n:translate="">Description:</div>
+        <textarea class="wide" id="kupu-properties-description"> </textarea>
+      </div>
+    </div>
+  
+    <div class="kupu-toolbox" id="kupu-toolbox-links">
+      <h1 class="kupu-toolbox-heading" i18n:translate="">Links</h1>
+
+      <div id="kupu-toolbox-addlink">
+        <div class="kupu-toolbox-label">
+          
+          <span i18n:translate="">
+            Link the highlighted text to this URL:
+          </span>
+        </div>
+
+        <input id="kupu-link-input" class="wide" type="text"/>
+        <div class="kupu-toolbox-buttons">
+          <button type="button" id="kupu-link-button" class="kupu-toolbox-action" i18n:translate="">Make Link</button>
+        </div>
+      </div>
+    </div>
+  
+    <div class="kupu-toolbox" id="kupu-toolbox-images">
+      <h1 class="kupu-toolbox-heading" i18n:translate="">Images</h1>
+
+      <div>
+        <div class="kupu-toolbox-label">
+          <span i18n:translate="">Image class:</span>
+        </div>
+        <select class="wide" id="kupu-image-float-select">
+          <option value="image-inline" i18n:translate="">Inline</option>
+          <option value="image-left" i18n:translate="">Left</option>
+          <option value="image-right" i18n:translate="">Right</option>
+        </select>
+
+        <div class="kupu-toolbox-label">
+          <span i18n:translate="">Insert image at the following URL:</span>
+        </div>
+        <input id="kupu-image-input" value="kupuimages/kupu_icon.gif" class="wide" type="text"/>
+
+        <div class="kupu-toolbox-buttons">
+          <button type="button" id="kupu-image-addbutton" class="kupu-toolbox-action" i18n:translate="">Insert Image</button>
+        </div>
+      </div>
+    </div>
+  
+    <div class="kupu-toolbox" id="kupu-toolbox-tables">
+      <h1 class="kupu-toolbox-heading" i18n:translate="">Tables</h1>
+
+      <div>
+      <div class="kupu-toolbox-label">
+        <span i18n:translate="">Table Class:</span>
+        <select class="wide" id="kupu-table-classchooser"> </select>
+      </div>
+
+      <div id="kupu-toolbox-addtable" class="kupu-toolbox-addtable">
+        <div class="kupu-toolbox-label" i18n:translate="">Rows:</div>
+        <input class="wide" type="text" id="kupu-table-newrows"/>
+
+        <div class="kupu-toolbox-label" i18n:translate="">Columns:</div>
+        <input class="wide" type="text" id="kupu-table-newcols"/>
+
+        <div class="kupu-toolbox-label">
+          <span i18n:translate="">Headings:</span>
+          <input name="kupu-table-makeheader" id="kupu-table-makeheader" type="checkbox"/>
+          <label for="kupu-table-makeheader" i18n:translate="">Create</label>
+        </div>
+
+        <div class="kupu-toolbox-buttons">
+          <button type="button" id="kupu-table-fixall-button" i18n:translate="">Fix Table</button> 
+          <button type="button" id="kupu-table-addtable-button" i18n:translate="">Add Table</button> 
+        </div>
+
+      </div>
+
+      <div id="kupu-toolbox-edittable" class="kupu-toolbox-edittable">
+      
+          <div class="kupu-toolbox-label">
+            <span i18n:translate="">Col Align:</span>
+            <select class="wide" id="kupu-table-alignchooser">
+              <option value="left" i18n:translate="">Left</option>
+              <option value="center" i18n:translate="">Center</option>
+              <option value="right" i18n:translate="">Right</option>
+            </select>
+          </div>
+      
+          <div class="kupu-toolbox-buttons">
+            <br/>
+            <button type="button" id="kupu-table-addcolumn-button" i18n:translate="">Add Column</button>
+            <button type="button" id="kupu-table-delcolumn-button" i18n:translate="">Remove Column</button>
+            
+            <br/>
+            <button type="button" id="kupu-table-addrow-button" i18n:translate="">Add Row</button>
+            <button type="button" id="kupu-table-delrow-button" i18n:translate="">Remove Row</button>
+          
+            <button type="button" id="kupu-table-fix-button" i18n:translate="">Fix</button>
+          </div>
+          
+      </div>
+      </div>
+
+    </div>
+  
+    <div class="kupu-toolbox" id="kupu-toolbox-cleanupexpressions">
+      <h1 class="kupu-toolbox-heading" i18n:translate="">Cleanup expressions</h1>
+
+      <div>
+        <div class="kupu-toolbox-label">
+          <span i18n:translate="">
+            Select a cleanup action:
+          </span>
+        </div>
+
+        <select id="kupucleanupexpressionselect" class="kupu-toolbox-st">
+        </select>
+        <div style="text-align: center">
+          <button type="button" id="kupucleanupexpressionbutton" class="kupu-toolbox-action">Perform action</button>
+        </div>
+      </div>
+    </div>
+  
+    <div class="kupu-toolbox" id="kupu-toolbox-debug">
+      <h1 class="kupu-toolbox-heading" i18n:translate="">Debug Log</h1>
+      <div id="kupu-toolbox-debuglog" class="kupu-toolbox-label">
+      </div>
+    </div>
+  
+    </div>
+  
+    <table id="kupu-colorchooser" cellpadding="0" cellspacing="0" style="position: fixed; border-style: solid; border-color: black; border-width: 1px;">
+    </table>
+  
+    <div class="kupu-editorframe">
+      <iframe id="kupu-editor" class="kupu-editor-iframe" frameborder="0" src="fulldoc.html" scrolling="auto">
+      </iframe>
+      <textarea class="kupu-editor-textarea" id="kupu-editor-textarea"> </textarea>
+    </div>
+  
+    </div>
+  
+      </form>
+    </body>
+  
+
+</html>
+