Changeset 168650 in webkit


Ignore:
Timestamp:
May 12, 2014 3:47:39 PM (10 years ago)
Author:
beidson@apple.com
Message:

Teach Editor to support more direct replacement of a Node
<rdar://problem/16817952> and https://bugs.webkit.org/show_bug.cgi?id=132834

Reviewed by Enrica Casucci.

The new method "Editor::replaceNodeFromPasteboard" has the intent that the new DocumentFragment
from the pasteboard is as similar to the old Node as possible.

In practice, the new DocumentFragment:
1 - Can represent a single node that's missing various attributes the original Node had.
2 - Can be an unwanted fragment of arbitrary depth when the replacement happens inside Mail.app

This fixes both of these issues.

Add a MailBlockquoteHandling enum class for various Editor operations to pass through to the
ReplaceSelectionCommand:

  • editing/Editor.cpp:

(WebCore::Editor::handleTextEvent):
(WebCore::Editor::pasteAsFragment):
(WebCore::Editor::pasteWithPasteboard):
(WebCore::Editor::replaceSelectionWithFragment):

  • editing/Editor.h:
  • dom/TextEvent.cpp:

(WebCore::TextEvent::createForPlainTextPaste):
(WebCore::TextEvent::createForFragmentPaste):
(WebCore::TextEvent::TextEvent):

  • dom/TextEvent.h:

(WebCore::TextEvent::mailBlockquoteHandling):

  • editing/ReplaceSelectionCommand.cpp:

(WebCore::ReplaceSelectionCommand::ReplaceSelectionCommand):
(WebCore::ReplaceSelectionCommand::doApply): Consider whether or not this particular Editor

operation was meant to give special consideration to Mail's Blockquotes.

  • editing/ReplaceSelectionCommand.h:
  • editing/efl/EditorEfl.cpp:

(WebCore::Editor::pasteWithPasteboard):

  • editing/ios/EditorIOS.mm:

(WebCore::Editor::pasteWithPasteboard):

  • editing/mac/EditorMac.mm:

(WebCore::Editor::pasteWithPasteboard):
(WebCore::Editor::readSelectionFromPasteboard):
(WebCore::maybeCopyNodeAttributesToFragment): If the new DocumentFragment represents a single HTML node

with the same tag name is the original HTML node, copy over most attributes from the original node.

(WebCore::Editor::replaceNodeFromPasteboard): Create the fragment, run it through maybeCopyNodeAttributesToFragment.

  • WebCore.exp.in:
Location:
trunk/Source/WebCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r168647 r168650  
     12014-05-12  Brady Eidson  <beidson@apple.com>
     2
     3        Teach Editor to support more direct replacement of a Node
     4        <rdar://problem/16817952> and https://bugs.webkit.org/show_bug.cgi?id=132834
     5
     6        Reviewed by Enrica Casucci.
     7
     8        The new method "Editor::replaceNodeFromPasteboard" has the intent that the new DocumentFragment
     9        from the pasteboard is as similar to the old Node as possible.
     10
     11        In practice, the new DocumentFragment:
     12        1 - Can represent a single node that's missing various attributes the original Node had.
     13        2 - Can be an unwanted fragment of arbitrary depth when the replacement happens inside Mail.app
     14
     15        This fixes both of these issues.
     16
     17        Add a MailBlockquoteHandling enum class for various Editor operations to pass through to the
     18        ReplaceSelectionCommand:
     19        * editing/Editor.cpp:
     20        (WebCore::Editor::handleTextEvent):
     21        (WebCore::Editor::pasteAsFragment):
     22        (WebCore::Editor::pasteWithPasteboard):
     23        (WebCore::Editor::replaceSelectionWithFragment):
     24        * editing/Editor.h:
     25
     26        * dom/TextEvent.cpp:
     27        (WebCore::TextEvent::createForPlainTextPaste):
     28        (WebCore::TextEvent::createForFragmentPaste):
     29        (WebCore::TextEvent::TextEvent):
     30        * dom/TextEvent.h:
     31        (WebCore::TextEvent::mailBlockquoteHandling):
     32
     33        * editing/ReplaceSelectionCommand.cpp:
     34        (WebCore::ReplaceSelectionCommand::ReplaceSelectionCommand):
     35        (WebCore::ReplaceSelectionCommand::doApply): Consider whether or not this particular Editor
     36          operation was meant to give special consideration to Mail's Blockquotes.
     37        * editing/ReplaceSelectionCommand.h:
     38
     39        * editing/efl/EditorEfl.cpp:
     40        (WebCore::Editor::pasteWithPasteboard):
     41        * editing/ios/EditorIOS.mm:
     42        (WebCore::Editor::pasteWithPasteboard):
     43
     44        * editing/mac/EditorMac.mm:
     45        (WebCore::Editor::pasteWithPasteboard):
     46        (WebCore::Editor::readSelectionFromPasteboard):
     47        (WebCore::maybeCopyNodeAttributesToFragment): If the new DocumentFragment represents a single HTML node
     48          with the same tag name is the original HTML node, copy over most attributes from the original node.
     49        (WebCore::Editor::replaceNodeFromPasteboard): Create the fragment, run it through maybeCopyNodeAttributesToFragment.
     50
     51        * WebCore.exp.in:
     52
    1532014-05-12  Alex Christensen  <achristensen@webkit.org>
    254
  • trunk/Source/WebCore/WebCore.exp.in

    r168647 r168650  
    11511151__ZN7WebCore6Editor14setCompositionERKN3WTF6StringERKNS1_6VectorINS_20CompositionUnderlineELm0ENS1_15CrashOnOverflowEEEjj
    11521152__ZN7WebCore6Editor14simplifyMarkupEPNS_4NodeES2_
    1153 __ZN7WebCore6Editor15pasteAsFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbb
     1153__ZN7WebCore6Editor15pasteAsFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbNS_22MailBlockquoteHandlingE
    11541154__ZN7WebCore6Editor16pasteAsPlainTextEv
    11551155__ZN7WebCore6Editor17cancelCompositionEv
     
    11711171__ZN7WebCore6Editor26toggleOverwriteModeEnabledEv
    11721172__ZN7WebCore6Editor26writeSelectionToPasteboardERNS_10PasteboardE
    1173 __ZN7WebCore6Editor28replaceSelectionWithFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbb
     1173__ZN7WebCore6Editor28replaceSelectionWithFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbbNS_22MailBlockquoteHandlingE
    11741174__ZN7WebCore6Editor28updateEditorUINowIfScheduledEv
    11751175__ZN7WebCore6Editor29canDecreaseSelectionListLevelEv
     
    22582258__ZN7WebCore6Editor25replaceNodeFromPasteboardEPNS_4NodeERKN3WTF6StringE
    22592259__ZN7WebCore6Editor26dataSelectionForPasteboardERKN3WTF6StringE
    2260 __ZN7WebCore6Editor27readSelectionFromPasteboardERKN3WTF6StringE
     2260__ZN7WebCore6Editor27readSelectionFromPasteboardERKN3WTF6StringENS_22MailBlockquoteHandlingE
    22612261__ZN7WebCore6Editor28stringSelectionForPasteboardEv
    22622262__ZN7WebCore6Editor28toggleAutomaticLinkDetectionEv
  • trunk/Source/WebCore/dom/TextEvent.cpp

    r165676 r168650  
    2929
    3030#include "DocumentFragment.h"
     31#include "Editor.h"
    3132
    3233namespace WebCore {
     
    4445PassRefPtr<TextEvent> TextEvent::createForPlainTextPaste(PassRefPtr<AbstractView> view, const String& data, bool shouldSmartReplace)
    4546{
    46     return adoptRef(new TextEvent(view, data, 0, shouldSmartReplace, false));
     47    return adoptRef(new TextEvent(view, data, 0, shouldSmartReplace, false, MailBlockquoteHandling::RespectBlockquote));
    4748}
    4849
    49 PassRefPtr<TextEvent> TextEvent::createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle)
     50PassRefPtr<TextEvent> TextEvent::createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling mailBlockquoteHandling)
    5051{
    51     return adoptRef(new TextEvent(view, "", data, shouldSmartReplace, shouldMatchStyle));
     52    return adoptRef(new TextEvent(view, "", data, shouldSmartReplace, shouldMatchStyle, mailBlockquoteHandling));
    5253}
    5354
     
    6667    , m_shouldSmartReplace(false)
    6768    , m_shouldMatchStyle(false)
     69    , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
    6870{
    6971}
     
    7678    , m_shouldSmartReplace(false)
    7779    , m_shouldMatchStyle(false)
     80    , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
    7881{
    7982}
    8083
    81 TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, PassRefPtr<DocumentFragment> pastingFragment,
    82                      bool shouldSmartReplace, bool shouldMatchStyle)
     84TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, PassRefPtr<DocumentFragment> pastingFragment, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling mailBlockquoteHandling)
    8385    : UIEvent(eventNames().textInputEvent, true, true, view, 0)
    8486    , m_inputType(TextEventInputPaste)
     
    8789    , m_shouldSmartReplace(shouldSmartReplace)
    8890    , m_shouldMatchStyle(shouldMatchStyle)
     91    , m_mailBlockquoteHandling(mailBlockquoteHandling)
    8992{
    9093}
     
    9699    , m_shouldSmartReplace(false)
    97100    , m_shouldMatchStyle(false)
     101    , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
    98102    , m_dictationAlternatives(dictationAlternatives)
    99103{
  • trunk/Source/WebCore/dom/TextEvent.h

    r165676 r168650  
    3636    class DocumentFragment;
    3737
     38    enum class MailBlockquoteHandling;
     39
    3840    class TextEvent : public UIEvent {
    3941    public:
     
    4143        static PassRefPtr<TextEvent> create();
    4244        static PassRefPtr<TextEvent> create(PassRefPtr<AbstractView>, const String& data, TextEventInputType = TextEventInputKeyboard);
    43         static PassRefPtr<TextEvent> createForPlainTextPaste(PassRefPtr<AbstractView> view, const String& data, bool shouldSmartReplace);
    44         static PassRefPtr<TextEvent> createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle);
    45         static PassRefPtr<TextEvent> createForDrop(PassRefPtr<AbstractView> view, const String& data);
     45        static PassRefPtr<TextEvent> createForPlainTextPaste(PassRefPtr<AbstractView>, const String& data, bool shouldSmartReplace);
     46        static PassRefPtr<TextEvent> createForFragmentPaste(PassRefPtr<AbstractView>, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling);
     47        static PassRefPtr<TextEvent> createForDrop(PassRefPtr<AbstractView>, const String& data);
    4648        static PassRefPtr<TextEvent> createForDictation(PassRefPtr<AbstractView>, const String& data, const Vector<DictationAlternative>& dictationAlternatives);
    4749
     
    6365        bool shouldSmartReplace() const { return m_shouldSmartReplace; }
    6466        bool shouldMatchStyle() const { return m_shouldMatchStyle; }
     67        MailBlockquoteHandling mailBlockquoteHandling() const { return m_mailBlockquoteHandling; }
    6568        DocumentFragment* pastingFragment() const { return m_pastingFragment.get(); }
    6669        const Vector<DictationAlternative>& dictationAlternatives() const { return m_dictationAlternatives; }
     
    7073
    7174        TextEvent(PassRefPtr<AbstractView>, const String& data, TextEventInputType = TextEventInputKeyboard);
    72         TextEvent(PassRefPtr<AbstractView>, const String& data, PassRefPtr<DocumentFragment>,
    73                   bool shouldSmartReplace, bool shouldMatchStyle);
     75        TextEvent(PassRefPtr<AbstractView>, const String& data, PassRefPtr<DocumentFragment>, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling);
    7476        TextEvent(PassRefPtr<AbstractView>, const String& data, const Vector<DictationAlternative>& dictationAlternatives);
    7577
     
    8284        bool m_shouldSmartReplace;
    8385        bool m_shouldMatchStyle;
     86        MailBlockquoteHandling m_mailBlockquoteHandling;
    8487        Vector<DictationAlternative> m_dictationAlternatives;
    8588    };
  • trunk/Source/WebCore/editing/Editor.cpp

    r167542 r168650  
    267267                return true;
    268268#endif
    269             replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle());
     269            replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle(), event->mailBlockquoteHandling());
    270270#if PLATFORM(IOS)
    271271        }
     
    529529}
    530530
    531 void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle)
     531void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle, MailBlockquoteHandling respectsMailBlockquote)
    532532{
    533533    Node* target = findEventTargetFromSelection();
    534534    if (!target)
    535535        return;
    536     target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), pastingFragment, smartReplace, matchStyle), IGNORE_EXCEPTION);
     536    target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), pastingFragment, smartReplace, matchStyle, respectsMailBlockquote), IGNORE_EXCEPTION);
    537537}
    538538
     
    566566
    567567#if !PLATFORM(COCOA) && !PLATFORM(EFL)
    568 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
     568void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
    569569{
    570570    RefPtr<Range> range = selectedRange();
     
    575575    RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, *range, allowPlainText, chosePlainText);
    576576    if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
    577         pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText);
     577        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, mailBlockquoteHandling);
    578578}
    579579#endif
     
    598598}
    599599
    600 void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle)
     600void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle, MailBlockquoteHandling mailBlockquoteHandling)
    601601{
    602602    VisibleSelection selection = m_frame.selection().selection();
     
    611611    if (matchStyle)
    612612        options |= ReplaceSelectionCommand::MatchStyle;
     613    if (mailBlockquoteHandling == MailBlockquoteHandling::IgnoreBlockquote)
     614        options |= ReplaceSelectionCommand::IgnoreMailBlockquote;
     615
    613616    applyCommand(ReplaceSelectionCommand::create(document(), fragment, options, EditActionPaste));
    614617    revealSelectionAfterEditingOperation();
  • trunk/Source/WebCore/editing/Editor.h

    r168378 r168650  
    9191enum EditorParagraphSeparator { EditorParagraphSeparatorIsDiv, EditorParagraphSeparatorIsP };
    9292
     93enum class MailBlockquoteHandling {
     94    RespectBlockquote,
     95    IgnoreBlockquote,
     96};
     97
    9398class Editor {
    9499public:
     
    336341    void dismissCorrectionPanelAsIgnored();
    337342
    338     void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle);
     343    void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
    339344    void pasteAsPlainText(const String&, bool smartReplace);
    340345
     
    378383    WritingDirection baseWritingDirectionForSelectionStart() const;
    379384
    380     void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle);
     385    void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
    381386    void replaceSelectionWithText(const String&, bool selectReplacement, bool smartReplace);
    382387    bool selectionStartHasMarkerFor(DocumentMarker::MarkerType, int from, int length) const;
     
    432437    bool canCopyExcludingStandaloneImages();
    433438    void takeFindStringFromSelection();
    434     void readSelectionFromPasteboard(const String& pasteboardName);
     439    void readSelectionFromPasteboard(const String& pasteboardName, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
    435440    void replaceNodeFromPasteboard(Node*, const String& pasteboardName);
    436441    PassRefPtr<SharedBuffer> dataSelectionForPasteboard(const String& pasteboardName);
     
    451456    bool canSmartReplaceWithPasteboard(Pasteboard&);
    452457    void pasteAsPlainTextWithPasteboard(Pasteboard&);
    453     void pasteWithPasteboard(Pasteboard*, bool allowPlainText);
     458    void pasteWithPasteboard(Pasteboard*, bool allowPlainText, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
    454459    String plainTextFromPasteboard(const PasteboardPlainText&);
    455460
  • trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp

    r168460 r168650  
    379379    , m_sanitizeFragment(options & SanitizeFragment)
    380380    , m_shouldMergeEnd(false)
     381    , m_ignoreMailBlockquote(options & IgnoreMailBlockquote)
    381382{
    382383}
     
    934935   
    935936    Position insertionPos = selection.start();
    936     bool startIsInsideMailBlockquote = enclosingNodeOfType(insertionPos, isMailBlockquote, CanCrossEditingBoundary);
     937    bool shouldHandleMailBlockquote = enclosingNodeOfType(insertionPos, isMailBlockquote, CanCrossEditingBoundary) && !m_ignoreMailBlockquote;
    937938    bool selectionIsPlainText = !selection.isContentRichlyEditable();
    938939    Element* currentRoot = selection.rootEditableElement();
    939940
    940     if ((selectionStartWasStartOfParagraph && selectionEndWasEndOfParagraph && !startIsInsideMailBlockquote) ||
    941         startBlock == currentRoot || isListItem(startBlock) || selectionIsPlainText)
     941    if ((selectionStartWasStartOfParagraph && selectionEndWasEndOfParagraph && !shouldHandleMailBlockquote)
     942        || startBlock == currentRoot || isListItem(startBlock) || selectionIsPlainText)
    942943        m_preventNesting = false;
    943944   
     
    949950        // Merge blocks if the start of the selection was in a Mail blockquote, since we handle 
    950951        // that case specially to prevent nesting.
    951         bool mergeBlocksAfterDelete = startIsInsideMailBlockquote || isEndOfParagraph(visibleEnd) || isStartOfBlock(visibleStart);
     952        bool mergeBlocksAfterDelete = shouldHandleMailBlockquote || isEndOfParagraph(visibleEnd) || isStartOfBlock(visibleStart);
    952953        // FIXME: We should only expand to include fully selected special elements if we are copying a
    953954        // selection and pasting it on top of itself.
     
    978979        // not <div>xbar<div>bar</div><div>bazx</div></div>.
    979980        // Don't do this if the selection started in a Mail blockquote.
    980         if (m_preventNesting && !startIsInsideMailBlockquote && !isEndOfParagraph(visibleStart) && !isStartOfParagraph(visibleStart)) {
     981        if (m_preventNesting && !shouldHandleMailBlockquote && !isEndOfParagraph(visibleStart) && !isStartOfParagraph(visibleStart)) {
    981982            insertParagraphSeparator();
    982983            setEndingSelection(endingSelection().visibleStart().previous());
     
    988989    // out of any surrounding Mail blockquotes. Unless we're inserting in a table, in which case
    989990    // breaking the blockquote will prevent the content from actually being inserted in the table.
    990     if (startIsInsideMailBlockquote && m_preventNesting && !(enclosingNodeOfType(insertionPos, &isTableStructureNode))) {
     991    if (shouldHandleMailBlockquote && m_preventNesting && !(enclosingNodeOfType(insertionPos, &isTableStructureNode))) {
    991992        applyCommandToComposite(BreakBlockquoteCommand::create(document()));
    992993        // This will leave a br between the split.
     
    10171018    // Adjust insertionPos to prevent nesting.
    10181019    // If the start was in a Mail blockquote, we will have already handled adjusting insertionPos above.
    1019     if (m_preventNesting && insertionBlock && !isTableCell(insertionBlock.get()) && !startIsInsideMailBlockquote) {
     1020    if (m_preventNesting && insertionBlock && !isTableCell(insertionBlock.get()) && !shouldHandleMailBlockquote) {
    10201021        ASSERT(insertionBlock != currentRoot);
    10211022        VisiblePosition visibleInsertionPos(insertionPos);
     
    11631164    m_shouldMergeEnd = shouldMergeEnd(selectionEndWasEndOfParagraph);
    11641165   
    1165     if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasInterchangeNewlineAtStart(), startIsInsideMailBlockquote)) {
     1166    if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasInterchangeNewlineAtStart(), shouldHandleMailBlockquote)) {
    11661167        VisiblePosition startOfParagraphToMove = positionAtStartOfInsertedContent();
    11671168        VisiblePosition destination = startOfParagraphToMove.previous();
     
    12121213                    // Use a default paragraph element (a plain div) for the empty paragraph, using the last paragraph
    12131214                    // block's style seems to annoy users.
    1214                     insertParagraphSeparator(true, !startIsInsideMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(),
     1215                    insertParagraphSeparator(true, !shouldHandleMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(),
    12151216                        isMailBlockquote, CannotCrossEditingBoundary, insertedNodes.firstNodeInserted()->parentNode()));
    12161217                }
  • trunk/Source/WebCore/editing/ReplaceSelectionCommand.h

    r165676 r168650  
    4343        PreventNesting = 1 << 3,
    4444        MovingParagraph = 1 << 4,
    45         SanitizeFragment = 1 << 5
     45        SanitizeFragment = 1 << 5,
     46        IgnoreMailBlockquote = 1 << 6,
    4647    };
    4748
     
    116117    bool m_sanitizeFragment;
    117118    bool m_shouldMergeEnd;
     119    bool m_ignoreMailBlockquote;
    118120};
    119121
  • trunk/Source/WebCore/editing/efl/EditorEfl.cpp

    r165676 r168650  
    4343}
    4444
    45 void Editor::pasteWithPasteboard(Pasteboard*, bool)
     45void Editor::pasteWithPasteboard(Pasteboard*, bool, MailBlockquoteHandling)
    4646{
    4747    notImplemented();
  • trunk/Source/WebCore/editing/ios/EditorIOS.mm

    r168579 r168650  
    552552}
    553553
    554 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
     554void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
    555555{
    556556    RefPtr<Range> range = selectedRange();
     
    562562
    563563    if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
    564         pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false);
     564        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false, mailBlockquoteHandling);
    565565}
    566566
  • trunk/Source/WebCore/editing/mac/EditorMac.mm

    r168579 r168650  
    8383}
    8484
    85 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
     85void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
    8686{
    8787    RefPtr<Range> range = selectedRange();
     
    9494
    9595    if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
    96         pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false);
     96        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false, mailBlockquoteHandling);
    9797
    9898    client()->setInsertionPasteboard(String());
     
    258258}
    259259
    260 void Editor::readSelectionFromPasteboard(const String& pasteboardName)
     260void Editor::readSelectionFromPasteboard(const String& pasteboardName, MailBlockquoteHandling mailBlockquoteHandling)
    261261{
    262262    Pasteboard pasteboard(pasteboardName);
    263263    if (m_frame.selection().selection().isContentRichlyEditable())
    264         pasteWithPasteboard(&pasteboard, true);
     264        pasteWithPasteboard(&pasteboard, true, mailBlockquoteHandling);
    265265    else
    266266        pasteAsPlainTextWithPasteboard(pasteboard);
    267267}
    268268
     269static void maybeCopyNodeAttributesToFragment(Node* node, DocumentFragment* fragment)
     270{
     271    // This is only supported for single-Node fragments.
     272    Node* firstChild = fragment->firstChild();
     273    if (firstChild != fragment->lastChild())
     274        return;
     275
     276    // And only supported for HTML elements.
     277    if (!node->isHTMLElement() || !firstChild->isHTMLElement())
     278        return;
     279
     280    // And only if the source Element and destination Element have the same HTML tag name.
     281    const Element& oldElement = toHTMLElement(*node);
     282    Element& newElement = toHTMLElement(*firstChild);
     283    if (!oldElement.hasTagName(newElement.tagQName()))
     284        return;
     285
     286    for (const Attribute& attribute : oldElement.attributesIterator()) {
     287        if (newElement.hasAttribute(attribute.name()))
     288            continue;
     289        newElement.setAttribute(attribute.name(), attribute.value());
     290    }
     291}
     292
    269293void Editor::replaceNodeFromPasteboard(Node* node, const String& pasteboardName)
    270294{
     
    277301    m_frame.selection().setSelection(VisibleSelection(range.get()), FrameSelection::DoNotSetFocus);
    278302
    279     readSelectionFromPasteboard(pasteboardName);
     303    Pasteboard pasteboard(pasteboardName);
     304
     305    if (!m_frame.selection().selection().isContentRichlyEditable()) {
     306        pasteAsPlainTextWithPasteboard(pasteboard);
     307        return;
     308    }
     309
     310    // FIXME: How can this hard-coded pasteboard name be right, given that the passed-in pasteboard has a name?
     311    client()->setInsertionPasteboard(NSGeneralPboard);
     312
     313    bool chosePlainText;
     314    RefPtr<DocumentFragment> fragment = webContentFromPasteboard(pasteboard, *range, true, chosePlainText);
     315
     316    maybeCopyNodeAttributesToFragment(node, fragment.get());
     317
     318    if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
     319        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false, MailBlockquoteHandling::IgnoreBlockquote);
     320
     321    client()->setInsertionPasteboard(String());
    280322}
    281323
Note: See TracChangeset for help on using the changeset viewer.