Changeset 8096 in webkit


Ignore:
Timestamp:
Dec 1, 2004 1:52:22 PM (19 years ago)
Author:
kocienda
Message:

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.
Location:
trunk
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog-2005-08-23

    r8094 r8096  
     12004-12-01  Ken Kocienda  <kocienda@apple.com>
     2
     3        Reviewed by Hyatt
     4       
     5        Some improvements for paste, including some new code to annotate
     6        whitespace when writing to the pasteboard to ensure that the meaning
     7        of the markup on the pasteboard is unambiguous.
     8       
     9        There is also new code for reading this annotated markup from the pasteboard,
     10        removing the nodes that were added only to prevent ambiguity.
     11
     12        * WebCore.pbproj/project.pbxproj: Added html_interchange.h and html_interchange.cpp files.
     13        The header should have been added earlier, but I did not do so.
     14        * khtml/editing/html_interchange.cpp: Added.
     15        (convertHTMLTextToInterchangeFormat):
     16        * khtml/editing/html_interchange.h: Added some new constants for use with whitespace annotations.
     17        * khtml/editing/htmlediting.cpp:
     18        (khtml::ReplacementFragment::ReplacementFragment): Now looks for and removes annotations added for whitespace.
     19        Also fixed a bug in the code that counts blocks in a fragment.
     20        (khtml::ReplacementFragment::isInterchangeConvertedSpaceSpan): New helper. Recognizes annotation spans.
     21        (khtml::ReplacementFragment::insertNodeBefore): New helper.
     22        (khtml::ReplaceSelectionCommand::doApply): Fixed a bug in the code that sets the start position
     23        for the replacement after deleting. This was causing a bug when pasting at the end of a block.
     24        * khtml/editing/htmlediting.h: Add some new declarations.
     25        * khtml/xml/dom2_rangeimpl.cpp:
     26        (DOM::RangeImpl::toHTML): Calls to startMarkup now pass true for the new annotate flag.
     27        * khtml/xml/dom_nodeimpl.cpp:
     28        (NodeImpl::stringValueForRange): New helper.
     29        (NodeImpl::renderedText): New helper to return only the rendered text in a node.
     30        (NodeImpl::startMarkup): Now takes an additional flag to control whether interchange annotations
     31        should be added. Called by the paste code.
     32        * khtml/xml/dom_nodeimpl.h: Added and modified function declarations.
     33
     34        New test to check the khtml::ReplaceSelectionCommand::doApply fix.
     35        * layout-tests/editing/pasteboard/paste-text-010-expected.txt: Added.
     36        * layout-tests/editing/pasteboard/paste-text-010.html: Added.
     37
    1382004-11-30  Chris Blumenberg  <cblu@apple.com>
    239
  • trunk/WebCore/WebCore.pbproj/project.pbxproj

    r8053 r8096  
    540540                                939FF8EF0702B1B100979E5E,
    541541                                BECE67BE07087B250007C14B,
     542                                BEA5E01E075CEDAC0098A432,
    542543                        );
    543544                        isa = PBXHeadersBuildPhase;
     
    827828                                93ABE074070285F600BD91F9,
    828829                                939FF8EE0702B1B100979E5E,
     830                                BEA5DBDB075CEDA00098A432,
    829831                        );
    830832                        isa = PBXSourcesBuildPhase;
     
    33913393                        };
    33923394                };
     3395                BEA5DBDA075CEDA00098A432 = {
     3396                        fileEncoding = 30;
     3397                        isa = PBXFileReference;
     3398                        lastKnownFileType = sourcecode.cpp.cpp;
     3399                        name = html_interchange.cpp;
     3400                        path = editing/html_interchange.cpp;
     3401                        refType = 4;
     3402                        sourceTree = "<group>";
     3403                };
     3404                BEA5DBDB075CEDA00098A432 = {
     3405                        fileRef = BEA5DBDA075CEDA00098A432;
     3406                        isa = PBXBuildFile;
     3407                        settings = {
     3408                        };
     3409                };
     3410                BEA5E01D075CEDAC0098A432 = {
     3411                        fileEncoding = 30;
     3412                        isa = PBXFileReference;
     3413                        lastKnownFileType = sourcecode.c.h;
     3414                        name = html_interchange.h;
     3415                        path = editing/html_interchange.h;
     3416                        refType = 4;
     3417                        sourceTree = "<group>";
     3418                };
     3419                BEA5E01E075CEDAC0098A432 = {
     3420                        fileRef = BEA5E01D075CEDAC0098A432;
     3421                        isa = PBXBuildFile;
     3422                        settings = {
     3423                        };
     3424                };
    33933425                BEB1DD0805C197DF00DD1F43 = {
    33943426                        children = (
    33953427                                BE9185DD05EE59B80081354D,
    33963428                                BE9185E005EE59B80081354D,
     3429                                BEA5DBDA075CEDA00098A432,
     3430                                BEA5E01D075CEDAC0098A432,
    33973431                                BE02D4E6066F908A0076809F,
    33983432                                BE02D4E7066F908A0076809F,
  • trunk/WebCore/khtml/editing/html_interchange.h

    r8087 r8096  
    2727#define KHTML_EDITING_HTML_INTERCHANGE_H
    2828
     29class QString;
     30
    2931#define KHTMLInterchangeNewline   "KHTMLInterchangeNewline"
     32#define AppleConvertedSpace       "Apple-converted-space"
    3033
    3134enum EAnnotateForInterchange { DoNotAnnotateForInterchange, AnnotateForInterchange };
    3235
     36QString convertHTMLTextToInterchangeFormat(const QString &);
     37
    3338#endif
  • trunk/WebCore/khtml/editing/htmlediting.cpp

    r8089 r8096  
    27002700
    27012701    NodeImpl *node = firstChild;
    2702     int blockCount = 0;
     2702    int realBlockCount = 0;
    27032703    NodeImpl *commentToDelete = 0;
    27042704    while (node) {
     
    27082708            commentToDelete = node;
    27092709        }
     2710        else if (isInterchangeConvertedSpaceSpan(node)) {
     2711            NodeImpl *n = 0;
     2712            while ((n = node->firstChild())) {
     2713                n->ref();
     2714                removeNode(n);
     2715                insertNodeBefore(n, node);
     2716                n->deref();
     2717            }
     2718            removeNode(node);
     2719            if (n)
     2720                next = n->traverseNextNode();
     2721        }
    27102722        else if (isProbablyBlock(node))
    2711             blockCount++;   
     2723            realBlockCount++;   
    27122724        node = next;
    2713      }
    2714 
    2715      if (commentToDelete)
     2725    }
     2726
     2727    if (commentToDelete)
    27162728        removeNode(commentToDelete);
    27172729
     2730    int blockCount = realBlockCount;
    27182731    firstChild = m_fragment->firstChild();
    27192732    lastChild = m_fragment->lastChild();
    27202733    if (!isProbablyBlock(firstChild))
    27212734        blockCount++;
    2722     if (!isProbablyBlock(lastChild) && firstChild != lastChild)
     2735    if (!isProbablyBlock(lastChild) && realBlockCount > 0)
    27232736        blockCount++;
    27242737
     
    28022815}
    28032816
     2817bool ReplacementFragment::isInterchangeConvertedSpaceSpan(const NodeImpl *node)
     2818{
     2819    static DOMString convertedSpaceSpanClass(AppleConvertedSpace);
     2820    return node->isHTMLElement() && static_cast<const HTMLElementImpl *>(node)->getAttribute(ATTR_CLASS) == convertedSpaceSpanClass;
     2821}
     2822
    28042823void ReplacementFragment::removeNode(NodeImpl *node)
    28052824{
     
    28142833    parent->removeChild(node, exceptionCode);
    28152834    ASSERT(exceptionCode == 0);
     2835}
     2836
     2837void ReplacementFragment::insertNodeBefore(NodeImpl *node, NodeImpl *refNode)
     2838{
     2839    if (!node || !refNode)
     2840        return;
     2841       
     2842    NodeImpl *parent = refNode->parentNode();
     2843    if (!parent)
     2844        return;
     2845       
     2846    int exceptionCode = 0;
     2847    parent->insertBefore(node, refNode, exceptionCode);
     2848    ASSERT(exceptionCode == 0);
    28162849 }
     2850
    28172851
    28182852bool isComment(const NodeImpl *node)
     
    28452879        case ID_TD:
    28462880        case ID_TH:
    2847         case ID_TR:
    28482881        case ID_UL:
    28492882            return true;
     
    28952928   
    28962929    selection = endingSelection();
    2897     if (!startAtBlockBoundary || !startPos.node()->inDocument())
     2930    if (startAtStartOfBlock && startBlock->inDocument())
     2931        startPos = Position(startBlock, 0);
     2932    else if (startAtEndOfBlock)
     2933        startPos = selection.start().downstream(StayInBlock);
     2934    else
    28982935        startPos = selection.start().upstream(upstreamStayInBlock);
    28992936    endPos = selection.end().downstream();
  • trunk/WebCore/khtml/editing/htmlediting.h

    r8087 r8096  
    515515
    516516    static bool isInterchangeNewlineComment(const DOM::NodeImpl *);
     517    static bool isInterchangeConvertedSpaceSpan(const DOM::NodeImpl *);
     518
     519    // A couple simple DOM helpers
    517520    void removeNode(DOM::NodeImpl *);
     521    void insertNodeBefore(DOM::NodeImpl *node, DOM::NodeImpl *refNode);
    518522
    519523    EFragmentType m_type;
  • trunk/WebCore/khtml/xml/dom2_rangeimpl.cpp

    r8090 r8096  
    876876       
    877877        // Add the node to the markup.
    878         markups.append(n->startMarkup(this));
     878        markups.append(n->startMarkup(this, annotate));
    879879        if (nodes) {
    880880            nodes->append(n);
     
    905905                        if (n != nextParent) {
    906906                            for (NodeImpl *parent = n->parent(); parent != 0 && parent != nextParent; parent = parent->parentNode()) {
    907                                 markups.prepend(parent->startMarkup(this));
     907                                markups.prepend(parent->startMarkup(this, annotate));
    908908                                markups.append(parent->endMarkup());
    909909                                if (nodes) {
     
    934934            }
    935935        }
    936         markups.prepend(ancestor->startMarkup(this));
     936        markups.prepend(ancestor->startMarkup(this, annotate));
    937937        markups.append(ancestor->endMarkup());
    938938        if (nodes) {
     
    952952        }
    953953    }
    954        
    955     return markups.join("");
     954   
     955    return markups.join("");;
    956956}
    957957
  • trunk/WebCore/khtml/xml/dom_nodeimpl.cpp

    r8085 r8096  
    3636#include "css/csshelper.h"
    3737#include "css/cssstyleselector.h"
     38#include "editing/html_interchange.h"
    3839#include "editing/selection.h"
    3940
     
    297298}
    298299
    299 QString NodeImpl::startMarkup(const RangeImpl *range) const
     300QString NodeImpl::stringValueForRange(const RangeImpl *range) const
     301{
     302    DOMString str = nodeValue().copy();
     303    if (range) {
     304        int exceptionCode;
     305        if (this == range->endContainer(exceptionCode)) {
     306            str.truncate(range->endOffset(exceptionCode));
     307        }
     308        if (this == range->startContainer(exceptionCode)) {
     309            str.remove(0, range->startOffset(exceptionCode));
     310        }
     311    }
     312    return str.string();
     313}
     314
     315QString NodeImpl::renderedText(const RangeImpl *range) const
     316{
     317    QString result;
     318
     319    RenderObject *r = renderer();
     320    if (!r)
     321        return result;
     322   
     323    if (!isTextNode())
     324        return result;
     325
     326    int exceptionCode;
     327    const TextImpl *textNode = static_cast<const TextImpl *>(this);
     328    unsigned startOffset = 0;
     329    unsigned endOffset = textNode->length();
     330
     331    if (range && this == range->startContainer(exceptionCode))
     332        startOffset = range->startOffset(exceptionCode);
     333    if (range && this == range->endContainer(exceptionCode))
     334        endOffset = range->endOffset(exceptionCode);
     335   
     336    RenderText *textRenderer = static_cast<RenderText *>(r);
     337    QString str = nodeValue().string();
     338    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
     339        unsigned start = box->m_start;
     340        unsigned end = box->m_start + box->m_len;
     341        if (endOffset < start)
     342            break;
     343        if (startOffset <= end) {
     344            unsigned s = kMax(start, startOffset);
     345            unsigned e = kMin(end, endOffset);
     346            result.append(str.mid(s, e-s));
     347        }
     348    }
     349   
     350    return result;
     351}
     352
     353QString NodeImpl::startMarkup(const RangeImpl *range, EAnnotateForInterchange annotate) const
    300354{
    301355    unsigned short type = nodeType();
    302356    if (type == Node::TEXT_NODE) {
    303357        DOMString str = nodeValue().copy();
    304         if (range) {
    305             int exceptionCode;
    306             if (this == range->endContainer(exceptionCode)) {
    307                 str.truncate(range->endOffset(exceptionCode));
    308             }
    309             if (this == range->startContainer(exceptionCode)) {
    310                 str.remove(0, range->startOffset(exceptionCode));
    311             }
    312         }
    313358        Id parentID = parentNode()->id();
    314359        bool dontEscape = (parentID == ID_SCRIPT || parentID == ID_TEXTAREA || parentID == ID_STYLE);
    315         return dontEscape ? str.string() : escapeHTML(str.string());       
     360        if (dontEscape)
     361            return stringValueForRange(range);
     362        if (annotate)
     363            return convertHTMLTextToInterchangeFormat(escapeHTML(renderedText(range)));
     364        return escapeHTML(stringValueForRange(range));
    316365    } else if (type == Node::COMMENT_NODE) {
    317366        return static_cast<const CommentImpl *>(this)->toString().string();
  • trunk/WebCore/khtml/xml/dom_nodeimpl.h

    r8082 r8096  
    2929#include "dom/dom_string.h"
    3030#include "dom/dom_node.h"
     31#include "editing/html_interchange.h"
    3132#include "misc/helper.h"
    3233#include "misc/shared.h"
     
    261262   
    262263    virtual bool isInline() const;
    263     QString startMarkup(const RangeImpl *range) const;
     264    QString stringValueForRange(const RangeImpl *range) const;
     265    QString renderedText(const RangeImpl *range) const;
     266    QString startMarkup(const RangeImpl *range, EAnnotateForInterchange annotate=DoNotAnnotateForInterchange) const;
    264267    QString endMarkup(void) const;
    265268    virtual QString toHTML() const;
Note: See TracChangeset for help on using the changeset viewer.