Reviewed by Hyatt
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Dec 2004 21:52:22 +0000 (21:52 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Dec 2004 21:52:22 +0000 (21:52 +0000)
        Some improvements for paste, including some new code to annotate
        whitespace when writing to the pasteboard to ensure that the meaning
        of the markup on the pasteboard is unambiguous.

        There is also new code for reading this annotated markup from the pasteboard,
        removing the nodes that were added only to prevent ambiguity.

        * WebCore.pbproj/project.pbxproj: Added html_interchange.h and html_interchange.cpp files.
        The header should have been added earlier, but I did not do so.
        * khtml/editing/html_interchange.cpp: Added.
        (convertHTMLTextToInterchangeFormat):
        * khtml/editing/html_interchange.h: Added some new constants for use with whitespace annotations.
        * khtml/editing/htmlediting.cpp:
        (khtml::ReplacementFragment::ReplacementFragment): Now looks for and removes annotations added for whitespace.
        Also fixed a bug in the code that counts blocks in a fragment.
        (khtml::ReplacementFragment::isInterchangeConvertedSpaceSpan): New helper. Recognizes annotation spans.
        (khtml::ReplacementFragment::insertNodeBefore): New helper.
        (khtml::ReplaceSelectionCommand::doApply): Fixed a bug in the code that sets the start position
        for the replacement after deleting. This was causing a bug when pasting at the end of a block.
        * khtml/editing/htmlediting.h: Add some new declarations.
        * khtml/xml/dom2_rangeimpl.cpp:
        (DOM::RangeImpl::toHTML): Calls to startMarkup now pass true for the new annotate flag.
        * khtml/xml/dom_nodeimpl.cpp:
        (NodeImpl::stringValueForRange): New helper.
        (NodeImpl::renderedText): New helper to return only the rendered text in a node.
        (NodeImpl::startMarkup): Now takes an additional flag to control whether interchange annotations
        should be added. Called by the paste code.
        * khtml/xml/dom_nodeimpl.h: Added and modified function declarations.

        New test to check the khtml::ReplaceSelectionCommand::doApply fix.
        * layout-tests/editing/pasteboard/paste-text-010-expected.txt: Added.
        * layout-tests/editing/pasteboard/paste-text-010.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8096 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/editing/pasteboard/paste-text-010-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/paste-text-010.html [new file with mode: 0644]
WebCore/ChangeLog-2005-08-23
WebCore/WebCore.pbproj/project.pbxproj
WebCore/khtml/editing/html_interchange.cpp [new file with mode: 0644]
WebCore/khtml/editing/html_interchange.h
WebCore/khtml/editing/htmlediting.cpp
WebCore/khtml/editing/htmlediting.h
WebCore/khtml/xml/dom2_rangeimpl.cpp
WebCore/khtml/xml/dom_nodeimpl.cpp
WebCore/khtml/xml/dom_nodeimpl.h

diff --git a/LayoutTests/editing/pasteboard/paste-text-010-expected.txt b/LayoutTests/editing/pasteboard/paste-text-010-expected.txt
new file mode 100644 (file)
index 0000000..710a95e
--- /dev/null
@@ -0,0 +1,19 @@
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x112 [border: (2px solid #FF0000)]
+        RenderText {TEXT} at (14,14) size 348x28
+          text run at (14,14) width 348: "There is a tide in the affairs of men."
+        RenderBR {BR} at (0,0) size 0x0
+        RenderBR {BR} at (14,42) size 0x28
+        RenderText {TEXT} at (14,70) size 74x28
+          text run at (14,70) width 74: "of men."
+        RenderText {TEXT} at (88,70) size 74x28
+          text run at (88,70) width 74: "of men."
+        RenderBR {BR} at (0,0) size 0x0
+selection is CARET:
+start:      position 7 of child 5 {TEXT} of child 2 {DIV} of root {BODY}
+upstream:   position 7 of child 5 {TEXT} of child 2 {DIV} of root {BODY}
+downstream: position 0 of child 6 {BR} of child 2 {DIV} of root {BODY}
diff --git a/LayoutTests/editing/pasteboard/paste-text-010.html b/LayoutTests/editing/pasteboard/paste-text-010.html
new file mode 100644 (file)
index 0000000..95ff47c
--- /dev/null
@@ -0,0 +1,44 @@
+<html> 
+<head>
+
+<style>
+.editing { 
+    border: 2px solid red; 
+    padding: 12px; 
+    font-size: 24px; 
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+// There was a bug when pasting at the end of the block. The content was inserted at the 
+// start of the block instead of the end. This tests the insert-at-end case.
+
+function editingTest() {
+    for (i = 0; i < 31; i++)
+        moveSelectionForwardByCharacterCommand();
+    for (i = 0; i < 7; i++)
+        extendSelectionForwardByCharacterCommand();
+    copyCommand();
+    moveSelectionForwardByCharacterCommand();
+    insertNewlineCommand();
+    insertNewlineCommand();
+    pasteCommand();
+    pasteCommand();
+}
+
+</script>
+
+<title>Editing Test</title> 
+</head> 
+<body contenteditable id="root">
+
+<div class="editing" id="test">There is a tide in the affairs of men.</div>
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
index 4abbcc2d454c35ad40158206c47020c5dd6c4a9d..986aa325664111b9b0c2d22fa874f9312be3c53f 100644 (file)
@@ -1,3 +1,40 @@
+2004-12-01  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by Hyatt
+        
+        Some improvements for paste, including some new code to annotate
+        whitespace when writing to the pasteboard to ensure that the meaning
+        of the markup on the pasteboard is unambiguous.
+        
+        There is also new code for reading this annotated markup from the pasteboard,
+        removing the nodes that were added only to prevent ambiguity.
+
+        * WebCore.pbproj/project.pbxproj: Added html_interchange.h and html_interchange.cpp files.
+        The header should have been added earlier, but I did not do so.
+        * khtml/editing/html_interchange.cpp: Added.
+        (convertHTMLTextToInterchangeFormat):
+        * khtml/editing/html_interchange.h: Added some new constants for use with whitespace annotations.
+        * khtml/editing/htmlediting.cpp:
+        (khtml::ReplacementFragment::ReplacementFragment): Now looks for and removes annotations added for whitespace.
+        Also fixed a bug in the code that counts blocks in a fragment.
+        (khtml::ReplacementFragment::isInterchangeConvertedSpaceSpan): New helper. Recognizes annotation spans.
+        (khtml::ReplacementFragment::insertNodeBefore): New helper.
+        (khtml::ReplaceSelectionCommand::doApply): Fixed a bug in the code that sets the start position
+        for the replacement after deleting. This was causing a bug when pasting at the end of a block.
+        * khtml/editing/htmlediting.h: Add some new declarations.
+        * khtml/xml/dom2_rangeimpl.cpp:
+        (DOM::RangeImpl::toHTML): Calls to startMarkup now pass true for the new annotate flag.
+        * khtml/xml/dom_nodeimpl.cpp:
+        (NodeImpl::stringValueForRange): New helper.
+        (NodeImpl::renderedText): New helper to return only the rendered text in a node.
+        (NodeImpl::startMarkup): Now takes an additional flag to control whether interchange annotations
+        should be added. Called by the paste code.
+        * khtml/xml/dom_nodeimpl.h: Added and modified function declarations.
+
+        New test to check the khtml::ReplaceSelectionCommand::doApply fix.
+        * layout-tests/editing/pasteboard/paste-text-010-expected.txt: Added.
+        * layout-tests/editing/pasteboard/paste-text-010.html: Added.
+
 2004-11-30  Chris Blumenberg  <cblu@apple.com>
 
         * ChangeLog: removed conflict marker
index ad24b2f39148153c7f8105a92d98dab695c7e09d..3d4923525fa1a6950139263b58f5381ece349d30 100644 (file)
                                932B9835070297DC0032804F,
                                939FF8EF0702B1B100979E5E,
                                BECE67BE07087B250007C14B,
+                               BEA5E01E075CEDAC0098A432,
                        );
                        isa = PBXHeadersBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                93ABE072070285F600BD91F9,
                                93ABE074070285F600BD91F9,
                                939FF8EE0702B1B100979E5E,
+                               BEA5DBDB075CEDA00098A432,
                        );
                        isa = PBXSourcesBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                        settings = {
                        };
                };
+               BEA5DBDA075CEDA00098A432 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = html_interchange.cpp;
+                       path = editing/html_interchange.cpp;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               BEA5DBDB075CEDA00098A432 = {
+                       fileRef = BEA5DBDA075CEDA00098A432;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               BEA5E01D075CEDAC0098A432 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = html_interchange.h;
+                       path = editing/html_interchange.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               BEA5E01E075CEDAC0098A432 = {
+                       fileRef = BEA5E01D075CEDAC0098A432;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
                BEB1DD0805C197DF00DD1F43 = {
                        children = (
                                BE9185DD05EE59B80081354D,
                                BE9185E005EE59B80081354D,
+                               BEA5DBDA075CEDA00098A432,
+                               BEA5E01D075CEDAC0098A432,
                                BE02D4E6066F908A0076809F,
                                BE02D4E7066F908A0076809F,
                                93ABE067070285F600BD91F9,
diff --git a/WebCore/khtml/editing/html_interchange.cpp b/WebCore/khtml/editing/html_interchange.cpp
new file mode 100644 (file)
index 0000000..e50b823
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "html_interchange.h"
+
+#include "qstring.h"
+
+namespace {
+
+QString convertedSpaceString() 
+{
+    static QString convertedSpaceString;
+    if (convertedSpaceString.length() == 0) {
+        convertedSpaceString = "<span class=\"";
+        convertedSpaceString += AppleConvertedSpace;
+        convertedSpaceString += "\">";
+        convertedSpaceString += QChar(0xa0);
+        convertedSpaceString += "</span>";
+    }
+    return convertedSpaceString;
+}
+
+bool isWSTreatedAsSpace(const QChar &c)
+{
+    static QChar nbsp = QChar(0xa0);
+    return c.isSpace() && c != nbsp;
+}
+
+} // end anonymous namespace
+
+QString convertHTMLTextToInterchangeFormat(const QString &in)
+{
+    QString s;
+
+    unsigned int i = 0;
+    unsigned int consumed = 0;
+    while (i < in.length()) {
+        consumed = 1;
+        const QChar &c(in[i].latin1());
+        if (isWSTreatedAsSpace(c)) {
+            // count number of adjoining spaces
+            unsigned int j = i + 1;
+            while (j < in.length() && isWSTreatedAsSpace(in[j].latin1()))
+                j++;
+            unsigned int count = j - i;
+            consumed = count;
+            while (count) {
+                unsigned int add = count % 3;
+                switch (add) {
+                    case 0:
+                        s += convertedSpaceString();
+                        s += ' ';
+                        s += convertedSpaceString();
+                        add = 3;
+                        break;
+                    case 1:
+                        if (i == 0 || i + 1 == in.length()) // at start or end of string
+                            s += convertedSpaceString();
+                        else
+                            s += ' ';
+                        break;
+                    case 2:
+                        if (i == 0) {
+                             // at start of string
+                            s += convertedSpaceString();
+                            s += ' ';
+                        }
+                        else if (i + 2 == in.length()) {
+                             // at end of string
+                            s += convertedSpaceString();
+                            s += convertedSpaceString();
+                        }
+                        else {
+                            s += convertedSpaceString();
+                            s += ' ';
+                        }
+                        break;
+                }
+                count -= add;
+            }
+        }
+        else {
+            s += in[i];
+        }
+        i += consumed;
+    }
+
+    return s;
+}
index 20d2eb958f5034aa3417242cc96a243c5e52c0e2..b5e9579375c484895e050077ede071021162e415 100644 (file)
 #ifndef KHTML_EDITING_HTML_INTERCHANGE_H
 #define KHTML_EDITING_HTML_INTERCHANGE_H
 
+class QString;
+
 #define KHTMLInterchangeNewline   "KHTMLInterchangeNewline"
+#define AppleConvertedSpace       "Apple-converted-space"
 
 enum EAnnotateForInterchange { DoNotAnnotateForInterchange, AnnotateForInterchange };
 
+QString convertHTMLTextToInterchangeFormat(const QString &);
+
 #endif
index 272376809fbc2e2cf84213fce30ca82c6cf0aa05..6c366b62c63ebc1bc0522fdef41c5133a7fab981 100644 (file)
@@ -2699,7 +2699,7 @@ ReplacementFragment::ReplacementFragment(DocumentFragmentImpl *fragment)
     m_type = TreeFragment;
 
     NodeImpl *node = firstChild;
-    int blockCount = 0;
+    int realBlockCount = 0;
     NodeImpl *commentToDelete = 0;
     while (node) {
         NodeImpl *next = node->traverseNextNode();
@@ -2707,19 +2707,32 @@ ReplacementFragment::ReplacementFragment(DocumentFragmentImpl *fragment)
             m_hasInterchangeNewlineComment = true;
             commentToDelete = node;
         }
+        else if (isInterchangeConvertedSpaceSpan(node)) {
+            NodeImpl *n = 0;
+            while ((n = node->firstChild())) {
+                n->ref();
+                removeNode(n);
+                insertNodeBefore(n, node);
+                n->deref();
+            }
+            removeNode(node);
+            if (n)
+                next = n->traverseNextNode();
+        }
         else if (isProbablyBlock(node))
-            blockCount++;    
+            realBlockCount++;    
         node = next;
-     }
+    }
 
-     if (commentToDelete)
+    if (commentToDelete)
         removeNode(commentToDelete);
 
+    int blockCount = realBlockCount;
     firstChild = m_fragment->firstChild();
     lastChild = m_fragment->lastChild();
     if (!isProbablyBlock(firstChild))
         blockCount++;
-    if (!isProbablyBlock(lastChild) && firstChild != lastChild)
+    if (!isProbablyBlock(lastChild) && realBlockCount > 0)
         blockCount++;
 
      if (blockCount > 1)
@@ -2801,6 +2814,12 @@ bool ReplacementFragment::isInterchangeNewlineComment(const NodeImpl *node)
     return isComment(node) && node->nodeValue() == KHTMLInterchangeNewline;
 }
 
+bool ReplacementFragment::isInterchangeConvertedSpaceSpan(const NodeImpl *node)
+{
+    static DOMString convertedSpaceSpanClass(AppleConvertedSpace);
+    return node->isHTMLElement() && static_cast<const HTMLElementImpl *>(node)->getAttribute(ATTR_CLASS) == convertedSpaceSpanClass;
+}
+
 void ReplacementFragment::removeNode(NodeImpl *node)
 {
     if (!node)
@@ -2813,8 +2832,23 @@ void ReplacementFragment::removeNode(NodeImpl *node)
     int exceptionCode = 0;
     parent->removeChild(node, exceptionCode);
     ASSERT(exceptionCode == 0);
+}
+
+void ReplacementFragment::insertNodeBefore(NodeImpl *node, NodeImpl *refNode)
+{
+    if (!node || !refNode)
+        return;
+        
+    NodeImpl *parent = refNode->parentNode();
+    if (!parent)
+        return;
+        
+    int exceptionCode = 0;
+    parent->insertBefore(node, refNode, exceptionCode);
+    ASSERT(exceptionCode == 0);
  }
 
+
 bool isComment(const NodeImpl *node)
 {
     return node && node->nodeType() == Node::COMMENT_NODE;
@@ -2844,7 +2878,6 @@ bool isProbablyBlock(const NodeImpl *node)
         case ID_PRE:
         case ID_TD:
         case ID_TH:
-        case ID_TR:
         case ID_UL:
             return true;
     }
@@ -2894,7 +2927,11 @@ void ReplaceSelectionCommand::doApply()
     }
     
     selection = endingSelection();
-    if (!startAtBlockBoundary || !startPos.node()->inDocument())
+    if (startAtStartOfBlock && startBlock->inDocument())
+        startPos = Position(startBlock, 0);
+    else if (startAtEndOfBlock)
+        startPos = selection.start().downstream(StayInBlock);
+    else
         startPos = selection.start().upstream(upstreamStayInBlock);
     endPos = selection.end().downstream(); 
     
index ae1dc5f5798900cea4901dc1b0c26d867136a28c..fd0b89cc6da7b2dc280f033a7c36a0f159a5017b 100644 (file)
@@ -514,7 +514,11 @@ private:
     ReplacementFragment &operator=(const ReplacementFragment &);
 
     static bool isInterchangeNewlineComment(const DOM::NodeImpl *);
+    static bool isInterchangeConvertedSpaceSpan(const DOM::NodeImpl *);
+
+    // A couple simple DOM helpers
     void removeNode(DOM::NodeImpl *);
+    void insertNodeBefore(DOM::NodeImpl *node, DOM::NodeImpl *refNode);
 
     EFragmentType m_type;
     DOM::DocumentFragmentImpl *m_fragment;
index 2c03ef39aa297d2a33cd4facd81907ed9e6862de..e83ae28d3ad1e6df661da70e9d817f3a83408543 100644 (file)
@@ -875,7 +875,7 @@ DOMString RangeImpl::toHTML(QPtrList<NodeImpl> *nodes, EAnnotateForInterchange a
         }
         
         // Add the node to the markup.
-        markups.append(n->startMarkup(this));
+        markups.append(n->startMarkup(this, annotate));
         if (nodes) {
             nodes->append(n);
         }
@@ -904,7 +904,7 @@ DOMString RangeImpl::toHTML(QPtrList<NodeImpl> *nodes, EAnnotateForInterchange a
                         NodeImpl *nextParent = next->parentNode();
                         if (n != nextParent) {
                             for (NodeImpl *parent = n->parent(); parent != 0 && parent != nextParent; parent = parent->parentNode()) {
-                                markups.prepend(parent->startMarkup(this));
+                                markups.prepend(parent->startMarkup(this, annotate));
                                 markups.append(parent->endMarkup());
                                 if (nodes) {
                                     nodes->append(parent);
@@ -933,7 +933,7 @@ DOMString RangeImpl::toHTML(QPtrList<NodeImpl> *nodes, EAnnotateForInterchange a
                 break;
             }
         }
-        markups.prepend(ancestor->startMarkup(this));
+        markups.prepend(ancestor->startMarkup(this, annotate));
         markups.append(ancestor->endMarkup());
         if (nodes) {
             nodes->append(ancestor);
@@ -951,8 +951,8 @@ DOMString RangeImpl::toHTML(QPtrList<NodeImpl> *nodes, EAnnotateForInterchange a
             addCommentToHTMLMarkup(KHTMLInterchangeNewline, markups, AppendToMarkup);    
         }
     }
-        
-    return markups.join("");
+    
+    return markups.join("");;
 }
 
 
index cae364d21e2fe6362054bf915554d4ebfccbf536..c20ff0f7683421c0277f5baa31178a8606459682 100644 (file)
@@ -35,6 +35,7 @@
 #include "xml/dom2_rangeimpl.h"
 #include "css/csshelper.h"
 #include "css/cssstyleselector.h"
+#include "editing/html_interchange.h"
 #include "editing/selection.h"
 
 #include <kglobal.h>
@@ -296,23 +297,71 @@ static QString escapeHTML( const QString& in )
     return s;
 }
 
-QString NodeImpl::startMarkup(const RangeImpl *range) const
+QString NodeImpl::stringValueForRange(const RangeImpl *range) const
+{
+    DOMString str = nodeValue().copy();
+    if (range) {
+        int exceptionCode;
+        if (this == range->endContainer(exceptionCode)) {
+            str.truncate(range->endOffset(exceptionCode));
+        }
+        if (this == range->startContainer(exceptionCode)) {
+            str.remove(0, range->startOffset(exceptionCode));
+        }
+    }
+    return str.string();
+}
+
+QString NodeImpl::renderedText(const RangeImpl *range) const
+{
+    QString result;
+
+    RenderObject *r = renderer();
+    if (!r)
+        return result;
+    
+    if (!isTextNode())
+        return result;
+
+    int exceptionCode;
+    const TextImpl *textNode = static_cast<const TextImpl *>(this);
+    unsigned startOffset = 0;
+    unsigned endOffset = textNode->length();
+
+    if (range && this == range->startContainer(exceptionCode))
+        startOffset = range->startOffset(exceptionCode);
+    if (range && this == range->endContainer(exceptionCode))
+        endOffset = range->endOffset(exceptionCode);
+    
+    RenderText *textRenderer = static_cast<RenderText *>(r);
+    QString str = nodeValue().string();
+    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+        unsigned start = box->m_start;
+        unsigned end = box->m_start + box->m_len;
+        if (endOffset < start)
+            break;
+        if (startOffset <= end) {
+            unsigned s = kMax(start, startOffset);
+            unsigned e = kMin(end, endOffset);
+            result.append(str.mid(s, e-s));
+        }
+    }
+    
+    return result;
+}
+
+QString NodeImpl::startMarkup(const RangeImpl *range, EAnnotateForInterchange annotate) const
 {
     unsigned short type = nodeType();
     if (type == Node::TEXT_NODE) {
         DOMString str = nodeValue().copy();
-        if (range) {
-            int exceptionCode;
-            if (this == range->endContainer(exceptionCode)) {
-                str.truncate(range->endOffset(exceptionCode));
-            }
-            if (this == range->startContainer(exceptionCode)) {
-                str.remove(0, range->startOffset(exceptionCode));
-            }
-        }
         Id parentID = parentNode()->id();
         bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE);
-        return dontEscape ? str.string() : escapeHTML(str.string());        
+        if (dontEscape)
+            return stringValueForRange(range);
+        if (annotate)
+            return convertHTMLTextToInterchangeFormat(escapeHTML(renderedText(range))); 
+        return escapeHTML(stringValueForRange(range));
     } else if (type == Node::COMMENT_NODE) {
         return static_cast<const CommentImpl *>(this)->toString().string();
     } else if (type != Node::DOCUMENT_NODE) {
index 8b273e88fc72faaf49317cc3120fe6e8939b4267..f6f69a48a2b8f47f387504d2f4d46d810cf8cb55 100644 (file)
@@ -28,6 +28,7 @@
 #include "dom/dom_misc.h"
 #include "dom/dom_string.h"
 #include "dom/dom_node.h"
+#include "editing/html_interchange.h"
 #include "misc/helper.h"
 #include "misc/shared.h"
 #include "dom_atomicstring.h"
@@ -260,7 +261,9 @@ public:
     virtual bool isMouseFocusable() const;
     
     virtual bool isInline() const;
-    QString startMarkup(const RangeImpl *range) const;
+    QString stringValueForRange(const RangeImpl *range) const;
+    QString renderedText(const RangeImpl *range) const;
+    QString startMarkup(const RangeImpl *range, EAnnotateForInterchange annotate=DoNotAnnotateForInterchange) const;
     QString endMarkup(void) const;
     virtual QString toHTML() const;
     QString recursive_toHTML(bool onlyIncludeChildren=false, QPtrList<NodeImpl> *nodes=NULL) const;