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

duncan at codespeak.net duncan at codespeak.net
Tue Mar 25 14:07:30 CET 2008


Author: duncan
Date: Tue Mar 25 14:07:28 2008
New Revision: 52910

Added:
   kupu/branch/kupu-1.4/plone/config.py
      - copied unchanged from r52909, kupu/trunk/kupu/plone/config.py
   kupu/branch/kupu-1.4/plone/profiles/default/metadata.xml
      - copied unchanged from r52909, kupu/trunk/kupu/plone/profiles/default/metadata.xml
   kupu/branch/kupu-1.4/plone/tests/image.jpg
      - copied unchanged from r52909, kupu/trunk/kupu/plone/tests/image.jpg
   kupu/branch/kupu-1.4/plone/tests/kuputestcase.py
      - copied unchanged from r52909, kupu/trunk/kupu/plone/tests/kuputestcase.py
Modified:
   kupu/branch/kupu-1.4/common/kupu_kjax.js
   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/kupueditor.js
   kupu/branch/kupu-1.4/common/kupuhelpers.js
   kupu/branch/kupu-1.4/common/sarissa.js
   kupu/branch/kupu-1.4/doc/CHANGES.txt
   kupu/branch/kupu-1.4/doc/PLONE2.txt
   kupu/branch/kupu-1.4/make-jspx.xsl
   kupu/branch/kupu-1.4/mmbase/body.kupu
   kupu/branch/kupu-1.4/mmbase/html.kupu
   kupu/branch/kupu-1.4/mmbase/kupustyle.css
   kupu/branch/kupu-1.4/mmbase/mmbase.kupu
   kupu/branch/kupu-1.4/mmbase/node.jspx
   kupu/branch/kupu-1.4/mmbase/toolboxes.kupu
   kupu/branch/kupu-1.4/plone/ReftextField.py
   kupu/branch/kupu-1.4/plone/body.kupu
   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/convertContentForKupu.py
   kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupu_wysiwyg_support.html
   kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupucollection.xml.pt
   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/kupuploneinit.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/librarytool.py
   kupu/branch/kupu-1.4/plone/plonedrawers.py
   kupu/branch/kupu-1.4/plone/plonelibrarytool.py
   kupu/branch/kupu-1.4/plone/profiles/default/import_steps.xml
   kupu/branch/kupu-1.4/plone/profiles/default/kupu.xml
   kupu/branch/kupu-1.4/plone/tests/framework.py
   kupu/branch/kupu-1.4/plone/tests/input/linked.in
   kupu/branch/kupu-1.4/plone/tests/input/simple.in
   kupu/branch/kupu-1.4/plone/tests/output/linked.out
   kupu/branch/kupu-1.4/plone/tests/output/notcaptioned.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/runme.cmd
   kupu/branch/kupu-1.4/plone/tests/test_browserSupportsKupu.py
   kupu/branch/kupu-1.4/plone/tests/test_html2captioned.py
   kupu/branch/kupu-1.4/plone/tests/test_links.py
   kupu/branch/kupu-1.4/plone/wysiwyg_support.kupu
   kupu/branch/kupu-1.4/plone/zmi_links.pt
   kupu/branch/kupu-1.4/tests/test_kupuhelpers.js
   kupu/branch/kupu-1.4/version.txt
Log:
Bring branch/kupu-1.4 back in line with trunk.

Modified: kupu/branch/kupu-1.4/common/kupu_kjax.js
==============================================================================
--- kupu/branch/kupu-1.4/common/kupu_kjax.js	(original)
+++ kupu/branch/kupu-1.4/common/kupu_kjax.js	Tue Mar 25 14:07:28 2008
@@ -57,9 +57,7 @@
                 // a web server expects from a POST.
                 xmlhttp.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
             };
-            if (reload) {
-                xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
-            }
+            xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
             this.xmlhttp = xmlhttp;
             xmlhttp.send(body);
         } catch(e) {

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	Tue Mar 25 14:07:28 2008
@@ -1251,6 +1251,7 @@
         /* create an image */
         var img = this.editor.getInnerDocument().createElement('img');
         img.src = url;
+        img.setAttribute('kupu-src', url);
         img.removeAttribute('height');
         img.removeAttribute('width');
         if (alttext) {
@@ -2751,9 +2752,9 @@
         var width = document.body.offsetWidth-5;
         var height = document.body.offsetHeight-5;
     }
-    width = width + 'px';
-    var offset = iframe.parentNode.offsetTop;
+    var offset = fulleditor.offsetTop;
     var nheight = Math.max(height - offset -1/*top border*/, 10) + 'px';
+    width = width + 'px';
     fulleditor.style.width = width; /*IE needs this*/
     iframe.style.width = width;
     iframe.style.height = nheight;
@@ -2832,13 +2833,21 @@
     var doc = this.editor.getInnerDocument();
     var body = doc.body;
     var paras = [];
-    for (var node = body.firstChild; node; node = node.nextSibling) {
-        var name = node.nodeName.toLowerCase();
-        var style = name + "|" + node.className;
-        if (style==style1) {
-            paras.push([node,0]);
-        } else if (style==style2) {
-            paras.push([node,1]);
+    var pat = /(.*?)(\|.*|$)/;
+    var tag1 = style1.replace(pat, '$1');
+    var tag2 = style2.replace(pat, '$1');
+    if (tag2 && tag2 != tag1) { tag1 = "*"; }
+    if (tag1) {
+        var nodes = body.getElementsByTagName(tag1);
+        for (var i = 0; i < nodes.length; i++) {
+            var node = nodes[i];
+            var style = node.nodeName.toLowerCase() + "|" + node.className;
+            if (style==style1) {
+                paras.push([node,0]);
+            }
+            if (style==style2) {
+                paras.push([node,1]);
+            }
         }
     }
     return paras;
@@ -2869,7 +2878,10 @@
     /* Returns the anchor for a node, creating one if reqd. unless
      * ifexists is set*/
     var anchors = node.getElementsByTagName('a');
-    if (anchors.length > 0) return anchors[0].name;
+    for (var i = 0; i < anchors.length; i++) {
+        if (anchors[i].name) { return anchors[i].name; }
+    }
+
     if (ifexists) return;
 
     var anchor = Sarissa.getText(node, true).strip().truncate(40).

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	Tue Mar 25 14:07:28 2008
@@ -162,6 +162,11 @@
 //
 function XhtmlValidation(editor) {
     // Support functions
+    function asList(s) {
+        if (typeof(s)==typeof('') || !s.length) s = [s];
+        return s;
+    }
+
     this.Set = function(ary) {
         if (typeof(ary)==typeof('')) ary = [ary];
         if (ary instanceof Array) {
@@ -175,7 +180,7 @@
             }
         }
     };
-
+    
     this._exclude = function(array, exceptions) {
         var ex;
         if (exceptions.split) {
@@ -312,7 +317,7 @@
         this.misc = ['noscript'].concat(this.misc_inline);
         this.inline = ['a'].concat(this.special, this.fontstyle, this.phrase, this.inline_forms);
 
-        this.Inline = ['#text'].concat(this.inline, this.misc_inline);
+        this.Inline = ['#text', '#comment'].concat(this.inline, this.misc_inline);
 
         this.heading = ['h1','h2','h3','h4','h5','h6'];
         this.lists = ['ul','ol','dl','menu','dir'];
@@ -446,7 +451,7 @@
     // Permitted elements for style.
     this.styleWhitelist = new this.Set(['text-align', 'list-style-type', 'float']);
     this.classBlacklist = new this.Set(['MsoNormal', 'MsoTitle', 'MsoHeader', 'MsoFootnoteText',
-        'Bullet1', 'Bullet2']);
+        'Bullet1', 'Bullet2', 'Apple-span-style']);
 
     this.classFilter = function(value) {
         var classes = value.split(' ');
@@ -462,8 +467,11 @@
     this._defaultCopyAttribute = function(name, htmlnode, xhtmlnode) {
         var val = htmlnode.getAttribute(name);
         if (val) xhtmlnode.setAttribute(name, val);
+        return !!val;
     };
     // Set up filters for attributes.
+    // Filters may return false if nothing was copied, true or
+    // undefined if an attribute was copied.
     var filter = this;
     this.attrFilters = new function(validation, editor) {
         var attrs = validation.elements.attributes;
@@ -474,10 +482,12 @@
             var val = htmlnode.getAttribute('class');
             if (val) val = validation.classFilter(val);
             if (val) xhtmlnode.setAttribute('class', val);
+            return !!val;
         };
         // allow a * wildcard to make all attributes valid in the filter
         // note that this is pretty slow on IE
         this['*'] = function(name, htmlnode, xhtmlnode) {
+            var res = false;
             var nodeName = filter._getTagName(htmlnode);
             var bad = filter.badTagAttributes[nodeName];
             for (var i=0; i < htmlnode.attributes.length; i++) {
@@ -488,8 +498,10 @@
                 };
                 if (attr.specified) {
                     xhtmlnode.setAttribute(name, attr.value);
+                    res = true;
                 };
             };
+            return res;
         };
         if (editor.getBrowserName()=="IE") {
             this['class'] = function(name, htmlnode, xhtmlnode) {
@@ -502,26 +514,33 @@
                     if (val) val = validation.classFilter(val);                        
                     if (val) xhtmlnode.setAttribute('class', val);
                 }
+                return !!val;
             };
             this['http-equiv'] = function(name, htmlnode, xhtmlnode) {
                 var val = htmlnode.httpEquiv;
                 if (val) xhtmlnode.setAttribute('http-equiv', val);
+                return !!val;
             };
             this['xml:lang'] = this['xml:space'] = function(name, htmlnode, xhtmlnode) {
                 try {
                     var val = htmlnode.getAttribute(name);
                     if (val) xhtmlnode.setAttribute(name, val);
+                    return !!val;
                 } catch(e) {
                 }
             };
         }
         this.alt = function(name, htmlnode, xhtmlnode) {
             var val = htmlnode.getAttribute(name);
-            if (val || xhtmlnode.tagName=='img') xhtmlnode.setAttribute(name, val);
+            var ok = val || xhtmlnode.tagName=='img';
+            if (ok) xhtmlnode.setAttribute(name, val);
+            return ok;
         };
         this.rowspan = this.colspan = function(name, htmlnode, xhtmlnode) {
             var val = htmlnode.getAttribute(name);
-            if (val && val != '1') xhtmlnode.setAttribute(name, val);
+            var ok = val && val != '1';
+            if (ok) xhtmlnode.setAttribute(name, val);
+            return ok;
         };
         this.style = function(name, htmlnode, xhtmlnode) {
             var val = htmlnode.style.cssText;
@@ -538,8 +557,9 @@
                 }
                 if (styles[styles.length-1]) styles.push('');
                 val = styles.join('; ').strip();
-            }
+            };
             if (val) xhtmlnode.setAttribute('style', val);
+            return !!val;
         };
     }(this, editor);
 
@@ -557,20 +577,19 @@
             this.excludeTags(exclude.t);
         }
         if (exclude.c) {
-            var c = exclude.c;
-            if (!c.length) c = [c];
+            var c = asList(exclude.c);
             for (var i = 0; i < c.length; i++) {
                 this.excludeTagAttributes(c[i].t, c[i].a);
             }
         }
         if (exclude.xstyle) {
-            var s = exclude.xstyle;
+            var s = asList(exclude.xstyle);
             for (var i = 0; i < s.length; i++) {
                 this.styleWhitelist[s[i]] = 1;
             }
         }
         if (exclude['class']) {
-            var c = exclude['class'];
+            var c = asList(exclude['class']);
             for (var i = 0; i < c.length; i++) {
                 this.classBlacklist[c[i]] = 1;
             }
@@ -578,18 +597,25 @@
     };
 
     // Copy all valid attributes from htmlnode to xhtmlnode.
+    // Returns true if at least one attribute was copied.
     this._copyAttributes = function(htmlnode, xhtmlnode, valid) {
         var name;
+        var res = false;
         if (valid.contains('*')) {
             // allow all attributes on this tag
-            this.attrFilters['*'](name, htmlnode, xhtmlnode);
-            return;
-        };        
-        for (var i = 0; i < valid.length; i++) {
-            name = valid[i];
-            var filter = this.attrFilters[name];
-            if (filter) filter(name, htmlnode, xhtmlnode);
+            res = this.attrFilters['*'](name, htmlnode, xhtmlnode);
+            if (res===undefined) res = true;
+        } else {
+            for (var i = 0; i < valid.length; i++) {
+                name = valid[i];
+                var filter = this.attrFilters[name];
+                if (filter) {
+                    var f = filter(name, htmlnode, xhtmlnode);
+                    res|=(f||f===undefined);
+                }
+            };
         }
+        return res;
     };
     this._xmlCopyAttr = function(srcnode, target) {
         var valid = this.tagAttributes[srcnode.nodeName];
@@ -705,7 +731,10 @@
             } catch (e) { };
             
             if (validattrs && xhtmlnode) {
-                this._copyAttributes(htmlnode, xhtmlnode, validattrs);
+                if (!this._copyAttributes(htmlnode, xhtmlnode, validattrs) && nodename=='span') {
+                    parentnode = xhtmlparent;
+                    xhtmlnode = null;
+                }
             }
         }
 
@@ -744,6 +773,8 @@
                     if (nostructure || permittedChildren['#text']) {
                         parentnode.appendChild(ownerdoc.createCDATASection(kid.nodeValue));
                     }
+                } else if (kid.nodeType == 8) {
+                    parentnode.appendChild(ownerdoc.createComment(kid.nodeValue));
                 }
             }
         } 

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	Tue Mar 25 14:07:28 2008
@@ -5,7 +5,7 @@
  * This software is distributed under the terms of the Kupu
  * License. See LICENSE.txt for license text. For a list of Kupu
  * Contributors see CREDITS.txt.
- * 
+ *
  *****************************************************************************/
 // $Id$
 
@@ -21,7 +21,7 @@
     */
     this.drawers = {};
     this.current_drawer = null;
-    
+
     this.initialize = function(editor) {
         this.editor = editor;
         this.isIE = this.editor.getBrowserName() == 'IE';
@@ -84,7 +84,7 @@
 
 proto.createContent = function() {
     /* fill the drawer with some content */
-    // here's where any intelligence and XSLT transformation and such 
+    // here's where any intelligence and XSLT transformation and such
     // is done
     this.element.style.display = 'block';
     this.focusElement();
@@ -242,7 +242,7 @@
 };
 
 proto.anchorText = function(a) {
-    // Text inside anchor, or immediate sibling block tag, or parent block. 
+    // Text inside anchor, or immediate sibling block tag, or parent block.
     var blocktag = /^div|p|body|td|h.$/i;
     var txt = '';
     var prefix = '#' + a.name;
@@ -315,7 +315,7 @@
 function LinkDrawer(elementid, tool) {
     /* Link drawer */
     DrawerWithAnchors.call(this, elementid, tool);
-    
+
     var input = getBaseTagClass(this.element, 'input', 'kupu-linkdrawer-input');
     var embed = getBaseTagClass(this.element, 'textarea', 'kupu-embed-input');
     var preview = getBaseTagClass(this.element, 'iframe', 'kupu-linkdrawer-preview');
@@ -324,11 +324,16 @@
     this.anchorui = getBaseTagClass(this.element, 'tr', 'kupu-linkdrawer-anchors');
     this.target = '';
     this.panel = getBaseTagClass(this.element, 'div', 'kupu-panels');
-    var tabs = getBaseTagClass(this.element, 'ul', 'kupu-tabs').getElementsByTagName('a');
-    for (var i = 0; i < tabs.length; i++) {
-        addEventHandler(tabs[i], 'click', this.switchMode, this);
+    var kuputabs = getBaseTagClass(this.element, 'ul', 'kupu-tabs');
+    if (kuputabs) {
+	var tabs = kuputabs.getElementsByTagName('a');
+	for (var i = 0; i < tabs.length; i++) {
+            addEventHandler(tabs[i], 'click', this.switchMode, this);
+	}
+    }
+    if (embed) {
+	addEventHandler(embed, 'click', function() { if(embed.defaultValue==embed.value) {embed.select();} });
     }
-    addEventHandler(embed, 'click', function() { if(embed.defaultValue==embed.value) {embed.select();} });
 
     this.selChange = function() {
         var anchor = this.getFragment();
@@ -403,7 +408,7 @@
         var current = bits.length > 1 ? bits[bits.length-1] : '';
         return current;
     }
-    
+
     this.getMode = function() {
         return !!(/addlink/.test(this.panel.className));
     };
@@ -489,7 +494,7 @@
         };
         fixClasses(addclassselect);
         fixClasses(editclassselect);
-        
+
         var table = editor.getNearestParentOfType(selNode, 'table');
         var show, hide;
         if (!table) {
@@ -578,11 +583,11 @@
 TableDrawer.prototype = new Drawer;
 
 function LibraryDrawer(tool, xsluri, libsuri, searchuri, baseelement, selecturi) {
-    /* a drawer that loads XSLT and XML from the server 
+    /* a drawer that loads XSLT and XML from the server
        and converts the XML to XHTML for the drawer using the XSLT
 
        there are 2 types of XML file loaded from the server: the first
-       contains a list of 'libraries', partitions for the data items, 
+       contains a list of 'libraries', partitions for the data items,
        and the second a list of data items for a certain library
 
        all XML loading is done async, since sync loading can freeze Mozilla
@@ -626,17 +631,17 @@
         this.libsuri = libsuri;
         this.searchuri = searchuri;
         this.selecturi = selecturi;
-        
+
         // marker that gets set when a new image has been uploaded
         this.shared.newimages = null;
 
         // the following vars will be available after this.initialize()
         // has been called
-    
+
         // this will be filled by this._libXslCallback()
         this.shared.xsl = null;
-        // this will be filled by this.loadLibraries(), which is called 
-        // somewhere further down the chain starting with 
+        // this will be filled by this.loadLibraries(), which is called
+        // somewhere further down the chain starting with
         // this._libsXslCallback()
         this.xmldata = null;
 
@@ -663,7 +668,7 @@
 
     this._libsXslCallback = function(dom) {
         /* callback for when the xsl for the libs is loaded
-        
+
             this is called on init and since the initial libs need
             to be loaded as well (and everything is async with callbacks
             so there's no way to wait until the XSL is loaded) this
@@ -672,7 +677,7 @@
         this.shared.xsl = dom;
         Sarissa.getDomDocument(); /* Work round Sarissa initialisation glitch */
 
-        // Change by Paul to have cached xslt transformers for reuse of 
+        // Change by Paul to have cached xslt transformers for reuse of
         // multiple transforms and also xslt params
         try {
             var xsltproc =  new XSLTProcessor();
@@ -715,8 +720,8 @@
         }
         // load the initial XML
         if(!this.xmldata) {
-            // Do a meaningful test to see if this is IE5.5 or some other 
-            // editor-enabled version whose XML support isn't good enough 
+            // Do a meaningful test to see if this is IE5.5 or some other
+            // editor-enabled version whose XML support isn't good enough
             // for the drawers
             if (!window.XSLTProcessor) {
                alert("This function requires better XML support in your browser.");
@@ -862,7 +867,7 @@
     this.selectLibrary = function(id) {
         /* unselect the currently selected lib and select a new one
 
-            the selected lib (libraries pane) will have a specific CSS class 
+            the selected lib (libraries pane) will have a specific CSS class
             (selected)
         */
         // remove selection in the DOM
@@ -882,7 +887,7 @@
 
         var items_xpath = "items";
         var items_node = libnode.selectSingleNode(items_xpath);
-        
+
         if (items_node && !this.shared.newimages) {
             // The library has already been loaded before or was
             // already provided with an items list. No need to do
@@ -901,7 +906,7 @@
         };
     };
     this.flagSelectedLib = function(id) {
-        // instead of running the full transformations again we get a 
+        // instead of running the full transformations again we get a
         // reference to the element and set the classname...
         var newseldiv = document.getElementById(id);
         if (newseldiv) {
@@ -1011,7 +1016,7 @@
 
         // First turn off current selection, if any
         this.removeSelection();
-        
+
         var leafnode_path = "//"+tag+"[@id='" + id + "']";
         var leafnode = this.xmldata.selectSingleNode(leafnode_path);
 
@@ -1108,7 +1113,7 @@
     this.removeSelection = function() {
         // Mark the drawer as having no selection
         if (!this.xmldata) return;
-        
+
         if (!this.multiple) {
             var items = this.xmldata.selectNodes('//resource[@checked]');
             for (var i = 0; i < items.length; i++) {
@@ -1294,7 +1299,7 @@
         // library as selected
         this.deselectActiveCollection();
         resultlib.setAttribute("selected", "1");
-        
+
         // now hook the result library into our DOM
         if (this.editor.getBrowserName() == 'IE') {
             resultlib = resultlib.cloneNode(true);
@@ -1330,7 +1335,7 @@
             with the DOM as the first argument and the uri loaded
             as the second
 
-            note that this method should be called in the context of an 
+            note that this method should be called in the context of an
             xmlhttp object
         */
             if (xmlhttp.readyState == 4) {
@@ -1427,7 +1432,7 @@
         }
         ImageLibraryDrawer.prototype.createContent.call(this);
     };
-    
+
     // upload, on submit/insert press
     this.uploadImage = function() {
         var form = document.getElementById('kupu_upload_form');
@@ -1435,34 +1440,55 @@
 
         if (form.node_prop_title.value == "") {
             alert("Please enter a title for the image you are uploading");
-            return;        
+            return;
         };
+        this.upload_title = form.node_prop_title.value;
         form.node_prop_desc.value = form.node_prop_desc.value.replace(/^\xa0|\xa0$/g,'');
         form.submit();
     };
-    
+
     // called for example when no permission to upload for some reason
     this.cancelUpload = function(msg) {
-        var s = this.xmldata.selectSingleNode('/libraries/*[@selected]');     
+        var s = this.xmldata.selectSingleNode('/libraries/*[@selected]');
         s.removeAttribute("selected");
         this.updateDisplay();
         if (msg != '') {
             alert(msg);
         };
     };
-    
+
     // called by onLoad within document sent by server
-    this.finishUpload = function(url) {
+    this.finishUpload = function(uri) {
         this.editor.resumeEditing();
-        var imgclass = 'image-inline';
-        if (this.editor.config && !!this.editor.config.captions) {
+        var sizeselector = document.getElementsByName('image-size-selector');
+        if (sizeselector && sizeselector.length > 0) {
+            sizeselector = sizeselector[0];
+            uri += sizeselector.options[sizeselector.selectedIndex].value;
+        }
+        var radios = document.getElementsByName('image-align');
+        var imgclass = "";
+        for (var i = 0; i < radios.length; i++) {
+            if (radios[i].checked) {
+                imgclass = radios[i].value;
+            };
+        };
+        var caption = document.getElementsByName('image-caption');
+        if (caption && caption.length>0 && caption[0].checked) {
             imgclass += " captioned";
         };
-        this.tool.createImage(url, null, imgclass);
+        var classnames = document.getElementById('kupu-image-class');
+        if (classnames && classnames.selectedIndex >= 0) {
+            imgclass += " "+classnames.options[classnames.selectedIndex].value;
+        } else {
+            imgclass += ' image-inline';
+        }
+        imgclass = imgclass.strip();
+
+        this.tool.createImage(uri, this.upload_title, imgclass);
         this.shared.newimages = 1;
         this.drawertool.closeDrawer();
     };
-    
+
 
     this.save = function() {
         this.editor.resumeEditing();
@@ -1470,7 +1496,7 @@
            from the drawer */
         var selxpath = '//resource[@selected]';
         var selnode = this.xmldata.selectSingleNode(selxpath);
-        
+
         // If no image resource is selected, check for upload
         if (!selnode) {
             var uploadbutton = this.xmldata.selectSingleNode("/libraries/*[@selected]//uploadbutton");
@@ -1565,7 +1591,7 @@
         var name = getFromSelector('link_name').value;
         var node = getFromSelector('link_target');
         var target = node && node.value;
-        
+
         this.tool.createLink(uri, null, name, target, title, 'internal-link');
         this.drawertool.closeDrawer();
     };
@@ -1672,12 +1698,12 @@
             };
             var div = el('div', {className: "kupu-bm-level" + paras[i][1] },
                 [el('label', inner)]);
-            
+
             this.paralist.appendChild(div);
         };
     };
     this.createContent = function() {
-        this.fillList(); 
+        this.fillList();
         this.element.style.display = 'block';
         this.focusElement();
     };
@@ -1685,7 +1711,7 @@
         var mode = this.getMode();
         var selected = this.paralist.getElementsByTagName('input');
         var ed = this.editor;
-        
+
         ed.resumeEditing();
 
         if (mode==2) {

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	Tue Mar 25 14:07:28 2008
@@ -341,8 +341,7 @@
        </xsl:choose>
     </xsl:template>
 
-    <xsl:template match="resource|collection" mode="image-properties">
-       <xsl:apply-templates select="." mode="base-properties"/>
+    <xsl:template match="resource|collection|uploadbutton" mode="image-extra-properties">
        <div class="kupu-image-fields">
           <input id="kupu-media" type="hidden" value="{media}" />
           <input id="kupu-width" type="hidden" value="{width}" />
@@ -429,6 +428,10 @@
           </textarea>
        </div>
     </xsl:template>
+    <xsl:template match="resource|collection" mode="image-properties">
+       <xsl:apply-templates select="." mode="base-properties"/>
+       <xsl:apply-templates select="." mode="image-extra-properties"/>
+    </xsl:template>
     <xsl:template match="class">
        <option value="{@name}">
           <xsl:if test="$image-class=@name">
@@ -527,6 +530,7 @@
             </form>
             <iframe id="kupu_upload_form_target" name="kupu_upload_form_target" src="javascript:''"
                 scrolling="off" frameborder="0" width="0px" height="0px" display="None">&#160;</iframe>
+            <xsl:apply-templates select="." mode="image-extra-properties"/>
     </xsl:template>
     <xsl:template match="breadcrumbs">
         <span>

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	Tue Mar 25 14:07:28 2008
@@ -505,21 +505,64 @@
         */
     };
 
+    // Fixup Mozilla breaking image src url when dragging images
+    this.imageInserted = function(event) {
+        var node = event.target;
+        if (node && node.nodeType==1) {
+            var nodes = (/^img$/i.test(node.nodeName))?[node]:node.getElementsByTagName('img');
+            for (var i = 0; i < nodes.length; i++) {
+                node = nodes[i];
+                var src = node.getAttribute('kupu-src');
+                if (src) { node.src = src; };
+            };
+        };
+    };
+    // Prevent Mozilla resizing of images
+    this.imageModified = function(event) {
+        var node = event.target;
+        if (node && /^img$/i.test(node.nodeName)) {
+            if (event.attrName=="style" && event.attrChange==1 && /height|width/.test(event.newValue)) {
+                timer_instance.registerFunction(this, this._clearStyle, 1, node);
+            }
+        };
+    };
+    // Make sure image size is set on width/height attributes not style.
+    this._clearStyle = function(node) {
+        var w = node.width;
+        var h = node.height;
+        node.style.width = "";
+        node.style.height = "";
+        if (this.okresize) {
+            if (w) {node.width = w;};
+            if (h) {node.height = h;};
+        };
+    };
+    this._cancelResize = function(evt) {
+        return false;
+    };
+
     this._initializeEventHandlers = function() {
         /* attache the event handlers to the iframe */
         var win = this.getDocument().getWindow();
         var idoc = this.getInnerDocument();
+        var e = this._addEventHandler;
+        var validattrs =  this.xhtmlvalid.tagAttributes['img'];
+        this.okresize = validattrs.contains('width') && validattrs.contains('height');
         // Set design mode on resize event:
-        this._addEventHandler(win, 'resize', this._resizeHandler, this);
+        e(win, 'resize', this._resizeHandler, this);
         // Initialize DOM2Event compatibility
         // XXX should come back and change to passing in an element
-        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);
+        e(idoc, "click", this.updateStateHandler, this);
+        e(idoc, "dblclick", this.updateStateHandler, this);
+        e(idoc, "keyup", this.updateStateHandler, this);
+        e(idoc, "keyup", function() {this.content_changed = true;}, this);
+        e(idoc, "mouseup", this.updateStateHandler, this);
         if (this.getBrowserName() == "IE") {
-            this._addEventHandler(idoc, "selectionchange", this.onSelectionChange, this);
+            e(idoc, "selectionchange", this.onSelectionChange, this);
+            if (!this.okresize) { e(idoc.documentElement, "resizestart", this._cancelResize, this);};
+        } else {
+            e(idoc, "DOMNodeInserted", this.imageInserted, this);
+            e(idoc, "DOMAttrModified", this.imageModified, this);
         }
     };
 
@@ -595,6 +638,8 @@
     };
 
     this._isDocumentSelected = function() {
+        if (this.suspended) return false;
+
         var editable_body = this.getInnerDocument().getElementsByTagName('body')[0];
         try {
             var selrange = this.getInnerDocument().selection.createRange();
@@ -652,20 +697,27 @@
 
     // If we have multiple bodies this needs to remove the extras.
     this.setHTMLBody = function(text) {
-        var bodies = this.getInnerDocument().documentElement.getElementsByTagName('body');
+        var doc = this.getInnerDocument().documentElement;
+        var bodies = doc.getElementsByTagName('body');
         for (var i = 0; i < bodies.length-1; i++) {
             bodies[i].parentNode.removeChild(bodies[i]);
         }
         if (!_SARISSA_IS_IE) { /* Mozilla doesn't understand strong/em */
             var fixups = { 'strong':'b', 'em':'i' };
 
-            text = text.replace(/<(\/?)(strong|em)>/gi, function(all,close,tag) {
+            text = text.replace(/<(\/?)(strong|em)\b([^>]*)>/gi, function(all,close,tag,attrs) {
                 tag = fixups[tag.toLowerCase()];
-                return '<'+close+tag+'>';
+                return '<'+close+tag+attrs+'>';
             });
         };
         text = text.replace(/<p>(<hr.*?>)<\/p>/g,'$1');
         bodies[bodies.length-1].innerHTML = text;
+        /* Mozilla corrupts dragged images, so save the src attribute */
+        var nodes = doc.getElementsByTagName('img');
+        for (var i = 0; i < nodes.length; i++) {
+            var node = nodes[i];
+            node.setAttribute('kupu-src', node.src);
+        };
     };
 
     this._fixXML = function(doc, document) {
@@ -845,15 +897,14 @@
         if (!this.suspended) {
             return;
         }
-        this.suspended = false;
         this.clearClass('kupu-modal');
         for (var id in this.tools) {
             this.tools[id].enable();
         }
         if (this.getBrowserName() == "IE") {
             var body = this.getInnerDocument().getElementsByTagName('body')[0];
-            this._restoreSelection();
             body.setAttribute('contentEditable', 'true');
+            this._restoreSelection();
         } else {
             var doc = this.getInnerDocument();
             this.getDocument().execCommand('contentReadOnly', 'false');
@@ -861,6 +912,7 @@
             this.focusDocument();
             this.getSelection().restoreRange(this._previous_range);
         }
+        this.suspended = false;
     };
     this.newElement = function(tagName) {
         return newDocumentElement(this.getInnerDocument(), tagName, arguments);

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	Tue Mar 25 14:07:28 2008
@@ -458,8 +458,9 @@
 };
 
 function MozillaSelection(document) {
+    var win = document.getWindow();
     this.document = document;
-    this.selection = document.getWindow().getSelection();
+    this.selection = win.getSelection();
 
     this._createRange = function() {
         return this.document.getDocument().createRange();
@@ -573,7 +574,7 @@
             // JavaScript isn't as nice as Python in that respect (kwargs)
             // if selectAfterPlace is a DOM node, select all of that node's
             // contents, else select the newly added node's
-            this.selection = this.document.getWindow().getSelection();
+            this.selection = win.getSelection();
             this.selection.addRange(range);
             if (selectAfterPlace.nodeType == 1) {
                 this.selection.selectAllChildren(selectAfterPlace);
@@ -587,7 +588,7 @@
                     this.selection.addRange(range);
                 };
             };
-            this.document.getWindow().focus();
+            win.focus();
         };
         return node;
     };
@@ -965,7 +966,7 @@
     };
 
     this.reset = function() {
-        this.selection = this.document.getWindow().getSelection();
+        this.selection = win.getSelection();
     };
 
     this.cloneContents = function() {
@@ -1007,8 +1008,8 @@
     };
 
     //sample kindly snipped from Mozilla's wiki
-    if( !Range.prototype.intersectsNode ){
-        Range.prototype.intersectsNode = function(node) {
+    if( !win.Range.prototype.intersectsNode ){
+        win.Range.prototype.intersectsNode = function(node) {
             var nodeRange = node.ownerDocument.createRange();
             try {
                 nodeRange.selectNode(node);
@@ -1030,8 +1031,8 @@
         };
         return false;
     };
-    if( !Range.prototype.containsNode ){
-        Range.prototype.containsNode = function(node) {
+    if( !win.Range.prototype.containsNode ){
+        win.Range.prototype.containsNode = function(node) {
             var nodeRange = node.ownerDocument.createRange();
             try {
                 nodeRange.selectNode(node);

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	Tue Mar 25 14:07:28 2008
@@ -464,7 +464,7 @@
         document.importNode = function(oNode, bChildren){
             var tmp;
             if (oNode.nodeName=='#text') {
-                return document.createTextElement(oNode.data);
+                return document.createTextNode(oNode.data);
             }
             else {
                 if(oNode.nodeName == "tbody" || oNode.nodeName == "tr"){

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	Tue Mar 25 14:07:28 2008
@@ -2,6 +2,81 @@
 Kupu changes
 ============
 
+- 1.4.9
+
+  - Manage anchors didn't add an anchor correctly if there was an
+    anchor used for a link inside the element.
+
+  - timte fixed a possible unicode decode error
+
+  - Image upload now has same style options as image insertion.
+
+  - Plone tickets
+
+    * 6915 Kupu can't find anchors inside table cells
+    * 7409 "edit without kupu" does not appear on edit form (the fix for this make the link appear but only in source mode).
+    * 7804 KupuLibraryTool spellcheck method is missing a docstring
+    * 7893 Workaround for bad KSS form submissions
+    * 7916 Kupu breaks strong/em tags with class names, on firefox
+    * 7939 Kupu breaks on Firefox 3.0b4 in OSX
+
+- 1.4.8
+
+  - Tabbing key now takes you to next/previous field. However, plone
+    ticket #7727 might result in tab behaviour changing again.
+
+  - Plone tickets
+
+    * 7473 Kupu full screen mode looks broken
+    * 7494 Insert internal link using IE links in the wrong place
+    * 7680 Kupu stripping out anchor to top of current page
+    * 7713 Kupu browser "Home" link goes to Plone root and not content
+      root.
+    * 7728 turning on "Link using UIDs" breaks indexing of rich text
+      fields that contain unicode characters out of the 128 range
+
+- 1.4.7
+
+  - Added metadata.xml file to the Plone GenericSetup profile.
+
+  - Style whitelist and class blacklist now work when there is only
+    one entry in the list.
+
+  - Span tags with no attributes after filtering are removed.
+
+- 1.4.6
+
+  - Fixed ReftextField error introduced in 1.4.5
+
+- 1.4.5
+
+  - Fixed unit tests for the transform (they now use a real image instead of a mockup)
+
+  - Fixed the transform to preserve links around images.
+
+  - Images may only be resized if 'height' and 'width' are permitted
+    image attributes. Resizing images in Firefox sets those
+    attributes rather than the style attribute.
+
+  - Plone tickets
+
+    * 5765 Kupu in IE unable to make a link from selected image
+    * 6430 Kupu: changes to images resized by handle-dragging are
+      lost (not saved)
+    * 6835 Drag image breaks in Kupu
+    * 7293 kupu import step has the wrong dependencies in a portal
+      setup export
+    * 7377 Making an Image a Link within Kupu renders the link tag at
+      the top of the content page
+    * 7387 Kupu-Commit Selected Changes button missing when
+      converting UID=>Relative Link
+    * 7426 Kupu 1.4.4 installed with Plone 3.0.3 for PowerPC presents
+      itself in Safari 3.0.4, but content in Kupu window can't be edited 
+    * 7428 Searching for non-ascii character in kupu Insert Link
+      dialog causes Error 500 
+    * 7419 Plone and/or Kupu should at least WARN an editor of an
+      image that changes may be lost at Save time
+
 - 1.4.4
 
   - Enabled Safari support (needs webkit nightly build and Safari 3)

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	Tue Mar 25 14:07:28 2008
@@ -501,6 +501,11 @@
             ),
         ),
 
+N.B. Toolbar buttons which are disabled in Plone's default
+configuration may represent tools which are not fully integrated into
+Plone. If you wish to use these tools and find problems with them you
+should submit a patch.
+
 Custom styles
 -------------
 Kupu allows you to specify styles for paragraphs (P or DIV tags),

Modified: kupu/branch/kupu-1.4/make-jspx.xsl
==============================================================================
--- kupu/branch/kupu-1.4/make-jspx.xsl	(original)
+++ kupu/branch/kupu-1.4/make-jspx.xsl	Tue Mar 25 14:07:28 2008
@@ -17,7 +17,7 @@
 This means that also the fmt-tags must be available, so your html.kupu must specificy something like:
   <kupu:part name="html">
     <html xmlns="http://www.w3.org/1999/xhtml"
-          xmlns:jsp="http://java.sun.com/JSP/Page" 
+          xmlns:jsp="http://java.sun.com/JSP/Page"
           xmlns:fmt="http://java.sun.com/jsp/jstl/fmt">
       <jsp:output doctype-root-element="html"
                   doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
@@ -33,14 +33,14 @@
 <xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:kupu="http://kupu.oscom.org/namespaces/dist"
-   xmlns:i18n="http://xml.zope.org/namespaces/i18n" 
+   xmlns:i18n="http://xml.zope.org/namespaces/i18n"
    xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
    xmlns:html="http://www.w3.org/1999/xhtml"
    xmlns:jsp="http://java.sun.com/JSP/Page"
    exclude-result-prefixes="kupu"
    version="1.0"
    >
-  <xsl:import href="make.xsl" />  
+  <xsl:import href="make.xsl" />
   <xsl:output
     method="xml"
     indent="no"
@@ -70,14 +70,14 @@
       </xsl:when>
       <xsl:when test="@i18n:attributes">
         <xsl:variable name="attributes"><xsl:value-of select="@i18n:attributes" /></xsl:variable>
-        <fmt:message var="_">
+        <fmt:message var="translation">
           <xsl:attribute name="key">
             <xsl:value-of select="@title" /><!-- should be @$attributes, but that doesn't work -->
           </xsl:attribute>
         </fmt:message>
         <xsl:element name="{name()}">
           <xsl:copy-of select="@html:*" />
-          <xsl:attribute name="{$attributes}">${_}</xsl:attribute>
+          <xsl:attribute name="title">${translation}</xsl:attribute>
           <xsl:apply-templates  mode="expand" />
         </xsl:element>
       </xsl:when>
@@ -105,7 +105,7 @@
       <xsl:apply-templates mode="expand" />
     </xsl:copy>
   </xsl:template>
-  
+
   <xsl:template match="text()" mode="expand-i18n">
     <!-- this should probably be trim() rather then normalize-space (but that functions does not natively exist) -->
     <xsl:value-of select="normalize-space(.)" />

Modified: kupu/branch/kupu-1.4/mmbase/body.kupu
==============================================================================
--- kupu/branch/kupu-1.4/mmbase/body.kupu	(original)
+++ kupu/branch/kupu-1.4/mmbase/body.kupu	Tue Mar 25 14:07:28 2008
@@ -20,7 +20,11 @@
     <mm:import id="back" externid="kupu_back">${header.referer}</mm:import>
     <mm:compare referid="objectnumber" value="new">
       <mm:import externid="referrer">${header.referer}</mm:import>
+      <mm:import externid="templates">${mm:directory(header.referer)}</mm:import>
       <mm:import id="wizardxml">${mm:directory(referrer)}/${param.wizard}.xml</mm:import>
+      <mm:haspage page="$wizardxml" inverse="true">
+        <mm:import id="wizardxml" reset="true">${templates}/${param.wizard}.xml</mm:import>
+      </mm:haspage>
       <mm:haspage page="$wizardxml">
         <mm:formatter id="type" write="false">
           <mm:include cite="true" page="${wizardxml}"/>
@@ -59,7 +63,7 @@
       </mm:present>
       <mm:import externid="link_nodetypes" />
       <mm:import externid="related_types" />
-      <mm:redirect referids="node at objectnumber,tools?,language?,origin?,nodetypes?,back at kupu_back,link_nodetypes?,related_types?" /> 
+      <mm:redirect referids="node at objectnumber,tools?,language?,origin?,nodetypes?,back at kupu_back,link_nodetypes?,related_types?" />
     </mm:compare>
     <mm:compare referid="objectnumber" value="new" inverse="true">
       <mm:node id="node" referid="objectnumber" />
@@ -78,7 +82,7 @@
 
   <kupu:part name="editorframe">
     <div class="kupu-editorframe">
-      <form>					
+      <form>
         <iframe id="kupu-editor"
                 class="kupu-editor-iframe"
                 frameborder="0"
@@ -88,7 +92,7 @@
           </jsp:text>
         </iframe>
         <textarea
-         class="kupu-editor-textarea" 
+         class="kupu-editor-textarea"
          id="kupu-editor-textarea"><jsp:text> </jsp:text></textarea>
       </form>
     </div>

Modified: kupu/branch/kupu-1.4/mmbase/html.kupu
==============================================================================
--- kupu/branch/kupu-1.4/mmbase/html.kupu	(original)
+++ kupu/branch/kupu-1.4/mmbase/html.kupu	Tue Mar 25 14:07:28 2008
@@ -7,7 +7,7 @@
   <kupu:id>$Id: html.kupu,v 1.14 2005/09/27 18:26:52 michiel Exp $</kupu:id>
   <kupu:part name="html">
     <html xmlns="http://www.w3.org/1999/xhtml"
-          xmlns:jsp="http://java.sun.com/JSP/Page" 
+          xmlns:jsp="http://java.sun.com/JSP/Page"
           xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
           xmlns:fn="http://java.sun.com/jsp/jstl/functions"
           xmlns:mm="http://www.mmbase.org/mmbase-taglib-2.0">
@@ -24,7 +24,7 @@
         <mm:param referid="org.mmbase.index-root" />
         <mm:write session="org.mmbase.index-root" referid="org.mmbase.index-root" />
         -->
-        <mm:import id="rich_language" externid="language" />
+        <mm:import id="rich_language" externid="language" from="parameters,request" />
         <mm:import externid="rich_language" from="this,session">client</mm:import>
         <mm:write session="rich_language" referid="rich_language" />
         <mm:write cookie="rich_language" referid="rich_language"/>

Modified: kupu/branch/kupu-1.4/mmbase/kupustyle.css
==============================================================================
--- kupu/branch/kupu-1.4/mmbase/kupustyle.css	(original)
+++ kupu/branch/kupu-1.4/mmbase/kupustyle.css	Tue Mar 25 14:07:28 2008
@@ -1,24 +1,24 @@
 @import url("../../style/css/mmxf.css");
-body { 
+body {
   background-color: white;
   font-size: 12pt;
 }
-h1,h2,h3,h4,h5,h6,h7,h8,th { 
+h1,h2,h3,h4,h5,h6,h7,h8,th {
   font-weight: bold;
   color: #006;
 }
-h1 { 
+h1 {
   font-size: 15pt;
 }
-h2 { 
+h2 {
   padding-left: 1em;
   font-size: 14pt;
 }
-h3 { 
+h3 {
   padding-left: 2em;
   font-size: 13pt;
 }
-h4 { 
+h4 {
   padding-left: 3em;
   font-size: 12pt;
   margin-top: 0px;
@@ -27,7 +27,7 @@
   padding-bottom: 0px;
 }
 
-h5, h6, h7, h8 { 
+h5, h6, h7, h8 {
   font-style: italic;
   font-size: 12pt;
   margin-top: 0px;
@@ -35,27 +35,27 @@
   padding-top: 0px;
   padding-bottom: 0px;
 }
-h5 { 
+h5 {
   padding-left: 4em;
 }
-h6 { 
+h6 {
   padding-left: 5em;
 }
-h7 { 
+h7 {
   padding-left: 6em;
 }
-h8 { 
+h8 {
   padding-left: 7em;
 }
 
-h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child, h7:first-child, h8:first-child { 
+h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child, h7:first-child, h8:first-child {
   margin-top: 0px;
 }
 
 p {
 }
 
-table { 
+table {
   border: 1px black solid;
   border-spacing: 0px;
   empty-cells: show;
@@ -63,58 +63,58 @@
   background-color: #fafafa;
 }
 
-.mmxf table.plain td, .mmxf table.data td { 
+.mmxf table.plain td, .mmxf table.data td {
   border: 1px gray solid;
 }
 
-th { 
+th {
   border: 1px black solid;
 }
 
-img.image-right { 
+img.image-right {
   width: 100px;
   float: right;
   margin-right: 0px;
   margin-left: 1ex;
 }
 
-img.image-left { 
+img.image-left {
   width: 100px;
   float: left;
   margin-left: 0px;
   margin-right: 1ex;
 }
 
-img.section-inline { 
+img.section-inline {
 }
 
-img.node { 
+img.node {
   float: left;
   border: solid 5px green;
 }
-img.paragraph { 
+img.paragraph {
   border: solid 1px green;
 }
-img.section { 
+img.section {
   float: left;
   border: solid 1px green;
 }
-img.big { 
+img.big {
   width: 200px;
   height: auto;
 }
 
-strong, b  { 
+strong, b  {
   color: green;
   font-weight: bold;
 }
 
-em, i { 
+em, i {
   font-style: italic;
 }
 
 
-div.float { 
+div.float {
   display: block;
   float: left;
   width: 200px;
@@ -123,28 +123,28 @@
   border: solid black 1px;
 }
 
-div.note { 
+div.note {
   background-color: #ffc;
   font-style: italic;
 }
-div.note i { 
+div.note i {
   font-style: normal;
 }
-div.note em { 
+div.note em {
   font-style: normal;
 }
 
-div.right { 
+div.right {
   margin-right: 0px;
   float: right;
 
 }
-div.left { 
+div.left {
   margin-left: 0px;
   float: left;
-} 
+}
 
-div.intermezzo  { 
+div.intermezzo  {
   float: left;
   margin-left: 0px;
   margin-right: 2ex;
@@ -152,18 +152,19 @@
   background-color: #cfc;
   font-style: normal;
 }
-div.quote { 
+div.quote {
   background-color: #fcc !important;
   font-style: italic;
 }
 
-div.caption { 
+div.caption {
   background-color: #ddd;
 }
-ul, ol { 
+ul, ol {
   list-style-position: outside;
+  margin-left: 0ex;
+  padding-left: 0ex;
+}
+ul li, ol li {
+  margin-left: 3ex;
 }
-
-li { 
-  margin-left: 20px;
-}
\ No newline at end of file

Modified: kupu/branch/kupu-1.4/mmbase/mmbase.kupu
==============================================================================
--- kupu/branch/kupu-1.4/mmbase/mmbase.kupu	(original)
+++ kupu/branch/kupu-1.4/mmbase/mmbase.kupu	Tue Mar 25 14:07:28 2008
@@ -58,16 +58,10 @@
               <mm:compare referid="rich_language" value="client" inverse="true">
                 <option value="client"><fmt:message key="default" /></option>
               </mm:compare>
-              <mm:import id="languages" vartype="list">en,zh,ja,de,fr,pt,nl,da,cs,fi,el,sr,eo</mm:import>
+              <mm:import id="languages" vartype="list">en,zh,ja,de,fr,pt,nl,da,cs,fi,el,sr,eo,hi</mm:import>
               <mm:stringlist referid="languages">
-                <mm:locale language="${_}" jspvar="locale">
-                  <mm:compare referid2="rich_language">
-                    <option value="${_}" selected="selected"><jsp:expression>locale.getDisplayName(locale)</jsp:expression></option>
-                  </mm:compare>
-                  <mm:compare referid2="rich_language" inverse="true">
-                    <option value="${_}"><jsp:expression>locale.getDisplayName(locale)</jsp:expression></option>
-                  </mm:compare>
-                </mm:locale>
+                <mm:import id="gui"><mm:locale language="${_}" jspvar="locale"><jsp:expression>locale.getDisplayName(locale)</jsp:expression></mm:locale></mm:import>
+                <mm:option value="${_}" compare="${rich_language}">${gui}</mm:option>
               </mm:stringlist>
             </select>
           </form>

Modified: kupu/branch/kupu-1.4/mmbase/node.jspx
==============================================================================
--- kupu/branch/kupu-1.4/mmbase/node.jspx	(original)
+++ kupu/branch/kupu-1.4/mmbase/node.jspx	Tue Mar 25 14:07:28 2008
@@ -22,7 +22,8 @@
 
           <mm:param name="org.mmbase.xml-mode" value="kupu" />
           <mm:node id="node" referid="node">
-            <div class="node" title="${node.number} ${node.title}">
+            <mm:import id="gui" escape="tagstripper(NONE)"><mm:nodeinfo type="gui" /></mm:import>
+            <div class="node" title="${node.number} ${gui}">
               <mm:notpresent referid="loadonly">
                 <table>
                   <tr>
@@ -60,4 +61,4 @@
       </fmt:bundle>
     </mm:cloud>
   </mm:locale>
-</mm:content>
\ No newline at end of file
+</mm:content>

Modified: kupu/branch/kupu-1.4/mmbase/toolboxes.kupu
==============================================================================
--- kupu/branch/kupu-1.4/mmbase/toolboxes.kupu	(original)
+++ kupu/branch/kupu-1.4/mmbase/toolboxes.kupu	Tue Mar 25 14:07:28 2008
@@ -14,16 +14,16 @@
 
   <kupu:part name="images">
     <div class="kupu-toolbox" id="kupu-toolbox-images">
-      <h1  class="kupu-toolbox-heading" i18n:translate="">Images</h1>
+      <h1 class="kupu-toolbox-heading" i18n:translate="title_images">Images</h1>
       <div>
         <div class="kupu-toolbox-label">
-          <span i18n:translate="">Image class:</span>
+          <span i18n:translate="label_image_class">Image class:</span>
         </div>
         <select class="wide" id="kupu-image-float-select">
-          <option value="image-inline" i18n:translate="">Inline</option>
-          <option value="image-left"   i18n:translate="">Left</option>
-          <option value="image-right"  i18n:translate="">Right</option>
-          <fmt:bundle basename="org.mmbase.kupu.Messages">             
+          <option value="image-inline" i18n:translate="opt_inline">Inline</option>
+          <option value="image-left" i18n:translate="opt_left">Left</option>
+          <option value="image-right" i18n:translate="opt_right">Right</option>
+          <fmt:bundle basename="org.mmbase.kupu.Messages">
             <option value="image-left big" ><fmt:message key="Left (Big)" /></option>
             <option value="image-right big"><fmt:message key="Right (Big)" /></option>
             <option value="image-center big"><fmt:message key="Big" /></option>
@@ -41,7 +41,7 @@
                  value="kupuimages/kupu_icon.gif"
                  class="wide"
                  type="text" />
-          
+
           <div class="kupu-toolbox-buttons">
             <button type="button" id="kupu-image-addbutton"
                     class="kupu-toolbox-action" i18n:translate="">Insert Image</button>
@@ -54,7 +54,7 @@
   <kupu:part name="divs">
     <div class="kupu-toolbox" id="kupu-toolbox-divs">
       <fmt:bundle basename="org.mmbase.kupu.Messages">
-        <h1  class="kupu-toolbox-heading"><fmt:message key="Block" /></h1>        
+        <h1  class="kupu-toolbox-heading"><fmt:message key="Block" /></h1>
         <div>
           <div class="kupu-toolbox-label">
             <span><fmt:message key="Block class" /></span>
@@ -80,12 +80,12 @@
   <!-- Overridden just for the jsp:text (to avoid that it collapses, which doesn't work in browers -->
   <kupu:part name="debug">
     <div class="kupu-toolbox" id="kupu-toolbox-debug">
-      <h1 class="kupu-toolbox-heading" i18n:translate="">Debug Log</h1>
+      <h1 class="kupu-toolbox-heading" i18n:translate="title_debug_log">Debug Log</h1>
       <div id="kupu-toolbox-debuglog"
            class="kupu-toolbox-label">
         <jsp:text> </jsp:text>
       </div>
     </div>
   </kupu:part>
-  
+
 </kupu:feature>

Modified: kupu/branch/kupu-1.4/plone/ReftextField.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/ReftextField.py	(original)
+++ kupu/branch/kupu-1.4/plone/ReftextField.py	Tue Mar 25 14:07:28 2008
@@ -1,16 +1,15 @@
 from AccessControl import ClassSecurityInfo
 from Products.Archetypes.public import *
+from Products.Archetypes.BaseUnit import BaseUnit
 from Products.Archetypes.config import REFERENCE_CATALOG
 from Products.Archetypes.Field import TextField
 from Products.Archetypes.ReferenceEngine import Reference
 from Products.Archetypes.exceptions import ReferenceException
 from ZPublisher.HTTPRequest import FileUpload
 from Products.CMFCore.utils import getToolByName
+from Products.kupu.plone.config import UID_PATTERN
 import re
 
-# UID_PATTERN matches a UID in an anchor or image tag.
-UID_PATTERN = re.compile(r'''<(?:a\b[^>]+href|img\b[^>]+src)="resolveuid/(?P<uid>[^?#">/]+)''', re.I)
-
 class ReftextField(TextField):
     __implements__ = TextField.__implements__
 
@@ -38,11 +37,15 @@
 
         TextField.set(self, instance, value, **kwargs)
 
+        if isinstance(value, BaseUnit):
+            # Baseunit: can occur when overriding atct text fields.
+            value = value()
         if not isinstance(value, basestring):
             value.seek(0);
             value = value.read()
 
-        uids = UID_PATTERN.findall(value) # XXX: build list of uids from the value here
+        # build list of uids from the value here
+        uids = [ m.group('uid') for m in UID_PATTERN.finditer(value) ]
         uids = dict.fromkeys(uids).keys() # Remove duplicate uids.
 
         tool = getToolByName(instance, REFERENCE_CATALOG)

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	Tue Mar 25 14:07:28 2008
@@ -65,15 +65,17 @@
 
   <kupu:part name="suppress-kupu">
     <div class="kupuoverride"
-        tal:condition="python:exists('kupu_content') and len(kupu_content)==0 and allowed and len(allowed)!=1"
+        tal:condition="python:exists('kupu_content') and allowed and len(allowed)!=1"
         tal:define="floated widget/allow_file_upload | python:1;
+                klass python:test(exists('kupu_content') and len(kupu_content), ' kupusourceoverride', '');
                 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;;', '');"
+        tal:attributes="style python:test(floated, 'float:left;;', '');class string:kupuoverride$klass"
       ><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};"
+        tal:define="fs fieldset|nothing;fs python:test(fs,'&amp;fieldset=%s'%fs,'');
+        editaction python:context.getActionInfo('object/edit')['url'];"
+        tal:attributes="href string:${editaction}?kupu.suppress=${fieldName}${fs};"
         title="reload current page without kupu">
          Edit without visual editor
       </a></span>

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	Tue Mar 25 14:07:28 2008
@@ -17,6 +17,8 @@
 from urllib import unquote_plus, quote_plus
 from Acquisition import aq_base
 from htmlentitydefs import name2codepoint
+from Products.kupu.plone.config import UID_PATTERN
+
 name2codepoint = name2codepoint.copy()
 name2codepoint['apos']=ord("'")
 
@@ -26,9 +28,9 @@
 # enclosed in a simple <p> or <div>. In the latter case we strip out
 # the enclosing tag since we are going to insert our own.
 PATIMG = '\\<img[^>]+class\s*=[^=>]*captioned[^>]+\\>'
-PATA = '(?:\\<a[^>]*\\>'+PATIMG+'\\</a\\>)' + '|' + PATIMG
-PAT0 = '('+PATA+')'
-PAT1 = '<(?:p|div)[^>]*>'+PAT0 + '</(?:p|div)>' + '|' + PAT0
+PATA = '(?:(?P<atag0>\\<a[^>]*\\>)'+PATIMG+'\\</a\\>)' + '|' + PATIMG
+PAT0 = '(?P<pat0>'+PATA+')'
+PAT1 = '<(?:p|div)[^>]*>'+PAT0 + '</(?:p|div)>' + '|' + PAT0.replace('0>','1>')
 IMAGE_PATTERN = re.compile(PAT1, re.IGNORECASE)
 
 # Regex to match stupid IE attributes. In IE generated HTML an
@@ -66,8 +68,6 @@
 </dl>
 '''
 
-UID_PATTERN = re.compile('(?P<tag><(?:a|img|object|param)\\s[^>]*(?:src|href|data|value)\s*=\s*")(?P<url>[^"]*resolveuid/(?P<uid>[^/"#? ]*))', re.DOTALL | re.IGNORECASE)
-
 class HTMLToCaptioned:
     """Transform which adds captions to images embedded in HTML"""
     __implements__ = itransform
@@ -122,8 +122,9 @@
 
         if context and at_tool:        
             def replaceImage(match):
-                tag = match.group(1) or match.group(2)
+                tag = match.group('pat0') or match.group('pat1')
                 attrs = ATTR_PATTERN.match(tag)
+                atag = match.group('atag0') or match.group('atag1')
                 src = attrs.group('src')
                 subtarget = None
                 m = SRC_TAIL.match(tag, attrs.end('src'))
@@ -142,7 +143,7 @@
                         d['caption'] = newline_to_br(html_quote(target.Description()))
                         d['image'] = d['fullimage'] = target
                         d['tag'] = None
-                        d['isfullsize'] = False
+                        d['isfullsize'] = True
                         d['width'] = target.width
                         if srctail:
                             if isinstance(srctail, unicode):
@@ -166,6 +167,10 @@
                             d['isfullsize'] = subtarget.width == target.width and subtarget.height == target.height
                             d['width'] = subtarget.width
 
+                        if atag: # Must preserve original link, don't overwrite with a link to the image
+                            d['isfullsize'] = True
+                            d['tag'] = "%s%s</a>" % (atag, d['tag'])
+
                         return template(**d)
                 return match.group(0) # No change
 
@@ -187,7 +192,8 @@
                 return match.group(0)
 
             html = UID_PATTERN.sub(replaceUids, html)
-            
+            if isinstance(html, unicode):
+                html = html.encode('utf8') # Indexing requires a string result.
             idata.setData(html)
             return idata
 
@@ -664,6 +670,9 @@
             if code:
                 return unichr(int(code, 16))
             else:
-                return unichr(name2codepoint[match.group(3)])
+                code = match.group(3)
+                if code in name2codepoint:
+                    return unichr(name2codepoint[code])
+        return match.group(0)
 
-    return EntityPattern.sub(unescape, s)
+    return EntityPattern.sub(unescape, s.decode(encoding))

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	Tue Mar 25 14:07:28 2008
@@ -16,7 +16,8 @@
 
       <body>
          <div metal:fill-slot="prefs_configlet_content" metal:define-slot="prefs_configlet_main"
-              tal:define="errors python:request.get('errors', {});">
+              tal:define="errors python:request.get('errors', {});"
+              id="content">
 
             <metal:styleslot define-slot="style_slot" />
 

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/convertContentForKupu.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/convertContentForKupu.py	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/convertContentForKupu.py	Tue Mar 25 14:07:28 2008
@@ -13,6 +13,13 @@
 text_format = context.REQUEST.get('%s_text_format' % fieldname, context.getContentType(fieldname))
 
 if len(content)==0 or 'html' in text_format.lower():
+    if isinstance(content, unicode):
+        try:
+            encoding = context.getCharset()
+        except AttributeError:
+            encoding = 'utf8'
+        content = content.encode(encoding)
+
     return str(content)
 
 transforms = getToolByName(context, 'portal_transforms')

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	Tue Mar 25 14:07:28 2008
@@ -16,18 +16,18 @@
     <!--$Id: toolboxes.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 47952 2007-10-25 15:40:31Z duncan $-->
+    <!--$Id: drawers.kupu 48419 2007-11-08 15:14:05Z duncan $-->
     <!--$Id: include.kupu 39202 2007-02-19 12:06:45Z duncan $-->
     <!--$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 47952 2007-10-25 15:40:31Z duncan $-->
+    <!--$Id: body.kupu 52772 2008-03-20 13:52:12Z 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 $-->
     <!--$Id: sourceedit.kupu 44538 2007-06-26 10:46:28Z duncan $-->
-    <!--$Id: wysiwyg_support.kupu 45010 2007-07-13 11:23:06Z duncan $-->
+    <!--$Id: wysiwyg_support.kupu 49390 2007-12-05 16:14:02Z duncan $-->
     
 
     <div xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:tal="http://xml.zope.org/namespaces/tal" metal:define-macro="wysiwygEditorBox" id="kupu-editor" tal:define="name fieldName|inputname;                 editorid string:kupu-editor-${name}" tal:attributes="id editorid">
@@ -483,7 +483,7 @@
     </textarea>
     </div>
   
-    <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">
+    <div class="kupuoverride" tal:condition="python:exists('kupu_content') and allowed and len(allowed)!=1" tal:define="floated widget/allow_file_upload | python:1;                 klass python:test(exists('kupu_content') and len(kupu_content), ' kupusourceoverride', '');                 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;;', '');class string:kupuoverride$klass"><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,'');         editaction python:context.getActionInfo('object/edit')['url'];" tal:attributes="href string:${editaction}?kupu.suppress=${fieldName}${fs};" title="reload current page without kupu">
          Edit without visual editor
       </a></span>
     </div>
@@ -504,6 +504,7 @@
   
     <textarea cols="80" rows="25" name="fieldName" tal:content="inputvalue" tal:attributes="name fieldName|inputname;                         id fieldName|inputname;                         onfocus onfocus|nothing;                         onblur onblur|nothing;                         rows rows|default;                         cols cols|default;">
     </textarea>
+     <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:archetypes tal:condition="fieldName|nothing">
       <div class="kupuoverride" tal:condition="python:path('widget/allow_format_edit|python:True') and not path('kupu_convert_message_generated|nothing')" tal:define="floated widget/allow_file_upload | python:1;" tal:attributes="style python:test(floated, 'float:left;;', '');">

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupucollection.xml.pt
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupucollection.xml.pt	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupucollection.xml.pt	Tue Mar 25 14:07:28 2008
@@ -91,8 +91,26 @@
       </collection>
 
     </tal:loop>
-    <uploadbutton tal:condition="python:exists('upload') and kupu.isUploadSupported(context)">
+    <uploadbutton tal:condition="python:exists('upload') and kupu.isUploadSupported(context)"
+                  tal:define="classes kupu/getUploadImageClasses;
+                  sizes kupu/getUploadImageSizes;
+                  defscale kupu/getDefaultScaleForType; origok kupu/getAllowOriginalImageSize;">
        <uri tal:content="string:${here/absolute_url}/kupuUploadImage" />
+       <class tal:condition="classes" tal:repeat="c classes"
+             tal:attributes="title c/title; name c/classname" />
+       <sizes>
+          <size tal:repeat="size sizes">
+             <selected tal:define="action size/action;"
+                    tal:condition="python:action==defscale" />
+             <label tal:content="size/label" />
+             <uri tal:content="size/uri" />
+          </size>
+          <size tal:condition="origok">
+             <selected tal:condition="python:defscale in ('original', '')" />
+             <label i18n:translate="option_original">Original</label>
+             <uri tal:content="info/url" />
+          </size>
+       </sizes>
     </uploadbutton>
   </items>
 

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	Tue Mar 25 14:07:28 2008
@@ -244,6 +244,9 @@
   font-size: 100%;
 }
 
+.kupusourceoverride { display: none; }
+.kupu-sourcemode .kupusourceoverride { display: block; margin: 0 0.5em; }
+
 div.kupuoverride {
     margin-left: 0.75em;
 }

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	Tue Mar 25 14:07:28 2008
@@ -66,7 +66,7 @@
                 path[i++] = '#';
             }
             str = path.join('/');
-            if (anchor) {
+            if (anchor || str=="") {
                 str = [str,anchor].join('#');
             }
             str = tag + str+'"';

Modified: kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuploneinit.js
==============================================================================
--- kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuploneinit.js	(original)
+++ kupu/branch/kupu-1.4/plone/kupu_plone_layer/kupuploneinit.js	Tue Mar 25 14:07:28 2008
@@ -201,6 +201,7 @@
             opt.selected = opt.defaultSelected = (opt.value=='text/html');
         }
         pulldown.disabled = true;
+        pulldown.removeAttribute('name');
         var hidden = document.createElement('input');
         hidden.type = 'hidden';
         hidden.name = fmtname;
@@ -292,21 +293,31 @@
         if (!(/kupu-fulleditor-zoomed/.test(document.body.className))) {
             var form = textarea.form;
             var els = form.elements;
-            var target, targindex;
-            var mytabindex = iframe.tabIndex;
-            for (var i = 0; i < els.length; i++) {
-                var el = els[i];
-                if (el.tabIndex && el.tabIndex > mytabindex && !el.disabled && el.offsetWidth && el.offsetHeight) {
-                    if (!targindex || el.tabIndex < targindex) {
+            var target;
+            if (event.shiftKey) { // shift-tab goes backwards.
+                for (var i = 0; i < els.length; i++) {
+                    var el = els[i];
+                    if (!el.disabled && el.offsetWidth && el.offsetHeight) {
                         target = el;
-                        targindex = el.tabIndex;
+                    }
+                    if (els[i]===textarea) break;
+                }
+            } else { // tab forwards
+                for (var i = 0; i < els.length; i++) {
+                    if (els[i]===textarea) break;
+                }
+                for (;i < els.length; i++) {
+                    var el = els[i];
+                    if (!el.disabled && el.offsetWidth && el.offsetHeight) {
+                        target = el;
+                        break;
                     }
                 }
             }
             if (target) {
                 window.focus();
                 target.focus();
-            }
+            } else { return; };
         }
         if (event.preventDefault) { event.preventDefault(); event.stopPropagation();}
         event.returnValue = false;

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	Tue Mar 25 14:07:28 2008
@@ -12,7 +12,8 @@
   <uri tal:content="template/absolute_url"/>
   <icon
        tal:content="searchlib/icon|string:${here/portal_url}/kupuimages/kupusearch_icon.gif"/>
-  <title tal:define="tpl searchlib/title|string:Search '$$';txt request/SearchableText;"
+  <title tal:define="tpl searchlib/title|string:Search '$$';txt request/form/SearchableText;
+         txt python:same_type(txt,'') and txt.decode('utf8') or txt;"
          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	Tue Mar 25 14:07:28 2008
@@ -88,9 +88,9 @@
 LIBRARIES = (
     dict(id="root",
          title="string:Home",
-         uri="string:${portal_url}",
-         src="string:${portal_url}/kupucollection.xml",
-         icon="string:${portal_url}/misc_/CMFPlone/plone_icon"),
+         uri="string:${globals_view/navigationRootUrl|portal_url}",
+         src="string:${globals_view/navigationRootUrl|portal_url}/kupucollection.xml",
+         icon="string:${globals_view/navigationRootUrl|portal_url}/misc_/CMFPlone/plone_icon"),
     dict(id="current",
          title="string:Current folder",
          uri="string:${folder_url}",

Modified: kupu/branch/kupu-1.4/plone/librarytool.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/librarytool.py	(original)
+++ kupu/branch/kupu-1.4/plone/librarytool.py	Tue Mar 25 14:07:28 2008
@@ -364,6 +364,9 @@
         return getattr(self, '_toolbar_filters', {})
 
     def spellcheck(self, REQUEST):
+        """Call spellchecker: WARNING this functionality may not work,
+        it is not part of the standard Plone+kupu implementation.
+        Some user assembly required."""
         from Products.kupu.python.spellcheck import SpellChecker, format_result
         data = REQUEST["text"]
         c = SpellChecker()

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	Tue Mar 25 14:07:28 2008
@@ -646,15 +646,15 @@
                 src = src[len(base):].lstrip('/')
             try:
                 obj = portal.restrictedTraverse(src)
+                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:
+                            return []
             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:
-                        return []
         else:
             # src=<uid1> <uid2> ... <uidn>
             src = src.split(' ') # src is a list of uids.
@@ -877,6 +877,40 @@
                 base = base[:posfactory]
         return base
 
+    security.declareProtected("View", "getUploadImageSizes")
+    def getUploadImageSizes(self, portal_type=None):
+        resource_type = self.getResourceType()
+        portal = getToolByName(self, 'portal_url').getPortalObject()
+        mediatypes = resource_type.get_portal_types()
+        catalog = getToolByName(self, 'portal_catalog')
+        adaptor = InfoAdaptor(self, resource_type, portal)
+        if portal_type is None:
+            portal_type = self.getDefaultImageType()
+
+        brains = catalog.searchResults(portal_type=portal_type, limit=1)[:1]
+        if brains:
+            info = adaptor.get_image_sizes(brains[0], portal_type, '')
+            return info
+        return []
+
+    security.declareProtected("View", "getUploadImageClasses")
+    def getUploadImageClasses(self, portal_type=None):
+        if portal_type is None:
+            portal_type = self.getDefaultImageType()
+        stored = self.getClassesForType(portal_type)
+        classes = []
+        for c in stored:
+            c = c.strip()
+            if not c:
+                continue
+            if '|' in c:
+                title, classname = c.split('|', 1)
+                classes.append({'title': title, 'classname': classname})
+            else:
+                classes.append({'title': c, 'classname': c})
+        return classes
+
+
     def _getImageSizes(self):
         resource_type = self.getResourceType()
         portal = getToolByName(self, 'portal_url').getPortalObject()

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	Tue Mar 25 14:07:28 2008
@@ -52,9 +52,9 @@
 _default_libraries = (
     dict(id="root",
          title="string:Home",
-         uri="string:${portal_url}",
-         src="string:${portal_url}/kupucollection.xml",
-         icon="string:${portal_url}/misc_/CMFPlone/plone_icon"),
+         uri="string:${globals_view/navigationRootUrl|portal_url}",
+         src="string:${globals_view/navigationRootUrl|portal_url}/kupucollection.xml",
+         icon="string:${globals_view/navigationRootUrl|portal_url}/misc_/CMFPlone/plone_icon"),
     dict(id="current",
          title="string:Current folder",
          uri="string:${folder_url}",
@@ -362,7 +362,7 @@
                     return verno >= (1,3,1)
                 verno = getver(' AppleWebKit/')
                 if verno:
-                    return verno >= (523,11)
+                    return verno >= (525,1)
                     verno = getver(' Safari/')
                     if verno:
                         return verno >= (522,12)
@@ -709,8 +709,14 @@
         value = action_map.get(portal_type, {}).get('scalefield', 'image')
         return value
 
+    security.declareProtected(permissions.ManageLibraries, "getDefaultImageType")
+    def getDefaultImageType(self):
+        return 'Image'
+
     security.declareProtected(permissions.ManageLibraries, "getDefaultScaleForType")
-    def getDefaultScaleForType(self, portal_type):
+    def getDefaultScaleForType(self, portal_type = None):
+        if not portal_type:
+            portal_type = self.getDefaultImageType()
         action_map = getattr(self, '_preview_actions', {})
         value = action_map.get(portal_type, {}).get('defscale', 'image_preview')
         return value

Modified: kupu/branch/kupu-1.4/plone/profiles/default/import_steps.xml
==============================================================================
--- kupu/branch/kupu-1.4/plone/profiles/default/import_steps.xml	(original)
+++ kupu/branch/kupu-1.4/plone/profiles/default/import_steps.xml	Tue Mar 25 14:07:28 2008
@@ -3,8 +3,7 @@
  <import-step id="kupu-setup" version="20061211-01"
               handler="Products.kupu.plone.exportimport.importKupuSettings"
               title="Kupu Settings">
-  <dependency step="toolset"/>
-  <dependency step="typeinfo"/>
+    <dependency step="plone_various"/>
   Import Kupu settings
  </import-step>
 </import-steps>

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	Tue Mar 25 14:07:28 2008
@@ -28,9 +28,9 @@
     <filterstyle>list-style-type</filterstyle>
     <filterstyle>float</filterstyle>
   </config>
-  <library src="string:${portal_url}/kupucollection.xml"
-           uri="string:${portal_url}" id="root"
-           icon="string:${portal_url}/misc_/CMFPlone/plone_icon"
+  <library src="string:${globals_view/navigationRootUrl|portal_url}/kupucollection.xml"
+           uri="string:${globals_view/navigationRootUrl|portal_url}" id="root"
+           icon="string:${globals_view/navigationRootUrl|portal_url}/misc_/CMFPlone/plone_icon"
            title="string:Home">
   </library>
   <library src="string:${folder_url}/kupucollection.xml"

Modified: kupu/branch/kupu-1.4/plone/tests/framework.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/framework.py	(original)
+++ kupu/branch/kupu-1.4/plone/tests/framework.py	Tue Mar 25 14:07:28 2008
@@ -105,4 +105,12 @@
 print 'INSTANCE_HOME: %s' % os.environ.get('INSTANCE_HOME', 'Not set')
 sys.stdout.flush()
 from Testing import ZopeTestCase
-ZopeTestCase.installProduct('kupu')
+from Testing import ZopeTestCase
+DEPS = ('MimetypesRegistry', 'PortalTransforms', 'Archetypes', 'ATContentTypes', 'kupu')
+try:
+    import Products.TextIndexNG2
+    DEPS = DEPS + ('TextIndexNG2',)
+except ImportError:
+    pass
+for product in DEPS:
+    ZopeTestCase.installProduct(product, 1)

Modified: kupu/branch/kupu-1.4/plone/tests/input/linked.in
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/input/linked.in	(original)
+++ kupu/branch/kupu-1.4/plone/tests/input/linked.in	Tue Mar 25 14:07:28 2008
@@ -1,2 +1,2 @@
 <div>Simple text containing an embedded image</div>
-<p><a href="xyzzy" class="link"><img class="image-left captioned" height="144" alt="picture alt text" src="resolveuid/104ede98d4c7c8eaeaa3b984f7395979" width="120"/></a></p>
+<p><a href="xyzzy" class="link"><img class="image-left captioned" alt="picture alt text" src="resolveuid/104ede98d4c7c8eaeaa3b984f7395979"/></a></p>

Modified: kupu/branch/kupu-1.4/plone/tests/input/simple.in
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/input/simple.in	(original)
+++ kupu/branch/kupu-1.4/plone/tests/input/simple.in	Tue Mar 25 14:07:28 2008
@@ -1,5 +1,4 @@
 <div>Simple text containing an embedded image</div>
+<p><img class="image-left captioned" alt="picture alt text" src="resolveuid/104ede98d4c7c8eaeaa3b984f7395979"/></p>
+<p><img class="image-left captioned" alt="picture alt text" src="resolveuid/104ede98d4c7c8eaeaa3b984f7395979/image_thumb"/></p>
 <p><img class="image-left captioned" height="144" alt="picture alt text" src="resolveuid/104ede98d4c7c8eaeaa3b984f7395979" width="120"/></p>
-<p><img class="image-left captioned" height="144" alt="picture alt text" src="resolveuid/104ede98d4c7c8eaeaa3b984f7395979/image_thumb"/></p>
-<p><img class="image-left captioned"
- height="144" alt="picture alt text" src="resolveuid/104ede98d4c7c8eaeaa3b984f7395979"/></p>

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	Tue Mar 25 14:07:28 2008
@@ -1,9 +1,12 @@
 <div>Simple text containing an embedded image</div>
 <dl class="image-left captioned">
  <dt>
-  <a href="xyzzy" class="link"><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/></a>
+  <a href="xyzzy" class="link">
+    <img src="http://nohost/plone/folder/gamma/image" alt="Kupu Test Image" title="Kupu Test Image"
+    height="331" width="500" />
+  </a>
  </dt>
- <dd class="image-caption" style="width:120px">
+ <dd class="image-caption" style="width:500px">
   Test image caption
  </dd>
-</div>
+</dl>

Modified: kupu/branch/kupu-1.4/plone/tests/output/notcaptioned.out
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/output/notcaptioned.out	(original)
+++ kupu/branch/kupu-1.4/plone/tests/output/notcaptioned.out	Tue Mar 25 14:07:28 2008
@@ -1,2 +1,2 @@
 <div>Simple text containing an embedded image</div>
-<p><img class=image-left height="144" alt="picture alt text" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120"/></p>
+<p><img class=image-left height="144" alt="picture alt text" src="/plone/folder/gamma" width="120"/></p>

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	Tue Mar 25 14:07:28 2008
@@ -1,13 +1,17 @@
 <div>IE doesn't always quote attributes</div>
 <dl class="image-left captioned">
   <dt>
-    <img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+    <img src="http://nohost/plone/folder/gamma/image"
+        alt="Kupu Test Image" title="Kupu Test Image"
+        height="331" width="500" />
   </dt>
-  <dd class="image-caption" style="width:120px">Test image caption</dd>
+  <dd class="image-caption" style="width:500px">Test image caption</dd>
 </dl>
 <dl class="captioned">
   <dt>
-    <img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+    <img src="http://nohost/plone/folder/gamma/image"
+        alt="Kupu Test Image" title="Kupu Test Image"
+        height="331" width="500" />
   </dt>
-  <dd class="image-caption" style="width:120px">Test image caption</dd>
+  <dd class="image-caption" style="width:500px">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	Tue Mar 25 14:07:28 2008
@@ -1,16 +1,27 @@
 <div>Simple text containing an embedded image</div>
 <dl class="image-left captioned">
-  <dt><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="120" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+  <dt>
+     <img src="http://nohost/plone/folder/gamma/image"
+          alt="Kupu Test Image" title="Kupu Test Image"
+          height="331" width="500" />
   </dt>
-  <dd class="image-caption" style="width:120px">Test image caption</dd>
+  <dd class="image-caption" style="width:500px">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>
+    <a rel="lightbox" href="/plone/folder/gamma">
+      <img src="http://nohost/plone/folder/gamma/image_thumb"
+           alt="Kupu Test Image" title="Kupu Test Image" height="84"
+           width="128" />
+    </a>
   </dt>
-  <dd class="image-caption" style="width:20px">Test image caption</dd>
+  <dd class="image-caption" style="width:128px">Test image caption</dd>
 </dl>
 <dl class="image-left captioned">
-  <dt><img height="144" src="[url for 104ede98d4c7c8eaeaa3b984f7395979]" width="600" alt="image 104ede98d4c7c8eaeaa3b984f7395979"/>
+  <dt>
+     <img src="http://nohost/plone/folder/gamma/image"
+          alt="Kupu Test Image" title="Kupu Test Image" height="331"
+          width="500" />
   </dt>
-  <dd class="image-caption" style="width:600px">Test image caption</dd>
+  <dd class="image-caption" style="width:500px">Test image caption</dd>
 </dl>

Modified: kupu/branch/kupu-1.4/plone/tests/runme.cmd
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/runme.cmd	(original)
+++ kupu/branch/kupu-1.4/plone/tests/runme.cmd	Tue Mar 25 14:07:28 2008
@@ -10,6 +10,7 @@
 @set PYTHON=C:\Plone20\Zope\bin\python.exe
 rem "%PYTHON%" %~D0%~P0test_browserSupportsKupu.py %2
 rem "%PYTHON%" %~D0%~P0test_librarymanager.py
+rem "%PYTHON%" %~D0%~P0test_links.py
 rem "%PYTHON%" %~D0%~P0test_html2captioned.py
 rem "%PYTHON%" %~D0%~P0test_resourcetypemapper.py
 rem "%PYTHON%" %~D0%~P0test_urls.py

Modified: kupu/branch/kupu-1.4/plone/tests/test_browserSupportsKupu.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/test_browserSupportsKupu.py	(original)
+++ kupu/branch/kupu-1.4/plone/tests/test_browserSupportsKupu.py	Tue Mar 25 14:07:28 2008
@@ -17,16 +17,6 @@
 if __name__ == '__main__':
     execfile(os.path.join(sys.path[0], 'framework.py'))
 
-from Testing import ZopeTestCase
-DEPS = ('MimetypesRegistry', 'PortalTransforms', 'Archetypes', 'ATContentTypes')
-try:
-    import Products.TextIndexNG2
-    DEPS = DEPS + ('TextIndexNG2',)
-except ImportError:
-    pass
-
-for product in DEPS:
-    ZopeTestCase.installProduct(product, 1)
 from Products.PloneTestCase import PloneTestCase
 
 PloneTestCase.setupPloneSite(products=['ATContentTypes', 'kupu'])
@@ -62,7 +52,7 @@
     MOZILLA: (1,3,1),
     INTERNET_EXPLORER: (5,5),
     OPERA: (9,0),
-    SAFARI: (999,9), #(420,0), # Safari not yet supported
+    SAFARI: (525,1), #(420,0), # Safari not yet supported
 }
 
 # BROWSERS records contain:
@@ -399,6 +389,8 @@
     ('Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; en) Opera 9.00', 'Linux', '9.00', OPERA),
     ('Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Safari/419.3', 'Mac', '420.0', SAFARI),
     ('Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418.9.1 (KHTML, like Gecko) Safari/419.3', 'Mac', '418.9.1', SAFARI),
+    ("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/523.12.9 (KHTML, like Gecko) Version/3.0 Safari/523.12.9", 'Windows', '523.12.9', SAFARI),
+    ("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.1+ (KHTML, like Gecko) Version/3.0 Safari/523.12.9", 'Mac', '525.1', SAFARI),
 )
 
 def createTest(sig, isSupported, index, os, browser, version):

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	Tue Mar 25 14:07:28 2008
@@ -2,8 +2,9 @@
 if __name__ == '__main__':
     execfile(os.path.join(sys.path[0], 'framework.py'))
 
+from kuputestcase import *
+
 from unittest  import TestCase, TestSuite, main, makeSuite
-from Products.CMFPlone.tests import PloneTestCase
 from os.path import join, abspath, dirname
 
 from Products.PortalTransforms.tests.test_transforms import *
@@ -27,92 +28,7 @@
 ('Products.kupu.plone.html2captioned', "linked.in", "linked.out", normalize_html, 0),
     )
 
-class MockImage:
-    def __init__(self, uid, description):
-        self.uid, self.description = uid, description
-        if not uid.startswith('SUB:'):
-            self.image_thumb = MockSubImage(self)
-
-    def Title(self):
-        return 'image '+self.uid
-    def Description(self):
-        return self.description
-    def absolute_url(self):
-        return '[url for %s]' % self.uid
-    def absolute_url_path(self):
-        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):
-        dummydata = {
-            '104ede98d4c7c8eaeaa3b984f7395979': 'Test image caption'
-        }
-        if uid not in dummydata:
-            return None
-        image = MockImage(uid, dummydata[uid])
-        return image
-
-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()
-    
+class TransformTest(KupuTestCase):
     def do_convert(self, filename=None):
         if filename is None and exists(self.output + '.nofilename'):
             output = self.output + '.nofilename'
@@ -136,22 +52,25 @@
             output.close()
             self.assert_(0)
         expected = output.read()
+        raw_got, raw_expected = got, expected
         if self.normalize is not None:
             expected = self.normalize(expected)
             got = self.normalize(got)
         output.close()
 
         self.assertEquals(got, expected,
-                          '[%s]\n\n!=\n\n[%s]\n\nIN %s(%s)' % (
+                          'Got:\n[%s]\n\n!=\n\nExpected:\n[%s]\n\nIN %s(%s)' % (
             got, expected, self.transform.name(), self.input))
         self.assertEquals(self.subobjects, len(res_data.getSubObjects()),
-                          '%s\n\n!=\n\n%s\n\nIN %s(%s)' % (
+                          'Subobjects:\n%s\n\n!=\n\nLength: %s\n\nIN %s(%s)' % (
             self.subobjects, len(res_data.getSubObjects()), self.transform.name(), self.input))
 
     def testSame(self):
+        self.setup_content()
         self.do_convert(filename=self.input)
 
     def testSameNoFilename(self):
+        self.setup_content()
         self.do_convert()
 
     def __repr__(self):

Modified: kupu/branch/kupu-1.4/plone/tests/test_links.py
==============================================================================
--- kupu/branch/kupu-1.4/plone/tests/test_links.py	(original)
+++ kupu/branch/kupu-1.4/plone/tests/test_links.py	Tue Mar 25 14:07:28 2008
@@ -13,103 +13,12 @@
 if __name__ == '__main__':
     execfile(os.path.join(sys.path[0], 'framework.py'))
 
-from Products.PloneTestCase import PloneTestCase
-from Products.PloneTestCase.ptc import portal_owner
-
-PloneTestCase.setupPloneSite(products=['kupu'])
-
-from AccessControl.SecurityManagement import newSecurityManager
-try:
-    from Products.ATContentTypes.lib import constraintypes
-except:
-    constraintypes = None
-
+from kuputestcase import *
 from Products.kupu.plone.html2captioned import Migration
 
-RESOURCES = dict(
-    linkable = ('Document', 'Image', 'File', 'Folder'),
-    mediaobject = ('Image',),
-    collection = ('Folder',),
-    containsanchors = ('Document',),
-    )
-
-# Type names vary according to the version of Plone and/or
-# ATContentTypes. Map the new names to the old ones here, and
-# turn it into an identity mapping later if we can.
-TypeMapping = {
-    'Document': 'ATDocument',
-    'Image': 'ATImage',
-    'Link': 'ATLink',
-    'Folder': 'ATFolder',
-    'File': 'ATFile',
-    'News Item': 'ATNewsItem',
-    'Event': 'ATEvent',
-}
-def MapType(typename):
-    return TypeMapping[typename]
-
-class TestLinkCode(PloneTestCase.PloneTestCase):
+class TestLinkCode(KupuTestCase):
     """Test the link checking code"""
 
-    def afterSetUp(self):
-        portal = self.portal
-        self.setRoles(['Manager',])
-        self.kupu = portal.kupu_library_tool
-        typestool = self.portal.portal_types
-        if not hasattr(typestool, 'ATDocument'):
-            # Use the type names without the AT prefix
-            for k in TypeMapping:
-                TypeMapping[k] = k
-
-    def loginPortalOwner(self):
-        '''Use if you need to manipulate the portal itself.'''
-        uf = self.app.acl_users
-        user = uf.getUserById(portal_owner).__of__(uf)
-        newSecurityManager(None, user)
-
-    def create(self, id, metatype='ATDocument', folder=None, **kwds):
-        '''Create an object in the cms portal'''
-        if folder is None:
-            folder = self.portal
-
-        folder.invokeFactory(MapType(metatype), id)
-        obj = getattr(folder, id)
-
-        if metatype=='Folder' and constraintypes:
-            obj.setConstrainTypesMode(constraintypes.DISABLED)
-
-        if metatype=='Document':
-            obj.setTitle('Simple document')
-            obj.setText('Sample document text')
-            for k, v in kwds.items():
-                field = obj.getField(k)
-                mutator = field.getMutator(obj)(v)
-
-            obj.reindexObject()
-        return obj
-
-    def setup_content(self):
-        self.setRoles(['Manager',])
-        self.loginPortalOwner()
-        f = self.create('folder', 'Folder')
-
-        for id in ('alpha', 'beta'):
-            self.create(id, 'Document', f, subject=['aspidistra'])
-        self.create('gamma', 'Image', f)
-
-        sub1 = self.create('sub1', 'Folder', f)
-        sub1.setSubject(['aspidistra'])
-        sub1.reindexObject()
-        sub2 = self.create('sub2', 'Folder', f)
-        self.create('delta', 'Folder', sub2)
-
-        portal = self.portal
-        tool = self.portal.kupu_library_tool
-        types = tool.zmi_get_resourcetypes()
-        #tool.deleteResource([ t.name for t in types])
-        for k,v in RESOURCES.items():
-            tool.addResourceType(k, [MapType(t) for t in v])
-
     def test_relative(self):
         self.setup_content()
         migrator = Migration(self.kupu)

Modified: kupu/branch/kupu-1.4/plone/wysiwyg_support.kupu
==============================================================================
--- kupu/branch/kupu-1.4/plone/wysiwyg_support.kupu	(original)
+++ kupu/branch/kupu-1.4/plone/wysiwyg_support.kupu	Tue Mar 25 14:07:28 2008
@@ -48,6 +48,12 @@
                         rows rows|default;
                         cols cols|default;">
     </textarea>
+     <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;"
+     />
   </kupu:part>
 
   <kupu:part name="textformatselector">

Modified: kupu/branch/kupu-1.4/plone/zmi_links.pt
==============================================================================
--- kupu/branch/kupu-1.4/plone/zmi_links.pt	(original)
+++ kupu/branch/kupu-1.4/plone/zmi_links.pt	Tue Mar 25 14:07:28 2008
@@ -34,7 +34,7 @@
       <form action="kupu_migration.xml"
             method="post"
             name="changes_form"
-            onsubmit="alert('submitting'); return false;return kj.submitForm(this);"
+            onsubmit="return kj.submitForm(this);"
             tal:define="infouri string:${context/absolute_url_path}/kupu_kjax_support.xml"
             >
         <div id="kupu-output"></div>

Modified: kupu/branch/kupu-1.4/tests/test_kupuhelpers.js
==============================================================================
--- kupu/branch/kupu-1.4/tests/test_kupuhelpers.js	(original)
+++ kupu/branch/kupu-1.4/tests/test_kupuhelpers.js	Tue Mar 25 14:07:28 2008
@@ -103,6 +103,7 @@
         s = s.replace(/\/>/g, ">");
         s = s.replace(' style=""', "");
         s = s.replace(" style=''", "");
+        s = s.replace(/ kupu-src="[^"]*"/, "");
         return s;
     };
 

Modified: kupu/branch/kupu-1.4/version.txt
==============================================================================
--- kupu/branch/kupu-1.4/version.txt	(original)
+++ kupu/branch/kupu-1.4/version.txt	Tue Mar 25 14:07:28 2008
@@ -1 +1 @@
-kupu 1.4.4
+kupu 1.4.9


More information about the kupu-checkins mailing list