[kupu-checkins] r48472 - in kupu/branch/kupu-1.4: . common common/kupudrawers default doc plone plone/kupu_plone_layer plone/kupu_references plone/profiles/default plone/tests plone/tests/output

duncan at codespeak.net duncan at codespeak.net
Fri Nov 9 15:08:39 CET 2007


Author: duncan
Date: Fri Nov  9 15:08:37 2007
New Revision: 48472

Modified:
   kupu/branch/kupu-1.4/common/kupubasetools.js
   kupu/branch/kupu-1.4/common/kupucontentfilters.js
   kupu/branch/kupu-1.4/common/kupudrawers.js
   kupu/branch/kupu-1.4/common/kupudrawers/drawer.xsl
   kupu/branch/kupu-1.4/common/kupudrawerstyles.css
   kupu/branch/kupu-1.4/common/kupueditor.js
   kupu/branch/kupu-1.4/common/kupuhelpers.js
   kupu/branch/kupu-1.4/common/sarissa.js
   kupu/branch/kupu-1.4/default/drawers.kupu
   kupu/branch/kupu-1.4/default/toolbar.kupu
   kupu/branch/kupu-1.4/doc/CHANGES.txt
   kupu/branch/kupu-1.4/doc/PLONE2.txt
   kupu/branch/kupu-1.4/i18n.bat
   kupu/branch/kupu-1.4/plone/body.kupu
   kupu/branch/kupu-1.4/plone/helpers.py
   kupu/branch/kupu-1.4/plone/html2captioned.py
   kupu/branch/kupu-1.4/plone/kupu_config.pt
   kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_captioned_image.pt
   kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_wysiwyg_support.html
   kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuplone.css.dtml
   kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuploneeditor.js
   kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupusearch.xml.pt
   kupu/branch/kupu-1.4/plone/kupu_plone_layer/sample-kupu-customisation-policy.py
   kupu/branch/kupu-1.4/plone/kupu_references/referencebrowser.pt
   kupu/branch/kupu-1.4/plone/plonedrawers.py
   kupu/branch/kupu-1.4/plone/plonelibrarytool.py
   kupu/branch/kupu-1.4/plone/profiles/default/kupu.xml
   kupu/branch/kupu-1.4/plone/save.kupu
   kupu/branch/kupu-1.4/plone/tests/output/linked.out
   kupu/branch/kupu-1.4/plone/tests/output/notquoted.out
   kupu/branch/kupu-1.4/plone/tests/output/simple.out
   kupu/branch/kupu-1.4/plone/tests/test_html2captioned.py
   kupu/branch/kupu-1.4/plone/util.py
   kupu/branch/kupu-1.4/plone/wire.kupu
   kupu/branch/kupu-1.4/plone/z3interfaces.py
   kupu/branch/kupu-1.4/plone/zmi_docs.pt
   kupu/branch/kupu-1.4/version.txt
Log:
Bring 1.4 branch up to date with 1.4.4 trunk

Modified: kupu/branch/kupu-1.4/common/kupubasetools.js
==============================================================================
--- kupu/branch/kupu-1.4/common/kupubasetools.js	(original)
+++ kupu/branch/kupu-1.4/common/kupubasetools.js	Fri Nov  9 15:08:37 2007
@@ -677,7 +677,7 @@
     this._removeStyle = function() {
         function needbreak(e) {
             if (isblock && e) {
-                if (blocktagre.test(e.nodeName) || e.nodeName=='BR') return;
+                if (blocktagre.test(e.nodeName) || /^br$/i.test(e.nodeName)) return;
                 parent.insertBefore(ed.newElement('br'), n);
             }
         }
@@ -1039,14 +1039,15 @@
         linkWindow.focus();
     };
 
-    this.updateLink = function (linkel, url, type, name, target, title, className) {
+    this.updateLink = function (linkel, url, type, name, target, title, className, bForce) {
         if (type && type == 'anchor') {
             linkel.removeAttribute('href');
             linkel.setAttribute('name', name);
         } else {
             linkel.href = url;
-            if (linkel.innerHTML == "") {
+            if (linkel.innerHTML == "" || (bForce && linkel.innerHTML==url)) {
                 var doc = this.editor.getInnerDocument();
+                while (linkel.firstChild) { linkel.removeChild(linkel.firstChild); };
                 linkel.appendChild(doc.createTextNode(title || url));
             }
             if (title) {
@@ -1069,13 +1070,13 @@
         };
     };
 
-    this.formatSelectedLink = function(url, type, name, target, title, className) {
+    this.formatSelectedLink = function(url, type, name, target, title, className, bForce) {
         var currnode = this.editor.getSelectedNode();
 
         // selection inside link
         var linkel = this.editor.getNearestParentOfType(currnode, 'A');
         if (linkel) {
-            this.updateLink(linkel, url, type, name, target, title, className);
+            this.updateLink(linkel, url, type, name, target, title, className, bForce);
             return true;
         }
 
@@ -1088,7 +1089,7 @@
         for (var i = 0; i < linkelements.length; i++) {
             linkel = linkelements[i];
             if (selection.containsNode(linkel)) {
-                this.updateLink(linkel, url, type, name, target, title, className);
+                this.updateLink(linkel, url, type, name, target, title, className, bForce);
                 containsLink = true;
             }
         };
@@ -1116,7 +1117,7 @@
         if (!this.formatSelectedLink(url, type, name, target, title, className)) {
             // No links inside or outside.
             this.editor.execCommand("CreateLink", url);
-            if (!this.formatSelectedLink(url, type, name, target, title, className)) {
+            if (!this.formatSelectedLink(url, type, name, target, title, className, true)) {
                 // Insert link with no text selected, insert the title
                 // or URI instead.
                 var doc = this.editor.getInnerDocument();
@@ -1711,8 +1712,7 @@
         for (var i=0; i < currtable.childNodes.length; i++) {
             var currtbody = currtable.childNodes[i];
             if (currtbody.nodeType != 1 || 
-                    (currtbody.nodeName.toUpperCase() != "THEAD" &&
-                        currtbody.nodeName.toUpperCase() != "TBODY")) {
+                    (/^thead|tbody$/i.test(currtbody.nodeName))) {
                 continue;
             }
             for (var j=0; j < currtbody.childNodes.length; j++) {
@@ -1808,7 +1808,7 @@
 
     this._isBodyRow = function(row) {
         for (var node = row.firstChild; node; node=node.nextSibling) {
-            if (/TD/.test(node.nodeName)) {
+            if (/^td$/i.test(node.nodeName)) {
                 return true;
             }
         }
@@ -1819,7 +1819,7 @@
         // Remove formatted div or p from a cell
         var nxt, n;
         for (var node = el.firstChild; node;) {
-            if (/^DIV|P$/i.test(node.nodeName)) {
+            if (/^div|p$/i.test(node.nodeName)) {
                 for (var n = node.firstChild; n;) {
                     var nxt = n.nextSibling;
                     el.insertBefore(n, node); // Move nodes out of div
@@ -1857,7 +1857,7 @@
             var row = rows[i];
             var currnumcols = 0;
             for (var node = row.firstChild; node; node=node.nextSibling) {
-                if (/td|th/i.test(node.nodeName)) {
+                if (/^(td|th)$/i.test(node.nodeName)) {
                     currnumcols += parseInt(node.getAttribute('colSpan') || '1');
                 };
             };
@@ -1879,7 +1879,7 @@
             }
             for (var node = row.firstChild; node;) {
                 var nxt = node.nextSibling;
-                if (/TD|TH/.test(node.nodeName)) {
+                if (/^(td|th)$/i.test(node.nodeName)) {
                     this._cleanCell(node);
                     newrow.appendChild(node);
                 };
@@ -1936,13 +1936,13 @@
 
         var hrows = [], brows = [], frows = [];
         for (var node = table.firstChild; node; node = node.nextSibling) {
-            var nodeName = node.nodeName;
-            if (/TR/.test(node.nodeName)) {
+            var nodeName = node.nodeName.toLowerCase();
+            if (/tr/i.test(node.nodeName)) {
                 brows.push(node);
-            } else if (/THEAD|TBODY|TFOOT/.test(node.nodeName)) {
-                var rows = nodeName=='THEAD' ? hrows : nodeName=='TFOOT' ? frows : brows;
+            } else if (/thead|tbody|tfoot/i.test(node.nodeName)) {
+                var rows = nodeName=='thead' ? hrows : nodeName=='tfoot' ? frows : brows;
                 for (var inode = node.firstChild; inode; inode = inode.nextSibling) {
-                    if (/TR/.test(inode.nodeName)) {
+                    if (/tr/i.test(inode.nodeName)) {
                         rows.push(inode);
                     };
                 };
@@ -2308,11 +2308,12 @@
         var path = '';
         var url = null; // for links we want to display the url too
         var currnode = selNode;
-        while (currnode != null && currnode.nodeName != '#document') {
-            if (currnode.nodeName.toLowerCase() == 'a') {
+        var nn;
+        while (currnode != null && (nn=currnode.nodeName.toLowerCase()) != '#document') {
+            if (nn=='a') {
                 url = currnode.getAttribute('href');
             };
-            path = '/' + currnode.nodeName.toLowerCase() + path;
+            path = '/' + nn + path;
             currnode = currnode.parentNode;
         }
         

Modified: kupu/branch/kupu-1.4/common/kupucontentfilters.js
==============================================================================
--- kupu/branch/kupu-1.4/common/kupucontentfilters.js	(original)
+++ kupu/branch/kupu-1.4/common/kupucontentfilters.js	Fri Nov  9 15:08:37 2007
@@ -724,7 +724,7 @@
                 var kid = kids[i];
 
                 if (kid.parentNode !== htmlnode) {
-                    if (kid.tagName == 'BODY') {
+                    if (kid.tagName.toLowerCase()=='body') {
                         if (nodename != 'html') continue;
                     } else if (kid.parentNode.tagName === htmlnode.tagName) {
                         continue; // IE bug: nodes appear multiple places

Modified: kupu/branch/kupu-1.4/common/kupudrawers.js
==============================================================================
--- kupu/branch/kupu-1.4/common/kupudrawers.js	(original)
+++ kupu/branch/kupu-1.4/common/kupudrawers.js	Fri Nov  9 15:08:37 2007
@@ -155,9 +155,9 @@
     event = event || window.event;
     var target = event.currentTarget || event.srcElement;
     var el = target;
-    while (el.nodeName != 'LI') { el = el.parentNode; };
+    while (!/^li$/i.test(el.nodeName)) { el = el.parentNode; };
     var thistab = el;
-    while (el.nodeName != 'UL') { el = el.parentNode; };
+    while (!/^ul$/i.test(el.nodeName)) { el = el.parentNode; };
     var tabs = el.getElementsByTagName('li');
     for (var i = 0; i < tabs.length; i++) {
         var el = tabs[i];
@@ -243,21 +243,19 @@
 
 proto.anchorText = function(a) {
     // Text inside anchor, or immediate sibling block tag, or parent block. 
-    var blocktag = /^DIV|P|BODY|TD|H.$/;
+    var blocktag = /^div|p|body|td|h.$/i;
     var txt = '';
     var prefix = '#' + a.name;
-findlabel:
+
     for (var node = a; node && !txt; node=node.parentNode) {
         var txt = node.textContent || node.innerText || '';
         if (txt || blocktag.test(node.nodeName)) {
             break;
         }
 
-        for (var sibling = node.nextSibling; sibling; sibling = sibling.nextSibling) {
-            if (sibling.nodeName=='#text') {
+        for (var sibling = node.nextSibling; sibling && !txt; sibling = sibling.nextSibling) {
+            if (sibling.nodeName.toLowerCase()=='#text') {
                 txt = sibling.data.strip();
-            } else if (blocktag.test(sibling.nodeName)) {
-                break findlabel;
             } else {
                 txt += sibling.textContent || sibling.innerText ||'';
             };
@@ -371,7 +369,7 @@
         this.editor.resumeEditing();
         if (this.getMode()) {
             var url = input.value;
-            this.tool.createLink(url, null, null, this.target, 'external-link');
+            this.tool.createLink(url, null, null, this.target, null, 'external-link');
             input.value = '';
         } else {
             // Import the html
@@ -442,7 +440,7 @@
             var there = preview.contentWindow.location.href;
         } catch(e) { return; }
 
-        if (here != there && !(/^about:/.test(there))) {
+        if (there && here != there && !(/^about:/.test(there))) {
             input.value = there;
         }
         this.showAnchors(currentAnchor());
@@ -928,8 +926,10 @@
 
         if (this.editor.getBrowserName() == 'IE') {
             newitemsnode = newitemsnode.cloneNode(true);
+            if (newbc) newbc = newbc.cloneNode(true);
         } else {
             newitemsnode = this.xmldata.importNode(newitemsnode, true);
+            if (newbc) newbc = this.xmldata.importNode(newbc, true);
         }
         if (newbc) {
             if (bcnode) {
@@ -1299,7 +1299,7 @@
         if (this.editor.getBrowserName() == 'IE') {
             resultlib = resultlib.cloneNode(true);
         } else {
-            this.xmldata.importNode(resultlib, true);
+            resultlib = this.xmldata.importNode(resultlib, true);
         }
         var libraries = this.xmldata.selectSingleNode("/libraries");
         libraries.appendChild(resultlib);
@@ -1400,10 +1400,20 @@
     }
 
     this.createContent = function() {
+        function getSel(sel, p, t) {
+            var nodes = p.getElementsByTagName(t);
+            for (var i = 0; i < nodes.length; i++) {
+                if (sel.containsNode(nodes[i])) {
+                    return nodes[i];
+                };
+            };
+        }
         var ed = this.editor;
+        var sel = ed.getSelection();
         var currnode = ed.getSelectedNode();
-        var currimg = ed.getNearestParentOfType(currnode, 'OBJECT') || ed.getNearestParentOfType(currnode, 'IMG');
-        this.selectedSrc = currimg.data||currimg.src||null;
+        var currimg = ed.getNearestParentOfType(currnode, 'OBJECT') || ed.getNearestParentOfType(currnode, 'IMG') ||
+                      getSel(sel, currnode, 'object') || getSel(sel, currnode, 'img');
+        this.selectedSrc = currimg?(currimg.data||currimg.src||null):null;
         this.options = {};
         if (currimg) {
             ed.getSelection().selectNodeContents(currimg);
@@ -1711,7 +1721,7 @@
                     if (level==0) {
                         toc.appendChild(li);
                     } else {
-                        if (!toc.lastChild || toc.lastChild.nodeName != 'ul') {
+                        if (!toc.lastChild || toc.lastChild.nodeName.toLowerCase() != 'ul') {
                             toc.appendChild(ed.newElement('ul'));
                         }
                         toc.lastChild.appendChild(li);
@@ -1735,10 +1745,10 @@
                 };
             }
             var node = ed.getSelection().parentElement();
-            if (node.nodeName == 'BODY') {
+            if (node.nodeName.toLowerCase() == 'body') {
                 node.insertBefore(toc, node.firstChild);
             } else {
-                while (node.parentNode.nodeName != 'BODY') {
+                while (node.parentNode.nodeName.toLowerCase() != 'body') {
                     node = node.parentNode;
                 }
                 node.parentNode.insertBefore(toc, node);

Modified: kupu/branch/kupu-1.4/common/kupudrawers/drawer.xsl
==============================================================================
--- kupu/branch/kupu-1.4/common/kupudrawers/drawer.xsl	(original)
+++ kupu/branch/kupu-1.4/common/kupudrawers/drawer.xsl	Fri Nov  9 15:08:37 2007
@@ -390,9 +390,10 @@
              </xsl:choose>
           </xsl:if>
           <xsl:if test="sizes">
-             <label class="kupu-detail" i18n:translate="imagedrawer_size"
-                    for="image-size-selector">Size
-                <span class="image-dimensions">
+             <label class="kupu-detail"
+                    for="image-size-selector"><span
+                    i18n:translate="imagedrawer_size_2">Size</span>
+                <span class="image-dimensions" i18n:translate="imagedrawer_size">
                    (<span i18n:name="width"><xsl:value-of select="width"/></span>
                    by
                    <span i18n:name="height"><xsl:value-of select="height"/></span>)

Modified: kupu/branch/kupu-1.4/common/kupudrawerstyles.css
==============================================================================
--- kupu/branch/kupu-1.4/common/kupudrawerstyles.css	(original)
+++ kupu/branch/kupu-1.4/common/kupudrawerstyles.css	Fri Nov  9 15:08:37 2007
@@ -275,13 +275,13 @@
    white-space: nowrap;
 }
 
-.kupu-tabs { border-bottom: 1px solid; margin: 0; padding: 0.5em 0 0 1.5em; }
+ul.kupu-tabs { border-bottom: 1px solid; margin: 0; padding: 0.5em 0.5em 1px 1.5em; }
 .kupu-tabs li {
   display: inline; padding: 2px; border: 1px solid; margin: 0 5px 0 0;
 }
 .kupu-tabs a { text-decoration: none; }
 .kupu-tabs li.selected { background: white; border-bottom: none !IMPORTANT; padding-bottom: 3px;}
-table.kupu-tabbed { border-spacing: 0;}
+.kupu-panels table.kupu-tabbed { border:none; border-spacing: 0;}
 
 .kupu-linkdrawer-addlink .kupu-embed,
 .kupu-linkdrawer-embed .kupu-addlink { display: none; }
@@ -299,6 +299,9 @@
 .kupu-ins-bm .hide-ins-bm, .kupu-anchor .hide-anchor, .kupu-toc .hide-toc {
   display: none;
 }
+.kupu-ins-bm .invis-ins-bm, .kupu-anchor .invis-anchor, .kupu-toc .invis-toc {
+        visibility: hidden; /* Hide controls without changing surrounding layout */
+}
 
 .image-dimensions {
   display: none;
@@ -318,6 +321,10 @@
 .kupu-bm-level1 SPAN { padding-left: 2em; }
 /* Anchor drawer */
 
+.kupu-bm-help { min-height: 2.5em; }
+.kupu-bm-heading { line-height: 2em; border-bottom: 1px solid; }
+.kupu-bm-tablestyle, .kupu-bm-numbering { float:right; padding-left: 0.5em; }
+
 .kupu-drawer label {
   font-weight: normal;
   vertical-align:middle;

Modified: kupu/branch/kupu-1.4/common/kupueditor.js
==============================================================================
--- kupu/branch/kupu-1.4/common/kupueditor.js	(original)
+++ kupu/branch/kupu-1.4/common/kupueditor.js	Fri Nov  9 15:08:37 2007
@@ -95,6 +95,7 @@
     
     this._designModeSetAttempts = 0;
     this._initialized = false;
+    this._wantDesignMode = false;
 
     // some properties to save the selection, required for IE to remember 
     // where in the iframe the selection was
@@ -506,43 +507,48 @@
 
     this._initializeEventHandlers = function() {
         /* attache the event handlers to the iframe */
+        var win = this.getDocument().getWindow();
+        var idoc = this.getInnerDocument();
+        // Set design mode on resize event:
+        this._addEventHandler(win, 'resize', this._resizeHandler, this);
         // 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._addEventHandler(idoc, "click", this.updateStateHandler, this);
+        this._addEventHandler(idoc, "dblclick", this.updateStateHandler, this);
+        this._addEventHandler(idoc, "keyup", this.updateStateHandler, this);
+        this._addEventHandler(idoc, "keyup", function() {this.content_changed = true;}, this);
+        this._addEventHandler(idoc, "mouseup", this.updateStateHandler, this);
         if (this.getBrowserName() == "IE") {
-            this._addEventHandler(this.getInnerDocument(), "selectionchange", this.onSelectionChange, this);
+            this._addEventHandler(idoc, "selectionchange", this.onSelectionChange, this);
         }
     };
 
+    this._resizeHandler = function() {
+        // Use the resize event to trigger setting design mode
+        if (this._wantDesignMode) {
+            this._setDesignModeWhenReady();
+        }
+    }
     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;
-        };
+        /* Try to set design mode, but if we fail then just wait for a
+         * resize event.
+         */
         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) {
+            this._wantDesignMode = false;
             // provide an 'afterInit' method on KupuEditor.prototype
             // for additional bootstrapping (after editor init)
             if (this.afterInit) {
                 this.afterInit();
             };
-        };
+        } else {
+            this._wantDesignMode = true; // Enable the resize trigger
+        }
     };
 
     this._setDesignMode = function() {
@@ -559,7 +565,7 @@
         if (this._isDocumentSelected()) {
             var cursel = this.getInnerDocument().selection;
             var currange = cursel.createRange();
-            if (cursel.type=="Control" && currange.item(0).nodeName=="BODY") {
+            if (cursel.type=="Control" && currange.item(0).nodeName.toLowerCase()=="body") {
                 /* This happens when you try to active an embedded
                  * object */
                 this._restoreSelection(true);

Modified: kupu/branch/kupu-1.4/common/kupuhelpers.js
==============================================================================
--- kupu/branch/kupu-1.4/common/kupuhelpers.js	(original)
+++ kupu/branch/kupu-1.4/common/kupuhelpers.js	Fri Nov  9 15:08:37 2007
@@ -460,13 +460,27 @@
 function MozillaSelection(document) {
     this.document = document;
     this.selection = document.getWindow().getSelection();
-    
+
+    this._createRange = function() {
+        return this.document.getDocument().createRange();
+    }
     this.selectNodeContents = function(node) {
         if (node && node.parentNode) {
             /* select the contents of a node */
-            this.selection.removeAllRanges();
-            this.selection.selectAllChildren(node);
-        }
+            var sel = this.selection;
+            sel.removeAllRanges();
+            if (sel.selectAllChildren) {
+                sel.selectAllChildren(node);
+            } else {
+                var range = this._createRange();
+                try {
+                    range.selectNode(node);
+                } catch (e) {
+                    range.selectNodeContents(node);
+                };
+                sel.addRange(range);
+            };
+        };
     };
 
     this.collapse = function(collapseToEnd) {
@@ -504,7 +518,7 @@
         var pos = range.startOffset;
 
         // make a new range for the new selection
-        var range = this.document.getDocument().createRange();
+        var range = this._createRange();
 
         if (container.nodeType == 3 && node.nodeType == 3) {
             // if we insert text in a textnode, do optimized insertion
@@ -616,9 +630,9 @@
         var aoffset = this.selection.anchorOffset;
         var onode = this.selection.focusNode;
         var ooffset = this.selection.focusOffset;
-        var arange = this.document.getDocument().createRange();
+        var arange = this._createRange();
         arange.setStart(anode, aoffset);
-        var orange = this.document.getDocument().createRange();
+        var orange = this._createRange();
         orange.setStart(onode, ooffset);
         return arange.compareBoundaryPoints('START_TO_START', orange) <= 0 ? anode : onode;
     };
@@ -672,9 +686,9 @@
         var aoffset = this.selection.anchorOffset;
         var onode = this.selection.focusNode;
         var ooffset = this.selection.focusOffset;
-        var arange = this.document.getDocument().createRange();
+        var arange = this._createRange();
         arange.setStart(anode, aoffset);
-        var orange = this.document.getDocument().createRange();
+        var orange = this._createRange();
         orange.setStart(onode, ooffset);
         return arange.compareBoundaryPoints('START_TO_START', orange) > 0 ? anode : onode;
     };
@@ -774,8 +788,8 @@
                 {
                     var parent1 = parent;
                     var parent2 = null;
-                    var range1 = this.document.getDocument().createRange();
-                    var range2 = this.document.getDocument().createRange();
+                    var range1 = this._createRange();
+                    var range2 = this._createRange();
                 
                     var parent2 = this.parentElementOfRange(this.selection.getRangeAt(i));
 
@@ -796,7 +810,7 @@
                         //just one node, which we don't want; but since parent1
                         //and parent2 are different, their range is not just
                         //one node
-                        var coverRange = this.document.getDocument().createRange();
+                        var coverRange = this._createRange();
                         coverRange.setStartBefore(parent1);
                         coverRange.setEndAfter(parent2);
                         parent = coverRange.commonAncestorContainer;
@@ -806,7 +820,7 @@
                         //just one node, which we don't want; but since parent1
                         //and parent2 are different, their range is not just
                         //one node
-                        var coverRange = this.document.getDocument().createRange();
+                        var coverRange = this._createRange();
                         coverRange.setStartBefore(parent2);
                         coverRange.setEndAfter(parent1);
                         parent = coverRange.commonAncestorContainer;                    
@@ -961,7 +975,18 @@
     };
 
     this.containsNode = function(node) {
-        return this.selection.containsNode(node, true);
+        var sel = this.selection;
+        if (sel.containsNode) {
+            return sel.containsNode(node, true);
+        } else {
+            // kludge it for safari
+            for(var i = 0; i < sel.rangeCount; i++ ) {
+                if( sel.getRangeAt(i).containsNode(node) ) {
+                    return true;
+                }
+            };
+            return false;
+        }
     };
 
     this.toString = function() {
@@ -969,12 +994,16 @@
     };
 
     this.getRange = function() {
-        return this.selection.getRangeAt(0);
+        if (this.selection) {
+            return this.selection.getRangeAt(0);
+        }
     };
     this.restoreRange = function(range) {
         var selection = this.selection;
-        selection.removeAllRanges();
-        selection.addRange(range);
+        if (selection) {
+            selection.removeAllRanges();
+            selection.addRange(range);
+        }
     };
 
     //sample kindly snipped from Mozilla's wiki
@@ -987,6 +1016,8 @@
                 nodeRange.selectNodeContents(node);
             };
 
+            // selection end after node start and selection start
+            // before node end
             return this.compareBoundaryPoints(Range.END_TO_START, nodeRange) == -1 &&
                 this.compareBoundaryPoints(Range.START_TO_END, nodeRange) == 1;
         };
@@ -999,6 +1030,21 @@
         };
         return false;
     };
+    if( !Range.prototype.containsNode ){
+        Range.prototype.containsNode = function(node) {
+            var nodeRange = node.ownerDocument.createRange();
+            try {
+                nodeRange.selectNode(node);
+            } catch (e) {
+                nodeRange.selectNodeContents(node);
+            };
+
+            // selection start not after node start and selection end
+            // not before node end.
+            return this.compareBoundaryPoints(Range.START_TO_START, nodeRange) != -1 &&
+                    this.compareBoundaryPoints(Range.END_TO_END, nodeRange) != 1;
+        };
+    };
 };
 
 MozillaSelection.prototype = new BaseSelection;

Modified: kupu/branch/kupu-1.4/common/sarissa.js
==============================================================================
--- kupu/branch/kupu-1.4/common/sarissa.js	(original)
+++ kupu/branch/kupu-1.4/common/sarissa.js	Fri Nov  9 15:08:37 2007
@@ -5,8 +5,9 @@
  * Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs.
  * The library supports Gecko based browsers like Mozilla and Firefox,
  * Internet Explorer (5.5+ with MSXML3.0+), Konqueror, Safari and a little of Opera
- * @version @sarissa.version@
- * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net
+ * @version ${project.version}
+ * @author: @author: Copyright 2004-2007 Emmanouil Batsis, mailto: mbatsis at users full stop sourceforge full stop net
+ *
  * ====================================================================
  * Licence
  * ====================================================================
@@ -17,6 +18,7 @@
  * In case your copy of Sarissa does not include the license texts, you may find
  * them online in various formats at <a href="http://www.gnu.org">http://www.gnu.org</a> and 
  * <a href="http://www.apache.org">http://www.apache.org</a>.
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
  * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
  * WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE 
@@ -32,22 +34,37 @@
  * @constructor
  */
 function Sarissa(){};
+Sarissa.VERSION = "${project.version}";
 Sarissa.PARSED_OK = "Document contains no parsing errors";
 Sarissa.PARSED_EMPTY = "Document is empty";
 Sarissa.PARSED_UNKNOWN_ERROR = "Not well-formed or other error";
+Sarissa.IS_ENABLED_TRANSFORM_NODE = false;
 var _sarissa_iNsCounter = 0;
 var _SARISSA_IEPREFIX4XSLPARAM = "";
 var _SARISSA_HAS_DOM_IMPLEMENTATION = document.implementation && true;
 var _SARISSA_HAS_DOM_CREATE_DOCUMENT = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.createDocument;
 var _SARISSA_HAS_DOM_FEATURE = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.hasFeature;
 var _SARISSA_IS_MOZ = _SARISSA_HAS_DOM_CREATE_DOCUMENT && _SARISSA_HAS_DOM_FEATURE;
-var _SARISSA_IS_SAFARI = (navigator.userAgent && navigator.vendor && (navigator.userAgent.toLowerCase().indexOf("applewebkit") != -1 || navigator.vendor.indexOf("Apple") != -1));
+var _SARISSA_IS_SAFARI = navigator.userAgent.toLowerCase().indexOf("safari") != -1 || navigator.userAgent.toLowerCase().indexOf("konqueror") != -1;
+var _SARISSA_IS_SAFARI_OLD = _SARISSA_IS_SAFARI && parseInt((navigator.userAgent.match(/AppleWebKit\/(\d+)/)||{})[1]) < 420;
 var _SARISSA_IS_IE = document.all && window.ActiveXObject && navigator.userAgent.toLowerCase().indexOf("msie") > -1  && navigator.userAgent.toLowerCase().indexOf("opera") == -1;
+var _SARISSA_IS_OPERA = navigator.userAgent.toLowerCase().indexOf("opera") != -1;
 if(!window.Node || !Node.ELEMENT_NODE){
     Node = {ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5,  ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12};
 };
 
-if( typeof XMLDocument == "undefined" && typeof Document != "undefined"){ XMLDocument = Document; }
+//This breaks for(x in o) loops in the old Safari
+if(_SARISSA_IS_SAFARI_OLD){
+    HTMLHtmlElement = document.createElement("html").constructor;
+    Node = HTMLElement = {};
+    HTMLElement.prototype = HTMLHtmlElement.__proto__.__proto__;
+    HTMLDocument = Document = document.constructor;
+    var x = new DOMParser();
+    XMLDocument = x.constructor;
+    Element = x.parseFromString("<Single />", "text/xml").documentElement.constructor;
+    x = null;
+}
+if(typeof XMLDocument == "undefined" && typeof Document !="undefined"){ XMLDocument = Document; } 
 
 // IE initialization
 if(_SARISSA_IS_IE){
@@ -69,8 +86,7 @@
         var bFound = false, e;
         for(var i=0; i < idList.length && !bFound; i++){
             try{
-                var _ = new ActiveXObject(idList[i]);
-                _ = _;
+                var oDoc = new ActiveXObject(idList[i]);
                 var o2Store = idList[i];
                 bFound = true;
             }catch (objException){
@@ -96,7 +112,7 @@
          */
         XMLHttpRequest = function() {
             if(!_SARISSA_XMLHTTP_PROGID){
-                _SARISSA_XMLHTTP_PROGID = Sarissa.pickRecentProgID(["Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
+                _SARISSA_XMLHTTP_PROGID = Sarissa.pickRecentProgID(["Msxml2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
             };
             return new ActiveXObject(_SARISSA_XMLHTTP_PROGID);
         };
@@ -108,7 +124,7 @@
     // see non-IE version
     Sarissa.getDomDocument = function(sUri, sName){
         if(!_SARISSA_DOM_PROGID){
-            _SARISSA_DOM_PROGID = Sarissa.pickRecentProgID(["Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]);
+            _SARISSA_DOM_PROGID = Sarissa.pickRecentProgID(["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]);
         };
         var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
         // if a root tag name was provided, we need to load it in the DOM object
@@ -136,7 +152,7 @@
     // see non-IE version   
     Sarissa.getParseErrorText = function (oDoc) {
         var parseErrorText = Sarissa.PARSED_OK;
-        if(oDoc.parseError.errorCode != 0){
+        if(oDoc && oDoc.parseError && oDoc.parseError.errorCode && oDoc.parseError.errorCode != 0){
             parseErrorText = "XML Parsing Error: " + oDoc.parseError.reason + 
                 "\nLocation: " + oDoc.parseError.url + 
                 "\nLine Number " + oDoc.parseError.line + ", Column " + 
@@ -165,7 +181,7 @@
      */
     XSLTProcessor = function(){
         if(!_SARISSA_XSLTEMPLATE_PROGID){
-            _SARISSA_XSLTEMPLATE_PROGID = Sarissa.pickRecentProgID(["Msxml2.XSLTemplate.4.0", "MSXML2.XSLTemplate.3.0"]);
+            _SARISSA_XSLTEMPLATE_PROGID = Sarissa.pickRecentProgID(["Msxml2.XSLTemplate.6.0", "MSXML2.XSLTemplate.3.0"]);
         };
         this.template = new ActiveXObject(_SARISSA_XSLTEMPLATE_PROGID);
         this.processor = null;
@@ -177,14 +193,20 @@
      */
     XSLTProcessor.prototype.importStylesheet = function(xslDoc){
         if(!_SARISSA_THREADEDDOM_PROGID){
-            _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.4.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
-            _SARISSA_DOM_XMLWRITER = Sarissa.pickRecentProgID(["Msxml2.MXXMLWriter.4.0", "Msxml2.MXXMLWriter.3.0", "MSXML2.MXXMLWriter", "MSXML.MXXMLWriter", "Microsoft.XMLDOM"]);
+            _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.6.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
         };
         xslDoc.setProperty("SelectionLanguage", "XPath");
         xslDoc.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
         // convert stylesheet to free threaded
         var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID);
         // make included/imported stylesheets work if exist and xsl was originally loaded from url
+        try{
+            converted.resolveExternals = true; 
+            converted.setProperty("AllowDocumentFunction", true); 
+        }
+        catch(e){
+            // Ignore. "AllowDocumentFunction" is only supported in MSXML 3.0 SP4 and later.
+        }; 
         if(xslDoc.url && xslDoc.selectSingleNode("//xsl:*[local-name() = 'import' or local-name() = 'include']") != null){
             converted.async = false;
             converted.load(xslDoc.url);
@@ -196,7 +218,7 @@
         this.outputMethod = output ? output.getAttribute("method") : "html";
         this.template.stylesheet = converted;
         this.processor = this.template.createProcessor();
-        // (re)set default param values
+        // for getParameter and clearParameters
         this.paramsSet = [];
     };
 
@@ -207,30 +229,23 @@
      */
     XSLTProcessor.prototype.transformToDocument = function(sourceDoc){
         // fix for bug 1549749
-        if(_SARISSA_THREADEDDOM_PROGID == "MSXML2.FreeThreadedDOMDocument.3.0"){
+        if(_SARISSA_THREADEDDOM_PROGID){
             this.processor.input=sourceDoc;
-
             var outDoc=new ActiveXObject(_SARISSA_DOM_PROGID);
-
             this.processor.output=outDoc;
-
             this.processor.transform();
-
             return outDoc;
         }
         else{
+            if(!_SARISSA_DOM_XMLWRITER){
+                _SARISSA_DOM_XMLWRITER = Sarissa.pickRecentProgID(["Msxml2.MXXMLWriter.6.0", "Msxml2.MXXMLWriter.3.0", "MSXML2.MXXMLWriter", "MSXML.MXXMLWriter", "Microsoft.XMLDOM"]);
+            };
             this.processor.input = sourceDoc;
-
             var outDoc = new ActiveXObject(_SARISSA_DOM_XMLWRITER);
-
             this.processor.output = outDoc; 
-
             this.processor.transform();
-
             var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
-
             oDoc.loadXML(outDoc.output+"");
-
             return oDoc;
         };
     };
@@ -277,19 +292,22 @@
      * @argument name The parameter base name
      * @argument value The new parameter value
      */
-    XSLTProcessor.prototype.setParameter = function(nsURI, name, value){
-        /* nsURI is optional but cannot be null */
-        if(nsURI){
-            this.processor.addParameter(name, value, nsURI);
-        }else{
-            this.processor.addParameter(name, value);
-        };
-        /* update updated params for getParameter */
-        if(!this.paramsSet[""+nsURI]){
-            this.paramsSet[""+nsURI] = [];
-        };
-        this.paramsSet[""+nsURI][name] = value;
-    };
+     XSLTProcessor.prototype.setParameter = function(nsURI, name, value){
+         // make value a zero length string if null to allow clearing
+         value = value ? value : "";
+         // nsURI is optional but cannot be null
+         if(nsURI){
+             this.processor.addParameter(name, value, nsURI);
+         }else{
+             this.processor.addParameter(name, value);
+         };
+         // update updated params for getParameter
+         nsURI = "" + (nsURI || "");
+         if(!this.paramsSet[nsURI]){
+             this.paramsSet[nsURI] = new Array();
+         };
+         this.paramsSet[nsURI][name] = value;
+     };
     /**
      * Gets a parameter if previously set by setParameter. Returns null
      * otherwise
@@ -298,13 +316,28 @@
      * @return The parameter value if reviously set by setParameter, null otherwise
      */
     XSLTProcessor.prototype.getParameter = function(nsURI, name){
-        nsURI = nsURI || "";
+        nsURI = "" + (nsURI || "");
         if(this.paramsSet[nsURI] && this.paramsSet[nsURI][name]){
             return this.paramsSet[nsURI][name];
         }else{
             return null;
         };
     };
+    /**
+     * Clear parameters (set them to default values as defined in the stylesheet itself)
+     */
+    XSLTProcessor.prototype.clearParameters = function(){
+        for(var nsURI in this.paramsSet){
+            for(var name in this.paramsSet[nsURI]){
+                if(nsURI!=""){
+                    this.processor.addParameter(name, "", nsURI);
+                }else{
+                    this.processor.addParameter(name, "");
+                };
+            };
+        };
+        this.paramsSet = new Array();
+    };
 }else{ /* end IE initialization, try to deal with real browsers now ;-) */
     if(_SARISSA_HAS_DOM_CREATE_DOCUMENT){
         /**
@@ -333,8 +366,7 @@
         Sarissa.__setReadyState__ = function(oDoc, iReadyState){
             oDoc.readyState = iReadyState;
             oDoc.readystate = iReadyState;
-            if (oDoc.onreadystatechange != null &&
-                typeof oDoc.onreadystatechange == "function") {
+            if (oDoc.onreadystatechange != null && typeof oDoc.onreadystatechange == "function") {
                 oDoc.onreadystatechange();
             }
         };
@@ -361,11 +393,10 @@
             return oDoc;
         };
         if(window.XMLDocument){
-        
-        //if(window.XMLDocument) , now mainly for opera  
+            // do nothing
         }// TODO: check if the new document has content before trying to copynodes, check  for error handling in DOM 3 LS
-        else if(_SARISSA_HAS_DOM_FEATURE && (typeof Document != 'undefined') && !Document.prototype.load && document.implementation.hasFeature('LS', '3.0')){
-    		//Opera 9 may get the XPath branch which gives creates XMLDocument, therefore it doesn't reach here which is good
+        else if(_SARISSA_HAS_DOM_FEATURE && window.Document && !Document.prototype.load && document.implementation.hasFeature('LS', '3.0')){
+            //Opera 9 may get the XPath branch which gives creates XMLDocument, therefore it doesn't reach here which is good
             /**
             * <p>Factory method to obtain a new DOM Document object</p>
             * @argument sUri the namespace of the root node (if any)
@@ -421,27 +452,41 @@
     };
 };
 
-if(!document.importNode && _SARISSA_IS_IE){
+if((typeof(document.importNode) == "undefined") && _SARISSA_IS_IE){
     try{
         /**
-        * Implementation of importNode for the context window document in IE
+        * Implementation of importNode for the context window document in IE.
+        * If <code>oNode</code> is a TextNode, <code>bChildren</code> is ignored.
         * @param oNode the Node to import
         * @param bChildren whether to include the children of oNode
         * @returns the imported node for further use
         */
         document.importNode = function(oNode, bChildren){
+            var tmp;
             if (oNode.nodeName=='#text') {
-		return document.createTextNode(oNode.data);
-	    }
-	    var tmp = document.createElement("div");
-
-	    var pNode = (oNode.nodeName.toLowerCase()=='tbody')? oNode.parentNode: oNode;
-            if(bChildren){
-                tmp.innerHTML = pNode.xml ? pNode.xml : pNode.outerHTML;
-            }else{
-                tmp.innerHTML = pNode.xml ? pNode.cloneNode(false).xml : pNode.cloneNode(false).outerHTML;
+                return document.createTextElement(oNode.data);
+            }
+            else {
+                if(oNode.nodeName == "tbody" || oNode.nodeName == "tr"){
+                    tmp = document.createElement("table");
+                }
+                else if(oNode.nodeName == "td"){
+                    tmp = document.createElement("tr");
+                }
+                else if(oNode.nodeName == "option"){
+                    tmp = document.createElement("select");
+                }
+                else{
+                    tmp = document.createElement("div");
+                };
+                if(bChildren){
+                    tmp.innerHTML = oNode.xml ? oNode.xml : oNode.outerHTML;
+                }else{
+                    tmp.innerHTML = oNode.xml ? oNode.cloneNode(false).xml : oNode.cloneNode(false).outerHTML;
+                };
+                return tmp.getElementsByTagName("*")[0];
             };
-            return tmp.getElementsByTagName(oNode.nodeName.replace(/^[^:]*:/,''))[0];
+            
         };
     }catch(e){ };
 };
@@ -479,18 +524,18 @@
         var nodeType = node.nodeType;
         if(nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE){
             s += node.data;
-        } else if(deep == true &&
-            (nodeType == Node.ELEMENT_NODE ||
-            nodeType == Node.DOCUMENT_NODE ||
-            nodeType == Node.DOCUMENT_FRAGMENT_NODE)){
+        } else if(deep == true
+                    && (nodeType == Node.ELEMENT_NODE
+                        || nodeType == Node.DOCUMENT_NODE
+                        || nodeType == Node.DOCUMENT_FRAGMENT_NODE)){
             s += Sarissa.getText(node, true);
         };
     };
     return s;
 };
-if(!window.XMLSerializer &&
-   Sarissa.getDomDocument &&
-   Sarissa.getDomDocument("","foo", null).xml){
+if(!window.XMLSerializer 
+    && Sarissa.getDomDocument 
+    && Sarissa.getDomDocument("","foo", null).xml){
     /**
      * Utility class to serialize DOM Node objects to XML strings
      * @constructor
@@ -530,6 +575,10 @@
  * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is false
  */
 Sarissa.copyChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) {
+    if(_SARISSA_IS_SAFARI && nodeTo.nodeType == Node.DOCUMENT_NODE){ // SAFARI_OLD ??
+        nodeTo = nodeTo.documentElement; //Appearantly there's a bug in safari where you can't appendChild to a document node
+    }
+    
     if((!nodeFrom) || (!nodeTo)){
         throw "Both source and destination nodes must be provided";
     };
@@ -572,7 +621,7 @@
         };
     } else {
         var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument;
-        if(ownerDoc.importNode) {
+        if(typeof(ownerDoc.importNode) != "undefined") {
            for(var i=0;i < nodes.length;i++) {
                nodeTo.appendChild(ownerDoc.importNode(nodes[i], true));
            };
@@ -586,20 +635,19 @@
 };
 
 /** 
- * <p>Serialize any object to an XML string. All properties are serialized using the property name
+ * <p>Serialize any <strong>non</strong> DOM object to an XML string. All properties are serialized using the property name
  * as the XML element name. Array elements are rendered as <code>array-item</code> elements, 
  * using their index/key as the value of the <code>key</code> attribute.</p>
  * @argument anyObject the object to serialize
  * @argument objectName a name for that object
- * @return the XML serializationj of the given object as a string
+ * @return the XML serialization of the given object as a string
  */
 Sarissa.xmlize = function(anyObject, objectName, indentSpace){
     indentSpace = indentSpace?indentSpace:'';
     var s = indentSpace  + '<' + objectName + '>';
     var isLeaf = false;
-    if(!(anyObject instanceof Object) || anyObject instanceof Number ||
-        anyObject instanceof String || anyObject instanceof Boolean ||
-        anyObject instanceof Date){
+    if(!(anyObject instanceof Object) || anyObject instanceof Number || anyObject instanceof String 
+        || anyObject instanceof Boolean || anyObject instanceof Date){
         s += Sarissa.escape(""+anyObject);
         isLeaf = true;
     }else{
@@ -618,11 +666,11 @@
  * @param sXml the string to escape
  */
 Sarissa.escape = function(sXml){
-    return sXml.replace(/&/g, "&amp;").
-        replace(/</g, "&lt;").
-        replace(/>/g, "&gt;").
-        replace(/"/g, "&quot;").
-        replace(/'/g, "&apos;");
+    return sXml.replace(/&/g, "&amp;")
+        .replace(/</g, "&lt;")
+        .replace(/>/g, "&gt;")
+        .replace(/"/g, "&quot;")
+        .replace(/'/g, "&apos;");
 };
 
 /** 
@@ -631,10 +679,10 @@
  * @param sXml the string to unescape
  */
 Sarissa.unescape = function(sXml){
-    return sXml.replace(/&apos;/g,"'").
-        replace(/&quot;/g,"\"").
-        replace(/&gt;/g,">").
-        replace(/&lt;/g,"<").
-        replace(/&amp;/g,"&");
+    return sXml.replace(/&apos;/g,"'")
+        .replace(/&quot;/g,"\"")
+        .replace(/&gt;/g,">")
+        .replace(/&lt;/g,"<")
+        .replace(/&amp;/g,"&");
 };
 //   EOF

Modified: kupu/branch/kupu-1.4/default/drawers.kupu
==============================================================================
--- kupu/branch/kupu-1.4/default/drawers.kupu	(original)
+++ kupu/branch/kupu-1.4/default/drawers.kupu	Fri Nov  9 15:08:37 2007
@@ -5,6 +5,7 @@
     xmlns="http://www.w3.org/1999/xhtml"
     xmlns:kupu="http://kupu.oscom.org/namespaces/dist"
     xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+    xmlns:tal="http://xml.zope.org/namespaces/tal"
     i18n:domain="kupu"
     >
   <kupu:id>$Id$</kupu:id>
@@ -57,7 +58,8 @@
          <ul class="kupu-tabs">
             <li class="kupu-linkdrawer-addlink selected"><a href="#"
             i18n:translate="tab_link">Link to url</a></li>
-            <li class="kupu-linkdrawer-embed"><a href="#"
+            <li class="kupu-linkdrawer-embed"
+                tal:condition="filter/embed-tab|nothing"><a href="#"
             i18n:translate="tab_embed">Embed external object</a></li>
          </ul>
          <table class="kupu-tabbed">
@@ -167,7 +169,7 @@
                   <th class="kupu-toolbox-label"> </th>
                   <td>
                     <input class="kupu-tabledrawer-makeheader"
-                           type="checkbox"
+                           type="checkbox" checked="checked"
                            onkeypress="return HandleDrawerEnter(event);"
                            id="tabledrawer_makeheader"
                            />
@@ -289,58 +291,64 @@
          <ul class="kupu-tabs">
             <li class="kupu-ins-bm selected"><a href="#"
             i18n:translate="tab_link_anchor">Link to anchor</a></li>
-            <li class="kupu-anchor"><a href="#"
+            <li class="kupu-anchor"
+                tal:condition="filter/manage-anchors-tab"><a href="#"
             i18n:translate="tab_manage_anchors">Manage Anchors</a></li>
-            <li class="kupu-toc"><a href="#" i18n:translate="tab_toc">Table of contents</a></li>
+            <li class="kupu-toc"
+                tal:condition="filter/toc-tab|nothing"><a href="#" i18n:translate="tab_toc">Table of contents</a></li>
          </ul>
-        <table class="kupu-tabbed">
+        <table class="kupu-tabbed" cellspacing="0">
           <tr>
             <td class="kupu-bm-select">
               <select id="kupu-bm-sel1" size="10"> </select>
             </td>
-            <td rowspan="2">
-              <div class="kupu-bm-heading hide-ins-bm">
-                <div style="float:right" class="hide-anchor">
+            <td>
+              <div class="kupu-bm-heading">
+                <div class="kupu-bm-tablestyle invis-ins-bm invis-anchor">
                   <label i18n:translate="label_table_style" for="kupu-bm-outcls">
                     Table style
                   </label>
                   <select id="kupu-bm-outcls" size="1">
-                    <option value="" i18n:translate="Normal">Normal</option>
+                    <option value="" i18n:translate="Normal">Normal paragraph</option>
                   </select>
                 </div>
-                <div style="float:right" class="hide-anchor">
+                <div class="kupu-bm-numbering invis-ins-bm invis-anchor">
                   <label i18n:translate="label_numbering" for="kupu-bm-number">
                     Numbering
                   </label>
-                  <input type="checkbox" checked="checked" id="kupu-bm-number"/>
+                  <input type="checkbox" class="hide-ins-bm hide-anchor" checked="checked" id="kupu-bm-number"/>
+                </div>
+                <div class="invis-ins-bm">
+                   <label for="kupu-bm-checkall">
+                      <em i18n:translate="label_toggle_all">toggle all</em>
+                   </label>
+                   <input type="checkbox" class="hide-ins-bm" checked="checked" id="kupu-bm-checkall"/>
                 </div>
-                <label for="kupu-bm-checkall">
-                  <em i18n:translate="label_toggle_all">toggle all</em>
-                </label>
-                <input type="checkbox" checked="checked" id="kupu-bm-checkall"/>
               </div>
               <div class="kupu-bm-paras">&#xa0;</div>
-              <div class="kupu-bm-helpanchor hide-anchor hide-toc"
-                   i18n:translate="create_anchor_link_help">
-                Select a paragraph style then choose a paragraph and Ok to insert a link to that location.
-              </div>
-              <div class="kupu-bm-helptoc hide-ins-bm hide-anchor"
-                   i18n:translate="create_toc_help">
-                Select one or two paragraph styles, then Ok to insert a table of contents.
-              </div>
-              <div class="hide-ins-bm hide-toc" i18n:translate="create_anchor_help">
-                Anchors are created for checked paragraphs and
-                removed for unchecked paragraphs when you press Ok.
-                Anchors in use on this page may not be deleted.
-              </div>
             </td>
           </tr>
           <tr>
-            <td class="hide-ins-bm hide-anchor">
+            <td>
               <select id="kupu-bm-sel2" size="1" class="hide-ins-bm hide-anchor">
                 <option value="" i18n:translate="opt_2nd_style">(optional 2nd style)</option>
               </select>
             </td>
+            <td>
+               <div class="kupu-bm-help">
+                  <span class="hide-anchor hide-toc discreet" i18n:translate="create_anchor_link_help">
+                     Select a paragraph style then choose a paragraph and Ok to insert a link to that location.
+                  </span>
+                  <span class="hide-ins-bm hide-anchor discreet" i18n:translate="create_toc_help">
+                     Select one or two paragraph styles, then Ok to insert a table of contents.
+                  </span>
+                  <span class="hide-ins-bm hide-toc discreet" i18n:translate="create_anchor_help">
+                     Anchors are created for checked paragraphs and
+                     removed for unchecked paragraphs when you press Ok.
+                     Anchors in use on this page may not be deleted.
+                  </span>
+              </div>
+            </td>
           </tr>
         </table>
         <div class="kupu-dialogbuttons">

Modified: kupu/branch/kupu-1.4/default/toolbar.kupu
==============================================================================
--- kupu/branch/kupu-1.4/default/toolbar.kupu	(original)
+++ kupu/branch/kupu-1.4/default/toolbar.kupu	Fri Nov  9 15:08:37 2007
@@ -61,7 +61,7 @@
   <kupu:part name="select-styles">
     <select id="kupu-tb-styles">
       <option value="P" i18n:translate="Normal">
-        Normal
+        Normal paragraph
       </option>
       <option value="H1">
         <span i18n:translate="Heading 1">Heading 1</span>

Modified: kupu/branch/kupu-1.4/doc/CHANGES.txt
==============================================================================
--- kupu/branch/kupu-1.4/doc/CHANGES.txt	(original)
+++ kupu/branch/kupu-1.4/doc/CHANGES.txt	Fri Nov  9 15:08:37 2007
@@ -2,6 +2,68 @@
 Kupu changes
 ============
 
+- 1.4.4
+
+  - Enabled Safari support (needs webkit nightly build and Safari 3)
+
+  - Plone tickets
+
+    * 7099 Kupu error on multi-schemata archetypes content
+    * 7258 Missing translation msgids for kupu
+    * 7224 Kupu: error in iframe tabindex attribute
+    * 7229 kupu 1.4.3 css correction to display redo button icon in editing interface
+    * 7285 Kupu Accesskey for Save conflict with Firefox History Menu
+    * 7305 Page creation and kupu upload image returns an error if Kupu link uid's is turned on.
+    * 7315 Kupu table of contents generator doesn't allow multiple paragraph styles to be selected in IE7
+
+- 1.4.3
+
+  - Kupu now uses sarissa 0.9.8.1 (still a differences in
+    sarissa_ieemu_xpath.js, but these are purely cosmetic so that jslint
+    runs cleanly).
+
+  - Plone tickets
+
+    * 6970: can't upgrade to Kupu 1.4.1
+    * 6975: Cannot save HTML field as NULL
+    * 7119: 'Edit without visual editor' link doesn't show up in Plone 2.5.3
+    * 7139: Kupu Manage Anchors not working in inline edit
+    * 7140: kupu fails with danish letters in title.
+    * 7143: UnicodeError inserting image
+    * 7158: Kupu Edit already inserted image: Preview and sizes get wrong urls
+
+- 1.4.2
+
+  - Florian fixed some encoding errors
+
+  - Plone tickets
+
+    * 7074: Search for image errors in Kupu
+
+- 1.4.1
+
+  Limi asked for some last minute changes for Plone 3:
+
+  - Embed doesn't work out of the box in Plone 3, so shouldn't be shown
+    by default (it will only lead to a lot of user frustration).
+
+  - The anchor/table of contents generation is done differently in Plone
+    3, so should be off by default (turning on buttons is easy in Kupu
+    now).
+
+  - Insert image/link should default to current folder instead of
+    Recent, since the Upload button isn't visible if not (which is the
+    most common use case)
+
+  - Place the delete link/image button after the pulldown (so it doesn't
+    push around the toolbar elements)
+
+  - Default table styles now include "grid listing" and "invisible".
+
+  - Paragraph styles now labelled just styles and include: highlight, page break, clear floats
+
+  - Create headings now on by default.
+
 - 1.4
 
   - The icons in the toolbar for Plone now use CSS sprites. This means that

Modified: kupu/branch/kupu-1.4/doc/PLONE2.txt
==============================================================================
--- kupu/branch/kupu-1.4/doc/PLONE2.txt	(original)
+++ kupu/branch/kupu-1.4/doc/PLONE2.txt	Fri Nov  9 15:08:37 2007
@@ -225,8 +225,8 @@
 ``data``. Only ``listing`` is defined in the default Plone css, you
 should add suitable rules for the other styles to ``ploneCustom.css``.
 
-Paragraph Styles
-::::::::::::::::
+Styles
+::::::
 Enter a list of styles to be added to the style pulldown. See `Custom
 Styles`_.
 
@@ -519,7 +519,7 @@
    c) For Archetypes content types additional styles may be defined for
       individual fields.
 
-Styles defined under `Paragraph Styles`_ in the control panel are in the format ``title|tag``
+Styles defined under `Styles`_ in the control panel are in the format ``title|tag``
 or ``title|tag|class``. e.g.::
 
     Heading|h2
@@ -529,7 +529,7 @@
     Highlight|span|highlight
     Table Head|th
 
-Each rich text field can define its own set of paragraph styles to be
+Each rich text field can define its own set of styles to be
 made available in kupu. These are defined on the ``parastyles`` attribute
 of the ``RichWidget``. For example, a typical field definition might be::
 

Modified: kupu/branch/kupu-1.4/i18n.bat
==============================================================================
--- kupu/branch/kupu-1.4/i18n.bat	(original)
+++ kupu/branch/kupu-1.4/i18n.bat	Fri Nov  9 15:08:37 2007
@@ -80,12 +80,12 @@
 for %%f in (default\*) do (find /C "i18n:domain=""kupuconfig""" %%f && set KUPUCONFIG=!KUPUCONFIG! %%f) >nul
 for %%f in (plone\*) do (find /C "i18n:domain=""kupuconfig""" %%f && set KUPUCONFIG=!KUPUCONFIG! %%f) >nul
 for %%f in (plone\kupu_plone_layer\*) do (find /C "i18n:domain=""kupuconfig""" %%f && set KUPUCONFIG=!KUPUCONFIG! %%f) >nul
-for %%f in (common\drawers\*) do (find /C "i18n:domain=""kupuconfig""" %%f && set KUPUCONFIG=!KUPUCONFIG! %%f) >nul
+for %%f in (common\kupudrawers\*) do (find /C "i18n:domain=""kupuconfig""" %%f && set KUPUCONFIG=!KUPUCONFIG! %%f) >nul
 goto :eof
 :setKUPU
 set KUPU=
 for %%f in (default\*) do (find /C "i18n:domain=""kupu""" %%f && set KUPU=!KUPU! %%f) >nul
 for %%f in (plone\*) do (find /C "i18n:domain=""kupu""" %%f && set KUPU=!KUPU! %%f) >nul
 for %%f in (plone\kupu_plone_layer\*) do (find /C "i18n:domain=""kupu""" %%f && set KUPU=!KUPU! %%f) >nul
-for %%f in (common\drawers\*) do (find /C "i18n:domain=""kupu""" %%f && set KUPU=!KUPU! %%f) >nul
+for %%f in (common\kupudrawers\*) do (find /C "i18n:domain=""kupu""" %%f && set KUPU=!KUPU! %%f) >nul
 goto :eof

Modified: kupu/branch/kupu-1.4/plone/body.kupu
==============================================================================
--- kupu/branch/kupu-1.4/plone/body.kupu	(original)
+++ kupu/branch/kupu-1.4/plone/body.kupu	Fri Nov  9 15:08:37 2007
@@ -18,7 +18,7 @@
                     base kupu_base_override|base;"
         tal:attributes="src string:${base}/emptypage;
                         id string:kupu-editor-iframe-${fname};
-                        name string:kupu-editor-iframe-${fname};tabindex tabindex|nothing;"
+                        name string:kupu-editor-iframe-${fname};tabindex tabindex/next|tabindex|nothing;"
         >
     </iframe>
      <input type="hidden" name="text_format:default" value="text/html"
@@ -65,8 +65,10 @@
 
   <kupu:part name="suppress-kupu">
     <div class="kupuoverride"
-        tal:condition="python:exists('kupu_content') and len(kupu_content)==0 and gAC and len(gAC(here))!=1"
-        tal:define="floated widget/allow_file_upload | python:1;gAC nocall:field/getAllowedContentTypes|nothing"
+        tal:condition="python:exists('kupu_content') and len(kupu_content)==0 and allowed and len(allowed)!=1"
+        tal:define="floated widget/allow_file_upload | python:1;
+                gAC nocall:field/getAllowedContentTypes|nothing;
+                allowed python:gAC and gAC(context) or path('field/allowable_content_types|nothing');"
         tal:attributes="style python:test(floated, 'float:left;;', '');"
       ><span class="discreet"><a class="forcekupu" href="#"
         i18n:translate="suppress-kupu" i18n:attributes="title title_suppress_kupu;"

Modified: kupu/branch/kupu-1.4/plone/helpers.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/helpers.py	(original)
+++ kupu/branch/kupu-1.4/plone/helpers.py	Fri Nov  9 15:08:37 2007
@@ -35,7 +35,10 @@
     ('imagelibdrawer-button', 'Image drawer button', True, 'kupu-image'),
     ('linklibdrawer-button', 'Link drawer button', True, 'kupu-inthyperlink'),
     ('linkdrawer-button', 'External link drawer button', True, 'kupu-exthyperlink'),
+    ('embed-tab', 'Embed tab in External link drawer', False, None),
     ('anchors-button', 'Anchor drawer button', True, 'kupu-anchors'),
+    ('manage-anchors-tab', 'Manage Anchors tab in anchor drawer', True, None),
+    ('toc-tab', 'Table of Contents in anchor drawer', False, None),
     ('tabledrawer-button', 'Table drawer button', True, 'kupu-table'),
     ('bg-remove', 'Remove group', True, None),
     ('removeimage-button', 'Remove image button', True, 'kupu-removeimage'),

Modified: kupu/branch/kupu-1.4/plone/html2captioned.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/html2captioned.py	(original)
+++ kupu/branch/kupu-1.4/plone/html2captioned.py	Fri Nov  9 15:08:37 2007
@@ -37,6 +37,7 @@
 ATTR_VALUE = '=(?:"?)(?P<%s>(?<=")[^"]*|[^ \/>]*)'
 ATTR_CLASS = ATTR_VALUE % 'class'
 ATTR_WIDTH = ATTR_VALUE % 'width'
+ATTR_HEIGHT = ATTR_VALUE % 'height'
 ATTR_ALT = ATTR_VALUE % 'alt'
 
 ATTR_PATTERN = re.compile('''
@@ -45,9 +46,10 @@
      | src\s*=\s*"resolveuid/(?P<src>([^/"#? ]*))
      | width%s
      | alt%s
+     | height%s
      | .
      )*\>
-    )''' % (ATTR_CLASS, ATTR_WIDTH, ATTR_ALT), re.VERBOSE | re.IGNORECASE | re.DOTALL)
+    )''' % (ATTR_CLASS, ATTR_WIDTH, ATTR_ALT, ATTR_HEIGHT), re.VERBOSE | re.IGNORECASE | re.DOTALL)
 SRC_TAIL = re.compile(r'/([^" \/>]+)')
 
 CLASS_PATTERN = re.compile('\s*class\s*=\s*("[^"]*captioned[^"]*"|[^" \/>]+)')
@@ -123,6 +125,7 @@
                 tag = match.group(1) or match.group(2)
                 attrs = ATTR_PATTERN.match(tag)
                 src = attrs.group('src')
+                subtarget = None
                 m = SRC_TAIL.match(tag, attrs.end('src'))
                 if m:
                     srctail = m.group(1)
@@ -135,18 +138,39 @@
                         d['class'] = attrs.group('class')
                         d['originalwidth'] = attrs.group('width')
                         d['originalalt'] = attrs.group('alt')
+                        d['url_path'] = target.absolute_url_path()
                         d['caption'] = newline_to_br(html_quote(target.Description()))
                         d['image'] = d['fullimage'] = target
+                        d['tag'] = None
+                        d['isfullsize'] = False
+                        d['width'] = target.width
                         if srctail:
+                            if isinstance(srctail, unicode):
+                                srctail =srctail.encode('utf8') # restrictedTraverse doesn't accept unicode
                             try:
                                 subtarget = target.restrictedTraverse(srctail)
                             except:
                                 subtarget = getattr(target, srctail, None)
                             if subtarget:
                                 d['image'] = subtarget
+
+                            if srctail.startswith('image_'):
+                                d['tag'] = target.getField('image').tag(target, scale=srctail[6:])
+                            elif subtarget:
+                                d['tag'] = subtarget.tag()
+
+                        if d['tag'] is None:
+                            d['tag'] = target.tag()
+
+                        if subtarget:
+                            d['isfullsize'] = subtarget.width == target.width and subtarget.height == target.height
+                            d['width'] = subtarget.width
+
                         return template(**d)
                 return match.group(0) # No change
 
+            if isinstance(data, str):
+                data = data.decode('utf8')
             html = IMAGE_PATTERN.sub(replaceImage, data)
 
             # Replace urls that use UIDs with human friendly urls.
@@ -223,9 +247,9 @@
         if fields:
             f = fields[0]
             self.portal_type = f.portal_type
-            self.typename = f.type
-            self.fieldname = f.name
-            self.fieldlabel = f.label
+            self.typename = f.type.decode('utf-8')
+            self.fieldname = f.name.decode('utf-8')
+            self.fieldlabel = f.label.decode('utf-8')
         else:
             self.portal_type = rfg('portal_type', None)
             self.fieldname = None

Modified: kupu/branch/kupu-1.4/plone/kupu_config.pt
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_config.pt	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_config.pt	Fri Nov  9 15:08:37 2007
@@ -233,8 +233,8 @@
                         </div>
 
                         <div class="field">
-                           <label for="parastyles" i18n:translate="label_paragraph_styles">Paragraph Styles</label>
-                           <div class="formHelp" i18n:translate="help_paragraph_styles">Enter a list of paragraph styles to appear in the style pulldown. Format is title|tag or title|tag|className, one per line.</div>
+                           <label for="parastyles" i18n:translate="label_paragraph_styles">Styles</label>
+                           <div class="formHelp" i18n:translate="help_paragraph_styles">Enter a list of styles to appear in the style pulldown. Format is title|tag or title|tag|className, one per line.</div>
                            <input type="hidden" name="parastyles:list:default" value=" " />
                            <textarea name="parastyles:lines" id="parastyles"
                                      rows="5" cols="30" style="width:90%"

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_captioned_image.pt
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_captioned_image.pt	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_captioned_image.pt	Fri Nov  9 15:08:37 2007
@@ -1,15 +1,9 @@
-<dl tal:define="image nocall:options/image;
-    width image/width|image/getWidth|python:150;
-    height image/height|image/getHeight|python:150;
-    oimage nocall:options/fullimage|nocall:options/image;
-    owidth oimage/width|oimage/getWidth|python:150;
-    oheight oimage/height|oimage/getHeight|python:150;"
-    tal:attributes="class options/class">
-<dt><a tal:omit-tag="python:height==oheight and width==owidth"
- rel="lightbox" tal:attributes="href oimage/absolute_url_path;"><img
- tal:replace="structure image/tag" /></a></dt>
+<dl tal:attributes="class options/class">
+<dt><a tal:omit-tag="options/isfullsize" rel="lightbox"
+   tal:attributes="href options/url_path;"
+   tal:content="structure options/tag">[image goes here]</a></dt>
  <dd class="image-caption"
-     tal:attributes="style string:width:${width}px;"
+     tal:attributes="style string:width:${options/width}px;"
      tal:content="options/caption|nothing">
  </dd>
 </dl>

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_wysiwyg_support.html
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_wysiwyg_support.html	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_wysiwyg_support.html	Fri Nov  9 15:08:37 2007
@@ -12,17 +12,17 @@
     <!--$Id: sourceedit.kupu 25717 2006-04-12 10:33:01Z fschulze $-->
     <!--$Id: sourceedit.kupu 9779 2005-03-15 11:34:47Z duncan $-->
     <!--$Id: contextmenu.kupu 9520 2005-02-26 16:30:23Z duncan $-->
-    <!--$Id: toolbar.kupu 44538 2007-06-26 10:46:28Z duncan $-->
+    <!--$Id: toolbar.kupu 47952 2007-10-25 15:40:31Z duncan $-->
     <!--$Id: toolboxes.kupu 44538 2007-06-26 10:46:28Z duncan $-->
-    <!--$Id: colorchooser.kupu 44538 2007-06-26 10:46:28Z duncan $-->
+    <!--$Id: colorchooser.kupu 45650 2007-08-14 10:04:42Z guido $-->
     <!--$Id: save.kupu 44538 2007-06-26 10:46:28Z duncan $-->
-    <!--$Id: drawers.kupu 44538 2007-06-26 10:46:28Z duncan $-->
+    <!--$Id: drawers.kupu 47952 2007-10-25 15:40:31Z duncan $-->
     <!--$Id: include.kupu 39202 2007-02-19 12:06:45Z duncan $-->
-    <!--$Id: wire.kupu 25247 2006-04-03 11:23:02Z fschulze $-->
+    <!--$Id: wire.kupu 45669 2007-08-15 10:47:27Z duncan $-->
     <!--$Id: head.kupu 44831 2007-07-07 19:01:27Z duncan $-->
     <!--$Id: xmlconfig.kupu 35367 2006-12-06 09:06:21Z duncan $-->
-    <!--$Id: body.kupu 45298 2007-07-24 10:38:54Z duncan $-->
-    <!--$Id: toolbar.kupu 45493 2007-08-05 06:38:47Z limi $-->
+    <!--$Id: body.kupu 47952 2007-10-25 15:40:31Z duncan $-->
+    <!--$Id: toolbar.kupu 45621 2007-08-13 12:26:50Z duncan $-->
     <!--$Id save.kupu (not yet in svn) $-->
     <!--$Id: drawers.kupu 44538 2007-06-26 10:46:28Z duncan $-->
     <!--$Id: beforeunload.kupu 14546 2005-07-12 14:35:55Z duncan $-->
@@ -128,7 +128,7 @@
     </span>
   
     <span class="kupu-tb-buttongroup" tal:condition="not:context/checkCreationFlag|python:True">
-      <button type="button" class="kupu-save" id="kupu-save-button" title="Save" i18n:attributes="title title_save;" accesskey="s" tal:condition="filter/save-button">&#160;</button>
+      <button type="button" class="kupu-save" id="kupu-save-button" title="Save" i18n:attributes="title title_save;" tal:condition="filter/save-button">&#160;</button>
     </span>
   
     <span class="kupu-tb-buttongroup" id="kupu-bg-basicmarkup" tal:condition="filter/bg-basicmarkup">
@@ -176,11 +176,6 @@
       <button type="button" class="kupu-table" tal:condition="filter/tabledrawer-button" id="kupu-tabledrawer-button" title="Insert table" i18n:attributes="title title_insert_table;">&#160;</button>
     </span>
   
-    <span class="kupu-tb-buttongroup" id="kupu-bg-remove" tal:condition="filter/bg-remove">
-      <button type="button" class="kupu-removeimage invisible" tal:condition="filter/removeimage-button" id="kupu-removeimage-button" title="Remove image" i18n:attributes="title title_removeimage;">&#160;</button>
-      <button type="button" class="kupu-removelink invisible" tal:condition="filter/removelink-button" id="kupu-removelink-button" title="Remove link" i18n:attributes="title title_removelink;">&#160;</button>
-    </span>
-  
     <span class="kupu-tb-buttongroup" id="kupu-bg-undo" tal:condition="filter/bg-undo">
       <button type="button" class="kupu-undo" tal:condition="filter/undo-button" id="kupu-undo-button" title="Undo: Access key (Alt or Ctrl) + Z" i18n:attributes="title title_undo;" accesskey="z">&#160;</button>
       <button type="button" class="kupu-redo" tal:condition="filter/redo-button" id="kupu-redo-button" title="Redo: Access key (Alt or Ctrl) + Y" i18n:attributes="title title_redo;" accesskey="y">&#160;</button>
@@ -201,6 +196,11 @@
       </tal:block>
     </select>
   
+    <span class="kupu-tb-buttongroup" id="kupu-bg-remove" tal:condition="filter/bg-remove">
+      <button type="button" class="kupu-removeimage invisible" tal:condition="filter/removeimage-button" id="kupu-removeimage-button" title="Remove image" i18n:attributes="title title_removeimage;">&#160;</button>
+      <button type="button" class="kupu-removelink invisible" tal:condition="filter/removelink-button" id="kupu-removelink-button" title="Remove link" i18n:attributes="title title_removelink;">&#160;</button>
+    </span>
+  
     </span>
   
     <select id="kupu-ulstyles" class="kupu-ulstyles" tal:condition="filter/ulstyles">
@@ -229,7 +229,7 @@
       <div id="kupu-linkdrawer-addlink" class="kupu-panels kupu-linkdrawer-addlink">
          <ul class="kupu-tabs">
             <li class="kupu-linkdrawer-addlink selected"><a href="#" i18n:translate="tab_link">Link to url</a></li>
-            <li class="kupu-linkdrawer-embed"><a href="#" i18n:translate="tab_embed">Embed external object</a></li>
+            <li class="kupu-linkdrawer-embed" tal:condition="filter/embed-tab|nothing"><a href="#" i18n:translate="tab_embed">Embed external object</a></li>
          </ul>
          <table class="kupu-tabbed">
             <tbody class="kupu-addlink">
@@ -323,7 +323,7 @@
                 <tr>
                   <th class="kupu-toolbox-label"> </th>
                   <td>
-                    <input class="kupu-tabledrawer-makeheader" type="checkbox" onkeypress="return HandleDrawerEnter(event);" id="tabledrawer_makeheader"/>
+                    <input class="kupu-tabledrawer-makeheader" type="checkbox" checked="checked" onkeypress="return HandleDrawerEnter(event);" id="tabledrawer_makeheader"/>
                     <label i18n:translate="tabledrawer_headings_label" for="tabledrawer_makeheader">
                       Create Headings
                     </label>
@@ -401,55 +401,61 @@
       <div class="kupu-panels kupu-ins-bm">
          <ul class="kupu-tabs">
             <li class="kupu-ins-bm selected"><a href="#" i18n:translate="tab_link_anchor">Link to anchor</a></li>
-            <li class="kupu-anchor"><a href="#" i18n:translate="tab_manage_anchors">Manage Anchors</a></li>
-            <li class="kupu-toc"><a href="#" i18n:translate="tab_toc">Table of contents</a></li>
+            <li class="kupu-anchor" tal:condition="filter/manage-anchors-tab"><a href="#" i18n:translate="tab_manage_anchors">Manage Anchors</a></li>
+            <li class="kupu-toc" tal:condition="filter/toc-tab|nothing"><a href="#" i18n:translate="tab_toc">Table of contents</a></li>
          </ul>
-        <table class="kupu-tabbed">
+        <table class="kupu-tabbed" cellspacing="0">
           <tr>
             <td class="kupu-bm-select">
               <select id="kupu-bm-sel1" size="10"> </select>
             </td>
-            <td rowspan="2">
-              <div class="kupu-bm-heading hide-ins-bm">
-                <div style="float:right" class="hide-anchor">
+            <td>
+              <div class="kupu-bm-heading">
+                <div class="kupu-bm-tablestyle invis-ins-bm invis-anchor">
                   <label i18n:translate="label_table_style" for="kupu-bm-outcls">
                     Table style
                   </label>
                   <select id="kupu-bm-outcls" size="1">
-                    <option value="" i18n:translate="Normal">Normal</option>
+                    <option value="" i18n:translate="Normal">Normal paragraph</option>
                   </select>
                 </div>
-                <div style="float:right" class="hide-anchor">
+                <div class="kupu-bm-numbering invis-ins-bm invis-anchor">
                   <label i18n:translate="label_numbering" for="kupu-bm-number">
                     Numbering
                   </label>
-                  <input type="checkbox" checked="checked" id="kupu-bm-number"/>
+                  <input type="checkbox" class="hide-ins-bm hide-anchor" checked="checked" id="kupu-bm-number"/>
+                </div>
+                <div class="invis-ins-bm">
+                   <label for="kupu-bm-checkall">
+                      <em i18n:translate="label_toggle_all">toggle all</em>
+                   </label>
+                   <input type="checkbox" class="hide-ins-bm" checked="checked" id="kupu-bm-checkall"/>
                 </div>
-                <label for="kupu-bm-checkall">
-                  <em i18n:translate="label_toggle_all">toggle all</em>
-                </label>
-                <input type="checkbox" checked="checked" id="kupu-bm-checkall"/>
               </div>
               <div class="kupu-bm-paras">&#160;</div>
-              <div class="kupu-bm-helpanchor hide-anchor hide-toc" i18n:translate="create_anchor_link_help">
-                Select a paragraph style then choose a paragraph and Ok to insert a link to that location.
-              </div>
-              <div class="kupu-bm-helptoc hide-ins-bm hide-anchor" i18n:translate="create_toc_help">
-                Select one or two paragraph styles, then Ok to insert a table of contents.
-              </div>
-              <div class="hide-ins-bm hide-toc" i18n:translate="create_anchor_help">
-                Anchors are created for checked paragraphs and
-                removed for unchecked paragraphs when you press Ok.
-                Anchors in use on this page may not be deleted.
-              </div>
             </td>
           </tr>
           <tr>
-            <td class="hide-ins-bm hide-anchor">
+            <td>
               <select id="kupu-bm-sel2" size="1" class="hide-ins-bm hide-anchor">
                 <option value="" i18n:translate="opt_2nd_style">(optional 2nd style)</option>
               </select>
             </td>
+            <td>
+               <div class="kupu-bm-help">
+                  <span class="hide-anchor hide-toc discreet" i18n:translate="create_anchor_link_help">
+                     Select a paragraph style then choose a paragraph and Ok to insert a link to that location.
+                  </span>
+                  <span class="hide-ins-bm hide-anchor discreet" i18n:translate="create_toc_help">
+                     Select one or two paragraph styles, then Ok to insert a table of contents.
+                  </span>
+                  <span class="hide-ins-bm hide-toc discreet" i18n:translate="create_anchor_help">
+                     Anchors are created for checked paragraphs and
+                     removed for unchecked paragraphs when you press Ok.
+                     Anchors in use on this page may not be deleted.
+                  </span>
+              </div>
+            </td>
           </tr>
         </table>
         <div class="kupu-dialogbuttons">
@@ -466,7 +472,7 @@
     </table>
   <script type="text/javascript">var focuscount = 0;</script>
     <div>
-    <iframe class="kupu-editor-iframe" frameborder="0" src="emptypage" tabindex="" onfocus="this.contentWindow.focus();" tal:define="base python:here.kupu_library_tool.getBaseUrl(here, True);                     base kupu_base_override|base;" tal:attributes="src string:${base}/emptypage;                         id string:kupu-editor-iframe-${fname};                         name string:kupu-editor-iframe-${fname};tabindex tabindex|nothing;">
+    <iframe class="kupu-editor-iframe" frameborder="0" src="emptypage" tabindex="" onfocus="this.contentWindow.focus();" tal:define="base python:here.kupu_library_tool.getBaseUrl(here, True);                     base kupu_base_override|base;" tal:attributes="src string:${base}/emptypage;                         id string:kupu-editor-iframe-${fname};                         name string:kupu-editor-iframe-${fname};tabindex tabindex/next|tabindex|nothing;">
     </iframe>
      <input type="hidden" name="text_format:default" value="text/html" tal:define="fieldName fieldName|inputname|nothing;                 val python:fieldName and 'text/html' or 'html';                 fieldName python:test(fieldName, fieldName+'_', '') + 'text_format:default';" tal:attributes="name fieldName;value val;"/>
 <tal:test condition="fieldName|nothing">
@@ -477,7 +483,7 @@
     </textarea>
     </div>
   
-    <div class="kupuoverride" tal:condition="python:exists('kupu_content') and len(kupu_content)==0 and gAC and len(gAC(here))!=1" tal:define="floated widget/allow_file_upload | python:1;gAC nocall:field/getAllowedContentTypes|nothing" tal:attributes="style python:test(floated, 'float:left;;', '');"><span class="discreet"><a class="forcekupu" href="#" i18n:translate="suppress-kupu" i18n:attributes="title title_suppress_kupu;" tal:define="fs fieldset|nothing;fs python:test(fs,'&amp;fieldset=%s'%fs,None);" tal:attributes="href string:${request/URL0}?kupu.suppress=${fieldName}${fs};" title="reload current page without kupu">
+    <div class="kupuoverride" tal:condition="python:exists('kupu_content') and len(kupu_content)==0 and allowed and len(allowed)!=1" tal:define="floated widget/allow_file_upload | python:1;                 gAC nocall:field/getAllowedContentTypes|nothing;                 allowed python:gAC and gAC(context) or path('field/allowable_content_types|nothing');" tal:attributes="style python:test(floated, 'float:left;;', '');"><span class="discreet"><a class="forcekupu" href="#" i18n:translate="suppress-kupu" i18n:attributes="title title_suppress_kupu;" tal:define="fs fieldset|nothing;fs python:test(fs,'&amp;fieldset=%s'%fs,None);" tal:attributes="href string:${request/URL0}?kupu.suppress=${fieldName}${fs};" title="reload current page without kupu">
          Edit without visual editor
       </a></span>
     </div>

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuplone.css.dtml
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuplone.css.dtml	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuplone.css.dtml	Fri Nov  9 15:08:37 2007
@@ -45,19 +45,19 @@
 .pullQuote { float: right; width: 30%; }
 .kupu .pullQuote { float:none; width: auto; }
 */
-.kupu table { 
-  border-left:1px solid ThreeDLightShadow; 
-  border-top:1px solid ThreeDLightShadow; 
-  border-right:1px solid ThreeDDarkShadow; 
-  border-bottom:1px solid ThreeDDarkShadow; 
+.kupu table.invisible { 
+  border:1px solid ThreeDLightShadow; 
 } 
 
-.kupu table tr td { 
-  border-left:1px solid ThreeDDarkShadow; 
-  border-top:1px solid ThreeDDarkShadow; 
-  border-right:1px solid ThreeDLightShadow; 
-  border-bottom:1px solid ThreeDLightShadow; 
+.kupu table.invisible tr td { 
+  border:1px solid ThreeDDarkShadow; 
 } 
+
+.kupu div.pageBreak {
+    border-top: 1px dotted #ccc;
+}
+
+
 /* Hide the 'target' field in the LinkLibraryDrawer 
 
    I've used a class as an identifier here because somehow using id
@@ -197,8 +197,6 @@
 button.kupu-justifyright-pressed 
                          { background-position: 0 -300px; }
 
-button.kupu-logo {}
-button.kupu-redo {}
 button.kupu-removelink,
 button.kupu-removeimage  { background-position: 0 -320px; }
 
@@ -228,7 +226,8 @@
 button.kupu-underline-pressed {background-image: url("&dtml-portal_url;/plonekupuimages/underline.gif");}
 
 button.kupu-undo {background-image: url("&dtml-portal_url;/plonekupuimages/undo.gif");}
-
+button.kupu-redo {background-image: url("&dtml-portal_url;/plonekupuimages/redo.gif");}
+button.kupu-logo {background-image: url("kupuimages/kupu_icon.gif");}
 
 
 div.kupu-drawer {
@@ -327,5 +326,30 @@
 dl.captioned {
    padding: 10px;
 }
+
+/* Styling for documentation tab */
+.template-zmi_docs .contents {
+    float: right;
+    width: 30%;
+    font-size: 90%;
+    margin: 0 0 0.5em 0.5em; padding-top:0;
+    border: &dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;;
+}
+.template-zmi_docs ul.auto-toc, .template-zmi_docs ul.simple {
+  list-style: none;
+}
+.template-zmi_docs .topic-title {
+    background-color: &dtml-globalBackgroundColor;;
+    margin-top: 0;
+    padding: 0em 1em;
+    text-transform: &dtml-textTransform;;
+    font-weight: normal;
+    line-height: 1.6em;
+    border-bottom: &dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;;
+}
+.template-zmi_docs .topic-title a {
+    color: &dtml-fontColor;;
+    border-bottom: none;
+}
 /* </dtml-let></dtml-with> */
 

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuploneeditor.js
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuploneeditor.js	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuploneeditor.js	Fri Nov  9 15:08:37 2007
@@ -100,7 +100,7 @@
     // We need to get the contents of the body node as xml, but we don't
     // want the body node itself, so we use a regex to remove it
     var contents = this.getXMLBody(transform);
-    if (/^<body[^>]*>(<\/?(p|br)[^>]*>|\&nbsp;)*<\/body>$/.test(contents)) {
+    if (/^<body[^>]*>(<\/?(p|br)[^>]*>|\&nbsp;|\s)*<\/body>$/.test(contents)) {
         contents = ''; /* Ignore nearly empty contents */
     }
     var base = this._getBase(transform);

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupusearch.xml.pt
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupusearch.xml.pt	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupusearch.xml.pt	Fri Nov  9 15:08:37 2007
@@ -12,8 +12,7 @@
   <uri tal:content="template/absolute_url"/>
   <icon
        tal:content="searchlib/icon|string:${here/portal_url}/kupuimages/kupusearch_icon.gif"/>
-  <title i18n:translate="heading_search_results"
-         tal:define="tpl searchlib/title|string:Search '$$';txt request/SearchableText;"
+  <title tal:define="tpl searchlib/title|string:Search '$$';txt request/SearchableText;"
          tal:content="python:tpl.replace('$',txt,1)">Search Results</title>
   <description i18n:translate="descr_search_results">Search results.</description>
 

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/sample-kupu-customisation-policy.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/sample-kupu-customisation-policy.py	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/sample-kupu-customisation-policy.py	Fri Nov  9 15:08:37 2007
@@ -107,7 +107,7 @@
          src="string:${portal_url}/kupurecentitems.xml",
          icon="string:${portal_url}/kupuimages/kupusearch_icon.gif")
     )
-DEFAULT_LIBRARY = 'myitems'
+DEFAULT_LIBRARY = 'current'
 
 INSTALL_BEFOREUNLOAD = False
 LINKBYUID = False

Modified: kupu/branch/kupu-1.4/plone/kupu_references/referencebrowser.pt
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_references/referencebrowser.pt	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_references/referencebrowser.pt	Fri Nov  9 15:08:37 2007
@@ -92,8 +92,8 @@
                          lookupObject nocall:here/reference_catalog/lookupObject;
                          resource_type string:$portal_type.$fieldName;
                          rt python:kupu.getResourceType(resource_type);
-                         label widget/label;
-                         rLabel python:repr(unicode(label))[1:];
+                         label python:kupu.getLabelFromWidget(widget);
+                         rLabel python:repr(label)[1:];
                          uids python:same_type(value, []) and value or [value];
                          uids python:[u for u in uids if u];
                          types_param python:','.join(field.allowed_types);

Modified: kupu/branch/kupu-1.4/plone/plonedrawers.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/plonedrawers.py	(original)
+++ kupu/branch/kupu-1.4/plone/plonedrawers.py	Fri Nov  9 15:08:37 2007
@@ -20,7 +20,9 @@
 from Globals import InitializeClass
 from Products.Archetypes.public import *
 from Products.Archetypes.interfaces.referenceable import IReferenceable
+from Products.Archetypes.utils import shasattr
 from Products.PythonScripts.standard import html_quote, newline_to_br
+from Products.kupu.plone import util
 from Products.kupu.plone.librarytool import KupuError
 from Products.CMFCore.utils import getToolByName
 try:
@@ -644,9 +646,11 @@
                 src = src[len(base):].lstrip('/')
             try:
                 obj = portal.restrictedTraverse(src)
-            except AttributeError:
+            except (KeyError, AttributeError):
                 return []
             if portal_types:
+                while not shasattr(obj.aq_base, 'portal_type'):
+                    obj = obj.aq_parent
                 while obj.portal_type not in portal_types:
                     obj = obj.aq_parent
                     if obj is portal:
@@ -780,15 +784,22 @@
         return (getattr(field, 'default_output_type', None) in
             ('text/x-html-safe', 'text/x-html-captioned'))
 
+    security.declarePublic("getLabelFromWidget")
+    def getLabelFromWidget(self, widget):
+        """Get the label for a widget converting from i18n message if needed"""
+        label = util.translate(widget.Label(self), self.REQUEST)
+        if isinstance(label, str):
+            label = label.decode('utf8', 'replace')
+        return label
+
     security.declareProtected("View", "getKupuFields")
     def getKupuFields(self, filter=1):
         """Returns a list of all kupu editable fields"""
         inuse = getToolByName(self, 'portal_catalog').uniqueValuesFor('portal_type')
-        site_encoding = getSiteEncoding(self)
         for t,f,pt in self._getKupuFields():
             if html2captioned.sanitize_portal_type(pt) in inuse or not filter:
                 yield dict(type=t, name=f.getName(), portal_type=pt,
-                           label=f.widget.Label(self).decode(site_encoding))
+                           label=self.getLabelFromWidget(f.widget))
 
     def _getKupuFields(self):
         """Yield all fields which are editable using kupu"""
@@ -806,13 +817,13 @@
     security.declareProtected("View", "supportedCaptioning")
     def supportedCaptioning(self):
         """Returns a list of document/fields which have support for captioning"""
-        supported = [t+'/'+f.widget.label for (t,f,pt) in self._getKupuFields() if self.canCaption(f) ]
+        supported = [t+'/'+self.getLabelFromWidget(f.widget) for (t,f,pt) in self._getKupuFields() if self.canCaption(f) ]
         return str.join(', ', supported)
 
     security.declareProtected("View", "unsupportedCaptioning")
     def unsupportedCaptioning(self):
         """Returns a list of document/fields which do not have support for captioning"""
-        unsupp = [t+'/'+f.widget.label for (t,f,pt) in self._getKupuFields() if not self.canCaption(f) ]
+        unsupp = [t+'/'+self.getLabelFromWidget(f.widget) for (t,f,pt) in self._getKupuFields() if not self.canCaption(f) ]
         return str.join(', ', unsupp)
 
     security.declareProtected("View", "transformIsEnabled")

Modified: kupu/branch/kupu-1.4/plone/plonelibrarytool.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/plonelibrarytool.py	(original)
+++ kupu/branch/kupu-1.4/plone/plonelibrarytool.py	Fri Nov  9 15:08:37 2007
@@ -182,7 +182,7 @@
 
     security.declareProtected('View', "getStyleList")
     def getStyleList(self, field=None):
-        """Return the paragraph styles for a field."""
+        """Return the styles for a field."""
         gstyles = self.getParagraphStyles()
         if field:
             widget = field.widget
@@ -360,9 +360,12 @@
                 verno = getver(' rv:')
                 if verno:
                     return verno >= (1,3,1)
-#                 verno = getver(' AppleWebKit/')
-#                 if verno:
-#                     return verno >= (420,)
+                verno = getver(' AppleWebKit/')
+                if verno:
+                    return verno >= (523,11)
+                    verno = getver(' Safari/')
+                    if verno:
+                        return verno >= (522,12)
 
             verno = getver('MSIE')
             if verno:

Modified: kupu/branch/kupu-1.4/plone/profiles/default/kupu.xml
==============================================================================
--- kupu/branch/kupu-1.4/plone/profiles/default/kupu.xml	(original)
+++ kupu/branch/kupu-1.4/plone/profiles/default/kupu.xml	Fri Nov  9 15:08:37 2007
@@ -2,10 +2,11 @@
 <kupu-settings>
   <config captioning="False" userefbrowser="False"
           linkbyuid="False" filtersourceedit="True">
-    <table>plain</table>
-    <table>listing</table>
-    <table>vertical listing</table>
-    <table>listing nosort|unsorted listing</table>
+    <table>plain|Subdued grid</table>
+    <table>invisible|Invisible grid</table>
+    <table>listing|Fancy listing</table>
+    <table>grid listing|Fancy grid listing</table>
+    <table>vertical listing|Fancy vertical listing</table>
     <style>Heading|h2</style>
     <style>Subheading|h3</style>
     <style>Literal|pre</style>
@@ -16,6 +17,8 @@
     <style>Odd row|tr|odd</style>
     <style>Even row|tr|even</style>
     <style>Heading cell|th|</style>
+    <style>Page break (print only)|div|pageBreak</style>
+    <style>Clear floats|div|visualClear</style>
     <filter attributes=""
             tags="center tt big small basefont font"/>
     <filter attributes="lang valign halign border frame rules cellspacing cellpadding bgcolor"
@@ -47,7 +50,7 @@
            icon="string:${portal_url}/kupuimages/kupusearch_icon.gif"
            title="string:Recent items">
   </library>
-  <defaultlibrary>myitems</defaultlibrary>
+  <defaultlibrary>current</defaultlibrary>
   <resource id="collection" mode="whitelist">
     <type>Plone Site</type>
     <type>Large Plone Folder</type>

Modified: kupu/branch/kupu-1.4/plone/save.kupu
==============================================================================
--- kupu/branch/kupu-1.4/plone/save.kupu	(original)
+++ kupu/branch/kupu-1.4/plone/save.kupu	Fri Nov  9 15:08:37 2007
@@ -13,7 +13,7 @@
   <kupu:part name="buttons">
     <span class="kupu-tb-buttongroup" tal:condition="not:context/checkCreationFlag|python:True">
       <button type="button" class="kupu-save" id="kupu-save-button"
-              title="Save" i18n:attributes="title title_save;" accesskey="s"
+              title="Save" i18n:attributes="title title_save;"
 	      tal:condition="filter/save-button">&#160;</button>
     </span>
   </kupu:part>

Modified: kupu/branch/kupu-1.4/plone/tests/output/linked.out
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/output/linked.out	(original)
+++ kupu/branch/kupu-1.4/plone/tests/output/linked.out	Fri Nov  9 15:08:37 2007
@@ -1,9 +1,9 @@
 <div>Simple text containing an embedded image</div>
-<div class="image-left captioned" style="width:120px;">
- <div style="width:120px;">
+<dl class="image-left captioned">
+ <dt>
   <a href="xyzzy" class="link"><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/></a>
- </div>
- <div class="image-caption">
+ </dt>
+ <dd class="image-caption" style="width:120px">
   Test image caption
- </div>
+ </dd>
 </div>

Modified: kupu/branch/kupu-1.4/plone/tests/output/notquoted.out
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/output/notquoted.out	(original)
+++ kupu/branch/kupu-1.4/plone/tests/output/notquoted.out	Fri Nov  9 15:08:37 2007
@@ -1,13 +1,13 @@
 <div>IE doesn't always quote attributes</div>
-<div class="image-left captioned" style="width:120px;">
-  <div style="width:120px;">
-    <img height=144 src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width=120 alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
-  </div>
-  <div class="image-caption">Test image caption</div>
-</div>
-<div class="captioned" style="width:120px;">
-  <div style="width:120px;">
-    <img height=144 src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width=120 alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
-  </div>
-  <div class="image-caption">Test image caption</div>
-</div>
+<dl class="image-left captioned">
+  <dt>
+    <img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+  </dt>
+  <dd class="image-caption" style="width:120px">Test image caption</dd>
+</dl>
+<dl class="captioned">
+  <dt>
+    <img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+  </dt>
+  <dd class="image-caption" style="width:120px">Test image caption</dd>
+</dl>

Modified: kupu/branch/kupu-1.4/plone/tests/output/simple.out
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/output/simple.out	(original)
+++ kupu/branch/kupu-1.4/plone/tests/output/simple.out	Fri Nov  9 15:08:37 2007
@@ -1,16 +1,16 @@
 <div>Simple text containing an embedded image</div>
-<div class="image-left captioned" style="width:120px;">
-  <div style="width:120px;"><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
-  </div>
-  <div class="image-caption">Test image caption</div>
-</div>
-<div class="image-left captioned" style="width:20px;">
-  <div style="width:20px;"><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]/image_thumb" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
-  </div>
-  <div class="image-caption">Test image caption</div>
-</div>
-<div class="image-left captioned" style="width:600px;">
-  <div style="width:600px;"><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
-  </div>
-  <div class="image-caption">Test image caption</div>
-</div>
+<dl class="image-left captioned">
+  <dt><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+  </dt>
+  <dd class="image-caption" style="width:120px">Test image caption</dd>
+</dl>
+<dl class="image-left captioned">
+  <dt><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]/image_thumb" width="20" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+  </dt>
+  <dd class="image-caption" style="width:20px">Test image caption</dd>
+</dl>
+<dl class="image-left captioned">
+  <dt><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="600" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+  </dt>
+  <dd class="image-caption" style="width:600px">Test image caption</dd>
+</dl>

Modified: kupu/branch/kupu-1.4/plone/tests/test_html2captioned.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/test_html2captioned.py	(original)
+++ kupu/branch/kupu-1.4/plone/tests/test_html2captioned.py	Fri Nov  9 15:08:37 2007
@@ -8,6 +8,7 @@
 
 from Products.PortalTransforms.tests.test_transforms import *
 from Products.PortalTransforms.tests.utils import normalize_html
+from Products.kupu import kupu_globals
 
 PREFIX = abspath(dirname(__file__))
 
@@ -26,14 +27,11 @@
 ('Products.kupu.plone.html2captioned', "linked.in", "linked.out", normalize_html, 0),
     )
 
-class MockSubImage:
-    def getWidth(self):
-        return 20
-
 class MockImage:
     def __init__(self, uid, description):
         self.uid, self.description = uid, description
-        self.image_thumb = MockSubImage()
+        if not uid.startswith('SUB:'):
+            self.image_thumb = MockSubImage(self)
 
     def Title(self):
         return 'image '+self.uid
@@ -45,6 +43,22 @@
         return '[url for %s]' % self.uid
     def getWidth(self):
         return 600
+    def tag(self, height="", width="", **kw):
+        src = self.absolute_url_path()
+        alt = self.Title()
+        if not width:
+            width = self.getWidth()
+        return '<img height="%s" src="%s" width="%s" alt="%s"/>' % (height, src, width, alt)
+
+class MockSubImage(MockImage):
+    def __init__(self, parent):
+        self.uid = parent.uid
+        self.description = parent.description
+
+    def getWidth(self):
+        return 20
+    def absolute_url_path(self):
+        return '[url for %s]' % self.uid+'/image_thumb'
 
 class MockCatalogTool:
     def lookupObject(self, uid):
@@ -59,11 +73,43 @@
 class MockArchetypeTool:
     reference_catalog = MockCatalogTool()
 
+def mockPageTemplate(self, **kw):
+    """Acquisition isn't set up correctly for us to use a real PageTemplateFile,
+    so for the test we just use string formatting.
+    """
+    caption = kw.get('caption', '!caption!')
+    image = kw.get('image', None)
+    fullimage = kw.get('fullimage', None)
+    Class=kw['class']
+    width = kw['width']
+    owidth = fullimage.getWidth()
+    if width is None:
+        kw['width'] = width = image.getWidth()
+    href = fullimage.absolute_url_path()
+    tag = image.tag(**kw)
+
+    #if width==owidth:
+    TEMPLATE = '''<dl class="%(Class)s">
+    <dt>%(tag)s</dt>
+    <dd class="image-caption" style="width:%(width)spx">%(caption)s</dd>
+    </dl>'''
+    #else:
+    #    TEMPLATE = '''<dl class="%(Class)s">
+    #    <dt><a rel="lightbox" href="%(href)s">%(tag)s</a></dt>
+    #    <dd class="image-caption" style="width:%(width)spx">%(caption)s</dd>
+    #    </dl>'''
+        
+    return TEMPLATE % dict(
+        caption=caption, Class=Class, href=href, width=width, tag=tag)
+
 class MockPortal:
     # Mock portal class: just enough to let me think I can lookup a
     # Description for an image from its UID.
     archetype_tool = MockArchetypeTool()
 
+    # Also now needs access to the captioning template
+    kupu_captioned_image = mockPageTemplate
+
 class TransformTest(TestCase):
     portal = MockPortal()
     

Modified: kupu/branch/kupu-1.4/plone/util.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/util.py	(original)
+++ kupu/branch/kupu-1.4/plone/util.py	Fri Nov  9 15:08:37 2007
@@ -92,7 +92,15 @@
 
     if not hasattr(transform_tool, INVERSE_TRANSFORM):
         transform_tool.manage_addTransform(INVERSE_TRANSFORM, 'Products.PortalTransforms.transforms.identity')
-    
+        # Need to commit a subtransaction here, otherwise setting the
+        # parameters will cause an exception when the transaction is
+        # finally comitted.
+        try:
+            import transaction
+            transaction.savepoint(optimistic=True)
+        except ImportError:
+            get_transaction().commit(1)
+
     inverse = transform_tool[INVERSE_TRANSFORM]
     if inverse.get_parameter_value('inputs') != [MT_CAPTIONED] or inverse.get_parameter_value('output') != 'text/html':
         inverse.set_parameters(inputs=[MT_CAPTIONED], output='text/html')
@@ -122,3 +130,15 @@
         transform_tool.manage_delPolicies([MT_SAFE])
         if required:
             transform_tool.manage_addPolicy(MT_SAFE, required)
+
+try:
+    from zope.i18nmessageid import Message
+    from zope.i18n import translate as i18n_translate
+    def translate(label, context):
+        if isinstance(label, Message):
+            return i18n_translate(label, context=context)
+        return label
+except ImportError:
+    def translate(label, context):
+        return label
+

Modified: kupu/branch/kupu-1.4/plone/wire.kupu
==============================================================================
--- kupu/branch/kupu-1.4/plone/wire.kupu	(original)
+++ kupu/branch/kupu-1.4/plone/wire.kupu	Fri Nov  9 15:08:37 2007
@@ -56,11 +56,11 @@
     <kupu:insert-part feature="toolbar" part="buttongroup-definitionlist" />
     <kupu:insert-part feature="toolbar" part="buttongroup-indent" />
     <kupu:insert-part feature="drawers" part="buttons" />
-    <kupu:insert-part feature="toolbar" part="buttongroup-remove" />
     <kupu:insert-part feature="toolbar" part="buttongroup-undo" />
     <kupu:insert-part feature="spellchecker" part="buttons" />
     <kupu:insert-part feature="sourceedit" part="buttons" />
     <kupu:insert-part feature="toolbar" part="select-styles" />
+    <kupu:insert-part feature="toolbar" part="buttongroup-remove" />
   </kupu:fill-slot>
 
 

Modified: kupu/branch/kupu-1.4/plone/z3interfaces.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/z3interfaces.py	(original)
+++ kupu/branch/kupu-1.4/plone/z3interfaces.py	Fri Nov  9 15:08:37 2007
@@ -26,7 +26,7 @@
         """Return a list of classnames supported by paragraphs"""
 
     def getStyleList(field=None):
-        """Return the paragraph styles for a field."""
+        """Return the styles for a field."""
 
     def filterToolbar(context, field=None):
         """Return a filter helper for toolbar elements.

Modified: kupu/branch/kupu-1.4/plone/zmi_docs.pt
==============================================================================
--- kupu/branch/kupu-1.4/plone/zmi_docs.pt	(original)
+++ kupu/branch/kupu-1.4/plone/zmi_docs.pt	Fri Nov  9 15:08:37 2007
@@ -2,13 +2,30 @@
     lang="en"
     metal:use-macro="here/kupu_config/macros/master"
     i18n:domain="kupuconfig">
+<style metal:fill-slot="style_slot">
+div.system-messages {
+  margin: 5em }
 
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+</style>
 <body>
 
     <div class="documentContent" metal:fill-slot="kupu_content"
  tal:define="convertTo nocall:here/portal_transforms/convertTo|nothing">
 <div tal:condition="nocall:convertTo"
-     tal:content="structure python:convertTo('text/html', here.docs(), mimetype='text/x-rst')"
+     tal:define="tpath template/absolute_url_path;
+        stream python:convertTo('text/html', here.docs(), mimetype='text/x-rst');
+        formatted python:str(stream).replace('href=\x22#','href=\x22'+tpath+'#');"
+     tal:content="structure formatted"
      tal:on-error="structure string:Documentation formatting failed: ${error/value}&lt;pre&gt;${here/docs}&lt;/pre;&gt;">
 </div>
 <pre tal:condition="not:nocall:convertTo"

Modified: kupu/branch/kupu-1.4/version.txt
==============================================================================
--- kupu/branch/kupu-1.4/version.txt	(original)
+++ kupu/branch/kupu-1.4/version.txt	Fri Nov  9 15:08:37 2007
@@ -1 +1 @@
-kupu 1.4
+kupu 1.4.4


More information about the kupu-checkins mailing list