[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    Re: [PATCH] KHTML clipboard text/html format
From:       Ilya Konstantinov <kfm-devel () future ! shiny ! co ! il>
Date:       2001-09-20 2:28:07
[Download RAW message or body]

On Wed, Sep 19, 2001 at 04:58:14PM +0200, Dirk Mueller wrote:
> On Mit, 19 Sep 2001, Ilya Konstantinov wrote:
> 
> > This patch will makes KHTML export the following formats into the
> > clipboard:
> 
> looks good to me.. just one comment (thinking loud). I think it might be 
> more correct to do the escaping of nonlatin1 characters as entities in 
> khtml's toHTML already - if the other browsers do it too. 
> 
> can you please test that how i.e. IE behaves in such a case? we should be 
> consistent to it (as toHTML is used in JS bindings which might expect this 
> behaviour). 

Both Internet Explorer and Mozilla return the actual Unicode string
even if you specify Unicode entities in the text. In fact, it makes
sense since JavaScript strings are Unicode, and we're requesting 

One thing which must always be done in innerHTML (even for UTF-8
encoding) is the escaping of characters such as ", &, < and >.

Another problem is in the alert / confirm / prompt boxes themselves,
rendering tags like <B> with QStyleSheet instead of escaping them.
This shouldn't happen.

So the new patch:
1. Separated toHTML() into the relevant pieces for each node
   implementation (ElementImpl, AttrImpl, TextImpl for now).
2. Added toXML(). Generally just like toHTML(), except for
   ElementImpl::toHTML() (<tag/> vs. <tag>)
3. Made NodeImpl::toHTML() return both the current item
   and it's children (unlike the previous implementation
   which worked more like innerHTML).
4. Made sure everything in KHTML which does a selection
   sets the QClipboard.
   "Select All" copies text to the clipboard properly now.
   "Find" still doesn't copy to the selection buffer, but it neither
   triggers emitChangedSelection() -- is it intentional?
   Selections and Clipboard copies are distincted on Qt 3.
5. Improved KHTMLDrag. Added 'TEXT' type for GTK apps.
6. Made sure the special symbls (", &, < and >) are escaped
   in the toHTML and toXML output.
7. Made sure JavaScript alert(str), confirm(str) and prompt(str)
   display tags in str literally instead of triggering QStyleSheet.

This patch is a bit larger, but more complete I believe.

["khtml_clipboard_html2.patch" (text/plain)]

Index: khtml_ext.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/khtml_ext.cpp,v
retrieving revision 1.24.2.1
diff -u -3 -d -p -r1.24.2.1 khtml_ext.cpp
--- khtml_ext.cpp	2001/09/10 21:04:12	1.24.2.1
+++ khtml_ext.cpp	2001/09/20 02:13:20
@@ -23,6 +23,7 @@
 
 #include <dom/dom_element.h>
 #include <misc/htmltags.h>
+#include <misc/khtmldrag.h>
 
 KHTMLPartBrowserExtension::KHTMLPartBrowserExtension( KHTMLPart *parent, const char *name )
 : KParts::BrowserExtension( parent, name )
@@ -161,10 +162,7 @@ void KHTMLPartBrowserExtension::copy()
     kdDebug( 6050 ) << "************! KHTMLPartBrowserExtension::copy()" << endl;
     if ( !m_editableFormWidget )
     {
-        // get selected text and paste to the clipboard
-        QString text = m_part->selectedText();
-        QClipboard *cb = QApplication::clipboard();
-        cb->setText(text);
+        m_part->copySelectionToClipboard();
     }
     else
     {
Index: khtml_part.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/khtml_part.cpp,v
retrieving revision 1.530.2.5
diff -u -3 -d -p -r1.530.2.5 khtml_part.cpp
--- khtml_part.cpp	2001/08/27 12:50:16	1.530.2.5
+++ khtml_part.cpp	2001/09/20 02:13:23
@@ -54,6 +54,7 @@ using namespace DOM;
 #include "decoder.h"
 #include "ecma/kjs_proxy.h"
 #include "khtml_settings.h"
+#include "khtmldrag.h"
 
 #include <sys/types.h>
 #include <assert.h>
@@ -1975,6 +1976,7 @@ bool KHTMLPart::findTextNext( const QStr
 
                 d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
                                         d->m_selectionEnd.handle(), d->m_endOffset );
+                copySelectionToClipboard(true);
                 emitSelectionChanged();
                 return true;
             }
@@ -3918,6 +3920,7 @@ void KHTMLPart::khtmlMouseReleaseEvent( 
     d->m_selectionEnd = 0;
     d->m_startOffset = 0;
     d->m_endOffset = 0;
+    copySelectionToClipboard(true);
     emitSelectionChanged();
   } else {
     // we have to get to know if end is before start or not...
@@ -3951,14 +3954,8 @@ void KHTMLPart::khtmlMouseReleaseEvent( 
       d->m_endOffset = tmpOffset;
       d->m_startBeforeEnd = true;
     }
-    // get selected text and paste to the clipboard
-#ifndef QT_NO_CLIPBOARD
-    QString text = selectedText();
-    text.replace(QRegExp(QChar(0xa0)), " ");
-    QClipboard *cb = QApplication::clipboard();
-    cb->setText(text);
-#endif
     //kdDebug( 6000 ) << "selectedText = " << text << endl;
+    copySelectionToClipboard(true);
     emitSelectionChanged();
   }
 #endif
@@ -4159,6 +4156,7 @@ void KHTMLPart::selectAll()
   d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
                           d->m_selectionEnd.handle(), d->m_endOffset );
 
+  copySelectionToClipboard();
   emitSelectionChanged();
 }
 
@@ -4294,6 +4292,32 @@ bool KHTMLPart::openedByJS()
 void KHTMLPart::setOpenedByJS(bool _openedByJS)
 {
     d->m_openedByJS = _openedByJS;
+}
+
+
+void KHTMLPart::copySelectionToClipboard(bool as_selection = false)
+{
+    #ifndef QT_NO_CLIPBOARD
+    // prepare the clipboard object
+    QClipboard *cb = QApplication::clipboard();
+    #if QT_VERSION >= 300
+    cb->setSelectionMode(as_selection);
+    #endif
+    if (d->m_selectionStart != d->m_selectionEnd) {
+        // get the selected text
+        QString text = selectedText();
+        text.replace(QRegExp(QChar(0xa0)), " ");
+        // get the selected HTML
+        QString html = selection().toHTML().string();
+        // ...and paste to the clipboard
+        KHTMLDrag *cb_data = new KHTMLDrag;
+        cb_data->setHTML(html);
+        cb_data->setPlain(text);
+        cb->setData(cb_data);
+    } else {
+        cb->clear();
+    }
+    #endif
 }
 
 using namespace KParts;
Index: khtml_part.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/khtml_part.h,v
retrieving revision 1.146
diff -u -3 -d -p -r1.146 khtml_part.h
--- khtml_part.h	2001/07/22 18:57:35	1.146
+++ khtml_part.h	2001/09/20 02:13:23
@@ -980,6 +980,8 @@ private slots:
   void slotPrintFrame();
 
   void slotSelectAll();
+  
+  void copySelectionToClipboard(bool as_selection = false);
 
 protected:
     // @internal
Index: dom/dom2_range.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/dom/dom2_range.cpp,v
retrieving revision 1.31
diff -u -3 -d -p -r1.31 dom2_range.cpp
--- dom/dom2_range.cpp	2001/04/16 13:27:38	1.31
+++ dom/dom2_range.cpp	2001/09/20 02:13:24
@@ -351,7 +351,10 @@ DOMString Range::toHTML(  )
     if (!impl)
         throw DOMException(DOMException::INVALID_STATE_ERR);
 
-    return impl->toHTML();
+    int exceptioncode = 0;
+    DOMString r = impl->toHTML(exceptioncode);
+    throwException(exceptioncode);
+    return r;
 }
 
 void Range::detach(  )
Index: dom/dom2_range.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/dom/dom2_range.h,v
retrieving revision 1.16
diff -u -3 -d -p -r1.16 dom2_range.h
--- dom/dom2_range.h	2001/04/15 07:18:04	1.16
+++ dom/dom2_range.h	2001/09/20 02:13:24
@@ -426,15 +426,26 @@ public:
     Range cloneRange (  );
 
     /**
-     * Returns the contents of a range as a string.
+     * Returns a text string with the textual contents of the nodes
+     * in this range. Range offsets are respected. Non-text nodes are
+     * ignored.
      *
-     * @return The contents of the range.
+     * @return Text string.
      *
+     * This convenience function is not part of the W3C DOM. Real loading
+     * and saving is expected in the W3C DOM Level 3 specification.
      */
     DOMString toString (  );
     
     /**
-     * @internal Not part of DOM
+     * Returns an HTML string equivalent to (though not necessarily the same as)
+     * the source to the nodes in this range and their contents.
+     * Range offsets are respected.
+     *
+     * @returns HTML string.
+     *
+     * This convenience function is not part of the W3C DOM. Real loading
+     * and saving is expected in the W3C DOM Level 3 specification.
      */
     DOMString toHTML (  );
     
Index: dom/dom_node.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/dom/dom_node.cpp,v
retrieving revision 1.30
diff -u -3 -d -p -r1.30 dom_node.cpp
--- dom/dom_node.cpp	2001/07/15 19:57:09	1.30
+++ dom/dom_node.cpp	2001/09/20 02:13:24
@@ -450,6 +450,18 @@ unsigned long Node::index() const
     return impl->nodeIndex();
 }
 
+QString Node::toXML()
+{
+    if (!impl)
+	return 0; // ### enable	throw throw DOMException(DOMException::NOT_FOUND_ERR);
+
+    int exceptioncode = 0;
+    QString r = impl->toXML();
+    if (exceptioncode)
+	throw DOMException(exceptioncode);
+    return r;
+}
+
 QString Node::toHTML()
 {
     if (!impl)
Index: dom/dom_node.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/dom/dom_node.h,v
retrieving revision 1.23
diff -u -3 -d -p -r1.23 dom_node.h
--- dom/dom_node.h	2001/03/11 09:52:21	1.23
+++ dom/dom_node.h	2001/09/20 02:13:24
@@ -681,7 +681,6 @@ public:
      * @internal returns the index of a node
      */
     unsigned long index() const;
-    QString toHTML();
     void applyChanges();
     void getCursor(int offset, int &_x, int &_y, int &height);
     /**
@@ -689,6 +688,24 @@ public:
      * @returns the exact coordinates and size of this element.
      */
     QRect getRect();
+
+    /**
+     * @returns XML string equivalent to (though not necessarily the same as)
+     * the source to the node and it's contents.
+     *
+     * This convenience function is not part of the W3C DOM. Real loading
+     * and saving is expected in the W3C DOM Level 3 specification.
+     */
+    QString toXML();
+    
+    /**
+     * @returns HTML string equivalent to (though not necessarily the same as)
+     * the source to this node and it's contents.
+     *
+     * This convenience function is not part of the W3C DOM. Real loading
+     * and saving is expected in the W3C DOM Level 3 specification.
+     */
+    QString toHTML();
     
 protected:
     NodeImpl *impl;
Index: ecma/kjs_window.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/ecma/kjs_window.cpp,v
retrieving revision 1.162
diff -u -3 -d -p -r1.162 kjs_window.cpp
--- ecma/kjs_window.cpp	2001/08/04 20:26:54	1.162
+++ ecma/kjs_window.cpp	2001/09/20 02:13:25
@@ -23,6 +23,7 @@
 #include <qstringlist.h>
 #include <qpaintdevicemetrics.h>
 #include <qapplication.h>
+#include <qstylesheet.h>
 #include <dom_string.h>
 #include <kdebug.h>
 #include <kurl.h>
@@ -866,7 +867,7 @@ Completion WindowFunc::tryExecute(const 
   KHTMLView *widget = part->view();
   KJSO v = args[0];
   String s = v.toString();
-  str = s.value().qstring();
+  str = QStyleSheet::convertFromPlainText(s.value().qstring());
 
   switch (id) {
   case Alert:
Index: html/html_elementimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/html/html_elementimpl.cpp,v
retrieving revision 1.128
diff -u -3 -d -p -r1.128 html_elementimpl.cpp
--- html/html_elementimpl.cpp	2001/07/27 23:54:41	1.128
+++ html/html_elementimpl.cpp	2001/09/20 02:13:26
@@ -230,7 +230,17 @@ DOMString HTMLElementImpl::getCSSPropert
 
 DOMString HTMLElementImpl::innerHTML() const
 {
-    return toHTML();
+    QString str;
+    
+    if (hasChildNodes()) {
+        NodeListImpl *list = const_cast<HTMLElementImpl *>(this)->childNodes();
+        int length = list->length();
+        for (int i=0; i<length; i++) {
+            str += list->item(i)->toHTML();
+        }
+    }
+        
+    return DOMString(str);
 }
 
 DOMString HTMLElementImpl::innerText() const
Index: misc/Makefile.am
===================================================================
RCS file: /home/kde/kdelibs/khtml/misc/Makefile.am,v
retrieving revision 1.17
diff -u -3 -d -p -r1.17 Makefile.am
--- misc/Makefile.am	2001/02/06 23:38:10	1.17
+++ misc/Makefile.am	2001/09/20 02:13:26
@@ -22,13 +22,13 @@
 noinst_LTLIBRARIES = libkhtmlmisc.la
 libkhtmlmisc_la_SOURCES = \
 	decoder.cpp    loader.cpp loader_jpeg.cpp \
-	htmlhashes.cpp helper.cpp 
+	htmlhashes.cpp helper.cpp khtmldrag.cpp
 
 libkhtmlmisc_la_METASOURCES = AUTO
 
 noinst_HEADERS = \
 	decoder.h      khtmllayout.h loader_jpeg.h loader.h \
-	stringit.h     htmlhashes.h    helper.h font.h
+	stringit.h     htmlhashes.h    helper.h font.h khtmldrag.h
 
 INCLUDES = -I$(top_srcdir)/kimgio -I$(top_srcdir) -I$(top_srcdir)/dcop \
  -I$(top_srcdir)/kio -I$(top_srcdir)/libltdl \
Index: misc/khtmldrag.cpp
===================================================================
RCS file: khtmldrag.cpp
diff -N khtmldrag.cpp
--- /dev/null	Tue May  5 20:32:27 1998
+++ khtmldrag.cpp	Thu Sep 20 02:13:26 2001
@@ -0,0 +1,89 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 2001 Ilya Konstantinov
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#include <qobject.h>
+#include "khtmldrag.h"
+
+const char * KHTMLDrag::format(int i) const
+{
+    // from the most appropriate to the least appropriate,
+    // according to the Qt docs
+    switch(i) {
+        case 0: return "text/html;charset=utf-8";
+        case 1: return "text/html";
+        case 2: return "text/plain;charset=utf-8";
+        case 3: return "text/plain";
+        case 4: return "UTF8_STRING";
+        case 5: return "TEXT";
+        case 6: return "COMPOUND_TEXT";
+        default: return 0;
+    }        
+}
+
+QByteArray KHTMLDrag::encodedData(const char* mimetype) const
+{
+    if (strncasecmp(mimetype, "text/html;charset=utf-8", 23) == 0)
+        return m_html.utf8();
+        
+    if (strncasecmp(mimetype, "text/html", 9) == 0)
+        return escapeUnicodeHTML(m_html);
+        
+    if ((strncasecmp(mimetype, "text/plain", 10) == 0) ||
+        (strncasecmp(mimetype, "TEXT", 4) == 0) ||
+        (strncasecmp(mimetype, "COMPOUND_TEXT", 14) == 0))
+        return QCString(m_plain.latin1());
+    
+    if ((strncasecmp(mimetype, "text/plain;charset=utf-8", 24) == 0) ||
+        (strncasecmp(mimetype, "UTF8_STRING", 11) == 0))
+       return m_plain.utf8();
+       
+    return QByteArray();
+}
+
+void KHTMLDrag::setPlain(const QString &plain)
+{
+    m_plain = plain;
+}
+
+void KHTMLDrag::setHTML(const QString &html)
+{
+    m_html = html;
+}
+
+QCString KHTMLDrag::escapeUnicodeHTML(const QString &html)
+{
+    QCString escaped;
+    const QChar *u = html.unicode();
+    int length = html.length();
+    
+    for (int i=0; i<length; i++) {
+    	if (u->latin1()) {
+    		escaped += u->latin1();
+    	} else {
+    		QCString entity;
+    		entity.sprintf("&#x%x;", u->unicode());
+    		escaped += entity;
+    	}
+    	u++;
+    }
+    
+    return escaped;
+}
Index: misc/khtmldrag.h
===================================================================
RCS file: khtmldrag.h
diff -N khtmldrag.h
--- /dev/null	Tue May  5 20:32:27 1998
+++ khtmldrag.h	Thu Sep 20 02:13:26 2001
@@ -0,0 +1,46 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 2001 Ilya Konstantinov
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+
+    This class allows clipboard and drag-and-drop operations with combined
+    text and HTML data.
+*/
+
+#ifndef KHTMLDRAG_H
+#define KHTMLDRAG_H
+
+
+#include <qobject.h>
+#include <qdragobject.h>
+#include <qmap.h>
+
+class KHTMLDrag : public QDragObject
+{
+    static QCString escapeUnicodeHTML(const QString &html);
+public:
+    const char* format(int i) const;
+    QByteArray encodedData(const char* mimetype) const;
+    void setPlain(const QString &plain);
+    void setHTML(const QString &html);
+private:
+    QString m_plain;
+    QString m_html;
+};
+
+#endif
\ No newline at end of file
Index: xml/dom2_rangeimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom2_rangeimpl.cpp,v
retrieving revision 1.23
diff -u -3 -d -p -r1.23 dom2_rangeimpl.cpp
--- xml/dom2_rangeimpl.cpp	2001/07/15 19:55:01	1.23
+++ xml/dom2_rangeimpl.cpp	2001/09/20 02:13:26
@@ -33,6 +33,7 @@
 #include "dom_docimpl.h"
 #include "dom2_rangeimpl.h"
 #include "dom2_traversalimpl.h"
+#include "dom_elementimpl.h"
 #include "dom_textimpl.h"
 #include "dom_xmlimpl.h"
 
@@ -847,10 +848,105 @@ DOMString RangeImpl::toString( int &exce
     return text;
 }
 
-DOMString RangeImpl::toHTML(  )
+DOMString RangeImpl::toHTML( int &exceptioncode )
 {
-    // ### implement me!!!!
-    return DOMString();
+    bool started = false; // marks whether we reached the beginning tag of the range
+    bool ended = false; // marks whether we reached the ending tag of the range
+
+    return DOMString(recursive_toHTML(commonAncestorContainer(exceptioncode), started, ended));
+}
+
+QString RangeImpl::recursive_toHTML(NodeImpl *n, bool &started, bool &ended) const
+{
+    QString str;
+    
+    // if any previous recursion already signaled it reached the m_endContainer,
+    // we should stop right away
+    if (ended)
+        return str;
+        
+    if (n == m_startContainer)
+        started = true;
+    
+    if ( started ) {
+        if ( n->nodeType() == Node::TEXT_NODE )
+        {
+            QString text = n->nodeValue().string();
+            // since it's a text node, we may cut it so it according to the range's offsets
+            if (n == m_endContainer)
+                text.truncate(m_endOffset);
+            if (n == m_startContainer)
+                text.remove(0,m_startOffset);
+            
+            // escape the text node
+            int length = text.length();
+            const QChar *c = text.unicode();
+    
+            for (int i=0; i<length; i++) {
+                if (*c == '&')
+                    str += "&amp;";
+                else if (*c == '<')
+                    str += "&lt;";
+                else if (*c == '>')
+                    str += "&gt;";
+                else
+                    str += *c;
+                c++;
+            }
+        }
+        else
+        {
+            // If I am an element, not a text
+            NodeImpl* temp = n->previousSibling();
+            str = QChar('<') + n->nodeName().string();
+            // print attributes
+            if( n->nodeType() == Node::ELEMENT_NODE )
+            {
+                // why they needed that whole mess in NodeList::recursive_toHTML is unclear
+                NamedNodeMapImpl *attrs = n->attributes();
+                int exceptioncode;
+                int length = attrs->length(exceptioncode);
+                for ( int i=0; i < length; i++)
+                {
+                    AttrImpl *attr = static_cast<AttrImpl*>(attrs->item(i, exceptioncode));
+                    str += QChar(' ') + attr->toHTML();
+                }
+            }
+
+            // print ending bracket of start tag
+            // This is HTML, not XML, so we don't make a destinction
+            // between a standalone tag and a start tag.
+            str += ">";
+        }
+    }
+
+    // is this node the final one?
+    if (n == m_endContainer) {
+        ended = true;
+        return str; // no sense in going on
+    }
+
+    NodeImpl *next_node;
+    if( next_node = n->firstChild() )
+    {
+        // make sure we only add a closing tag if 'started' was triggered
+        // before we scanned the children, to prevent things like:
+        // <b>hello [world</b> quack] turning into "world</b> quack"
+        QString closing;
+        if ( started && (n->nodeType() != Node::TEXT_NODE))
+            closing += "</" + n->nodeName().string() + ">";
+
+        // print firstChild
+        str += recursive_toHTML(next_node, started, ended);
+
+        // print my closing tag
+        str += closing;
+    }
+    // print next sibling
+    if( next_node = n->nextSibling() )
+        str += recursive_toHTML(next_node, started, ended);
+
+    return str;
 }
 
 void RangeImpl::detach( int &exceptioncode )
Index: xml/dom2_rangeimpl.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom2_rangeimpl.h,v
retrieving revision 1.13
diff -u -3 -d -p -r1.13 dom2_rangeimpl.h
--- xml/dom2_rangeimpl.h	2001/05/23 13:36:43	1.13
+++ xml/dom2_rangeimpl.h	2001/09/20 02:13:27
@@ -62,7 +62,7 @@ public:
     DocumentFragmentImpl *cloneContents ( int &exceptioncode );
     void insertNode( NodeImpl *newNode, int &exceptioncode );
     DOMString toString ( int &exceptioncode );
-    DOMString toHTML (  );
+    DOMString toHTML ( int &exceptioncode );
     void detach ( int &exceptioncode );
     bool isDetached() const;
     RangeImpl *cloneRange(int &exceptioncode);
@@ -99,6 +99,7 @@ private:
     void setEndContainer(NodeImpl *_endContainer);
     void checkDeleteExtract(int &exceptioncode);
     bool containedByReadOnly();
+    QString recursive_toHTML(NodeImpl *n, bool &started, bool &ended) const;
 };
 
 }; // namespace
Index: xml/dom_elementimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_elementimpl.cpp,v
retrieving revision 1.128
diff -u -3 -d -p -r1.128 dom_elementimpl.cpp
--- xml/dom_elementimpl.cpp	2001/07/22 09:00:16	1.128
+++ xml/dom_elementimpl.cpp	2001/09/20 02:13:27
@@ -255,6 +255,36 @@ bool AttrImpl::childTypeAllowed( unsigne
     }
 }
 
+QString AttrImpl::toXML() const
+{
+    QString str = name().string() + "=\"";
+    QString avalue = value().string();
+    int length = avalue.length();
+    const QChar *c = avalue.unicode();
+    
+    for (int i=0; i<length; i++) {
+        if (*c == '"')
+            str += "&quot;";
+        else if (*c == '&')
+            str += "&amp;";
+        else if (*c == '<')
+            str += "&lt;";
+        else if (*c == '>')
+            str += "&gt;";
+        else
+            str += *c;
+        c++;
+    }
+    
+    str += "\"";
+    return str;
+}
+
+QString AttrImpl::toHTML() const
+{
+    return toXML();
+}
+
 // -------------------------------------------------------------------------
 
 ElementImpl::ElementImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
@@ -810,6 +840,69 @@ void ElementImpl::dispatchAttrAdditionEv
     AttrImpl *att = static_cast<AttrImpl*>(attr);
     dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,att->value(),
 		  att->value(),att->name(),MutationEvent::ADDITION),exceptioncode);
+}
+
+QString ElementImpl::toXML() const
+{
+    QString str = QChar('<') + nodeName().string();
+    
+    // print attributes
+    NamedNodeMapImpl *attrs = const_cast<ElementImpl*>(this)->attributes();
+    int exceptioncode;
+    int length = attrs->length(exceptioncode);
+    for ( int i=0; i < length; i++)
+    {
+        AttrImpl *attr = static_cast<AttrImpl*>(attrs->item(i, exceptioncode));
+        str += " " + attr->toXML();
+    }
+    
+    if( NodeImpl *n = firstChild() )
+    {
+        // print ending bracket of start tag
+        str += "/>";
+
+        // iterate over children
+        do { str += n->toXML(); } while (n = n->nextSibling());
+
+        // Print my ending tag
+        if ( nodeType() != Node::TEXT_NODE )
+            str += "</" + nodeName().string() + ">";
+    } else {
+        // print ending bracket of standalone
+        str += "/>";
+    }
+    
+    return str;
+}
+
+QString ElementImpl::toHTML() const
+{
+    QString str = QChar('<') + nodeName().string();
+    
+    // print attributes
+    NamedNodeMapImpl *attrs = const_cast<ElementImpl*>(this)->attributes();
+    int exceptioncode;
+    int length = attrs->length(exceptioncode);
+    for ( int i=0; i < length; i++)
+    {
+        AttrImpl *attr = static_cast<AttrImpl*>(attrs->item(i, exceptioncode));
+        str += " " + attr->toHTML();
+    }
+    
+    // print ending bracket of start tag
+    str += ">";
+
+    if( NodeImpl *n = firstChild() )
+    {
+        // iterate over children
+        do { str += n->toHTML(); } while (n = n->nextSibling());
+
+        // Print my ending tag
+        if ( nodeType() != Node::TEXT_NODE )
+            str += "</" + nodeName().string() + ">";
+    }
+    
+    return str;
 }
 
 // -------------------------------------------------------------------------
Index: xml/dom_elementimpl.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_elementimpl.h,v
retrieving revision 1.74
diff -u -3 -d -p -r1.74 dom_elementimpl.h
--- xml/dom_elementimpl.h	2001/07/22 09:00:16	1.74
+++ xml/dom_elementimpl.h	2001/09/20 02:13:27
@@ -71,6 +71,9 @@ public:
     virtual bool childAllowed( NodeImpl *newChild );
     virtual bool childTypeAllowed( unsigned short type );
 
+    virtual QString toXML() const;
+    virtual QString toHTML() const;
+
 protected:
     AttrImpl(const DOMString &name, const DOMString &value, DocumentPtr *doc);
     AttrImpl(int _id, const DOMString &value, DocumentPtr *doc);
@@ -134,6 +137,9 @@ public:
     int getAttributeCount() const;
     void setAttribute ( int id, const DOMString &value );
     void setAttributeMap ( NamedAttrMapImpl* list );
+    
+    virtual QString toXML() const;
+    virtual QString toHTML() const;
 
     // State of the element.
     virtual QString state() { return QString::null; }
Index: xml/dom_nodeimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_nodeimpl.cpp,v
retrieving revision 1.134.2.1
diff -u -3 -d -p -r1.134.2.1 dom_nodeimpl.cpp
--- xml/dom_nodeimpl.cpp	2001/08/08 14:11:51	1.134.2.1
+++ xml/dom_nodeimpl.cpp	2001/09/20 02:13:28
@@ -28,6 +28,7 @@
 
 #include "dom_elementimpl.h"
 #include "dom_docimpl.h"
+#include "dom_textimpl.h"
 #include "dom2_eventsimpl.h"
 
 #include <kdebug.h>
@@ -180,86 +181,63 @@ NodeImpl *NodeImpl::addChild(NodeImpl *)
   return 0;
 }
 
-QString NodeImpl::toHTML() const
+QString NodeImpl::toXML() const
 {
-    NodeImpl* fc = firstChild();
-    if ( fc )
-        return fc->recursive_toHTML(true);
+    switch (nodeType()) {
+        case Node::ELEMENT_NODE:
+            return const_cast<ElementImpl*>(static_cast<const ElementImpl*>(this))->toXML();
+        case Node::ATTRIBUTE_NODE:
+            return const_cast<AttrImpl*>(static_cast<const AttrImpl*>(this))->toXML();
+        case Node::TEXT_NODE:
+            return const_cast<TextImpl*>(static_cast<const TextImpl*>(this))->toXML();
+        
+        /*
+        We don't handle the following types:
+     
+        CDATA_SECTION_NODE = 4,
+        ENTITY_REFERENCE_NODE = 5,
+        ENTITY_NODE = 6,
+        PROCESSING_INSTRUCTION_NODE = 7,
+        COMMENT_NODE = 8,
+        DOCUMENT_NODE = 9,
+        DOCUMENT_TYPE_NODE = 10,
+        DOCUMENT_FRAGMENT_NODE = 11,
+        NOTATION_NODE = 12
+        
+        Should we?
+        */
 
-    return "";
+        default:
+            QString str;
+            // We resort to this function only if it wasn't overriden.
+            // Here we assume we know nothing of the node's type, so we'll
+            // just scan it's children.
+            if ( NodeImpl *n = firstChild() ) {
+                do { str += n->toXML(); } while (n = n->nextSibling());
+            }
+            return str;
+    }
 }
 
-QString NodeImpl::recursive_toHTML(bool start) const
+QString NodeImpl::toHTML() const
 {
-    QString me = "";
-
-    // Copy who I am into the htmlText string
-    if ( nodeType() == Node::TEXT_NODE )
-        me = nodeValue().string();
-    else
-    {
-        // If I am an element, not a text
-        NodeImpl* temp = previousSibling();
-        if(temp)
-        {
-            if( !start && (temp->nodeType() != Node::TEXT_NODE && nodeType() != Node::TEXT_NODE ) )
-                me = QString("    ") + QChar('<') + nodeName().string();
-            else
-                me = QChar('<') + nodeName().string();
-        }
-        else
-            me = QChar('<') + nodeName().string();
-        // print attributes
-        if( nodeType() == Node::ELEMENT_NODE )
-        {
-            ElementImpl *el = const_cast<ElementImpl*>(static_cast<const ElementImpl *>(this));
-            AttrImpl *attr;
-            int exceptioncode;
-            if(el->namedAttrMap) {
-                NamedNodeMapImpl *attrs = el->namedAttrMap;
-            unsigned long lmap = attrs->length(exceptioncode);
-            for( unsigned int j=0; j<lmap; j++ )
-            {
-                attr = static_cast<AttrImpl*>(attrs->item(j,exceptioncode));
-                me += " " + attr->name().string() + "=\"" + attr->value().string() + "\"";
-                }
+    switch (nodeType()) {
+        case Node::ELEMENT_NODE:
+            return const_cast<ElementImpl*>(static_cast<const ElementImpl*>(this))->toHTML();
+        case Node::ATTRIBUTE_NODE:
+            return const_cast<AttrImpl*>(static_cast<const AttrImpl*>(this))->toHTML();
+        case Node::TEXT_NODE:
+            return const_cast<TextImpl*>(static_cast<const TextImpl*>(this))->toHTML();
+        default:
+            QString str;
+            // We resort to this function only if it wasn't overriden.
+            // Here we assume we know nothing of the node's type, so we'll
+            // just scan it's children.
+            if ( NodeImpl *n = firstChild() ) {
+                do { str += n->toHTML(); } while (n = n->nextSibling());
             }
-        }
-
-        // print ending bracket of start tag
-        if( firstChild() == 0 )     // if element has no endtag
-                me += " />\n";
-        else                        // if element has endtag
-        {
-                NodeImpl* temp = nextSibling();
-                if(temp)
-                {
-                    if( (temp->nodeType() != Node::TEXT_NODE) )
-                        me += ">\n";
-                    else
-                        me += ">";
-                }
-                else
-                    me += ">";
-        }
-    }
-
-    NodeImpl* n;
-
-    if( (n = firstChild()) )
-    {
-        // print firstChild
-        me += n->recursive_toHTML( );
-
-        // Print my ending tag
-        if ( nodeType() != Node::TEXT_NODE )
-            me += "</" + nodeName().string() + ">\n";
+            return str;
     }
-    // print next sibling
-    if( (n = nextSibling()) )
-        me += n->recursive_toHTML( );
-
-    return me;
 }
 
 void NodeImpl::applyChanges(bool, bool)
Index: xml/dom_nodeimpl.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_nodeimpl.h,v
retrieving revision 1.88
diff -u -3 -d -p -r1.88 dom_nodeimpl.h
--- xml/dom_nodeimpl.h	2001/07/18 16:46:29	1.88
+++ xml/dom_nodeimpl.h	2001/09/20 02:13:28
@@ -241,7 +241,7 @@ public:
     virtual bool isInline() const { return true; }
     virtual void printTree(int indent=0);
     virtual QString toHTML() const;
-    QString recursive_toHTML(bool start = false) const;
+    virtual QString toXML() const;
 
     virtual void applyChanges(bool top = true, bool force = true);
     virtual void getCursor(int offset, int &_x, int &_y, int &height);
Index: xml/dom_textimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_textimpl.cpp,v
retrieving revision 1.68
diff -u -3 -d -p -r1.68 dom_textimpl.cpp
--- xml/dom_textimpl.cpp	2001/07/18 16:46:29	1.68
+++ xml/dom_textimpl.cpp	2001/09/20 02:13:28
@@ -410,6 +410,33 @@ TextImpl *TextImpl::createNew(DOMStringI
     return new TextImpl(docPtr(),_str);
 }
 
+QString TextImpl::toXML() const
+{
+    QString str;
+    QString text = nodeValue().string();
+    int length = text.length();
+    const QChar *c = text.unicode();
+    
+    for (int i=0; i<length; i++) {
+        if (*c == '&')
+            str += "&amp;";
+        else if (*c == '<')
+            str += "&lt;";
+        else if (*c == '>')
+            str += "&gt;";
+        else
+            str += *c;
+        c++;
+    }
+    
+    return str;
+}
+
+QString TextImpl::toHTML() const
+{
+    return toXML();
+}
+
 // ---------------------------------------------------------------------------
 
 CDATASectionImpl::CDATASectionImpl(DocumentPtr *impl, const DOMString &_text) : TextImpl(impl,_text)
Index: xml/dom_textimpl.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_textimpl.h,v
retrieving revision 1.42
diff -u -3 -d -p -r1.42 dom_textimpl.h
--- xml/dom_textimpl.h	2001/06/08 17:08:36	1.42
+++ xml/dom_textimpl.h	2001/09/20 02:13:29
@@ -117,6 +117,9 @@ public:
     virtual NodeImpl *cloneNode(bool deep, int &exceptioncode);
     virtual void recalcStyle();
     virtual bool childTypeAllowed( unsigned short type );
+    
+    virtual QString toXML() const;
+    virtual QString toHTML() const;
 
 protected:
     virtual TextImpl *createNew(DOMStringImpl *_str);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic