Diff
Modified: branches/safari-538.34-branch/Source/WebCore/ChangeLog (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/ChangeLog 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/ChangeLog 2014-05-12 23:01:49 UTC (rev 168652)
@@ -1,5 +1,61 @@
2014-04-17 Lucas Forschler <lforsch...@apple.com>
+ Merge r168650
+
+ 2014-05-12 Brady Eidson <beid...@apple.com>
+
+ 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:
+
+2014-04-17 Lucas Forschler <lforsch...@apple.com>
+
Merge r168565
2014-05-09 Joseph Pecoraro <pecor...@apple.com>
Modified: branches/safari-538.34-branch/Source/WebCore/WebCore.exp.in (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/WebCore.exp.in 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/WebCore.exp.in 2014-05-12 23:01:49 UTC (rev 168652)
@@ -1144,7 +1144,7 @@
__ZN7WebCore6Editor13rangeForPointERKNS_8IntPointE
__ZN7WebCore6Editor14setCompositionERKN3WTF6StringERKNS1_6VectorINS_20CompositionUnderlineELm0ENS1_15CrashOnOverflowEEEjj
__ZN7WebCore6Editor14simplifyMarkupEPNS_4NodeES2_
-__ZN7WebCore6Editor15pasteAsFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbb
+__ZN7WebCore6Editor15pasteAsFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbNS_22MailBlockquoteHandlingE
__ZN7WebCore6Editor16pasteAsPlainTextEv
__ZN7WebCore6Editor17cancelCompositionEv
__ZN7WebCore6Editor17insertOrderedListEv
@@ -1164,7 +1164,7 @@
__ZN7WebCore6Editor26increaseSelectionListLevelEv
__ZN7WebCore6Editor26toggleOverwriteModeEnabledEv
__ZN7WebCore6Editor26writeSelectionToPasteboardERNS_10PasteboardE
-__ZN7WebCore6Editor28replaceSelectionWithFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbb
+__ZN7WebCore6Editor28replaceSelectionWithFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbbNS_22MailBlockquoteHandlingE
__ZN7WebCore6Editor28updateEditorUINowIfScheduledEv
__ZN7WebCore6Editor29canDecreaseSelectionListLevelEv
__ZN7WebCore6Editor29canIncreaseSelectionListLevelEv
@@ -2249,7 +2249,7 @@
__ZN7WebCore6Editor24advanceToNextMisspellingEb
__ZN7WebCore6Editor25replaceNodeFromPasteboardEPNS_4NodeERKN3WTF6StringE
__ZN7WebCore6Editor26dataSelectionForPasteboardERKN3WTF6StringE
-__ZN7WebCore6Editor27readSelectionFromPasteboardERKN3WTF6StringE
+__ZN7WebCore6Editor27readSelectionFromPasteboardERKN3WTF6StringENS_22MailBlockquoteHandlingE
__ZN7WebCore6Editor28stringSelectionForPasteboardEv
__ZN7WebCore6Editor28toggleAutomaticLinkDetectionEv
__ZN7WebCore6Editor30toggleAutomaticTextReplacementEv
Modified: branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.cpp (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.cpp 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.cpp 2014-05-12 23:01:49 UTC (rev 168652)
@@ -28,6 +28,7 @@
#include "TextEvent.h"
#include "DocumentFragment.h"
+#include "Editor.h"
namespace WebCore {
@@ -43,12 +44,12 @@
PassRefPtr<TextEvent> TextEvent::createForPlainTextPaste(PassRefPtr<AbstractView> view, const String& data, bool shouldSmartReplace)
{
- return adoptRef(new TextEvent(view, data, 0, shouldSmartReplace, false));
+ return adoptRef(new TextEvent(view, data, 0, shouldSmartReplace, false, MailBlockquoteHandling::RespectBlockquote));
}
-PassRefPtr<TextEvent> TextEvent::createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle)
+PassRefPtr<TextEvent> TextEvent::createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling mailBlockquoteHandling)
{
- return adoptRef(new TextEvent(view, "", data, shouldSmartReplace, shouldMatchStyle));
+ return adoptRef(new TextEvent(view, "", data, shouldSmartReplace, shouldMatchStyle, mailBlockquoteHandling));
}
PassRefPtr<TextEvent> TextEvent::createForDrop(PassRefPtr<AbstractView> view, const String& data)
@@ -65,6 +66,7 @@
: m_inputType(TextEventInputKeyboard)
, m_shouldSmartReplace(false)
, m_shouldMatchStyle(false)
+ , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
{
}
@@ -75,17 +77,18 @@
, m_pastingFragment(0)
, m_shouldSmartReplace(false)
, m_shouldMatchStyle(false)
+ , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
{
}
-TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, PassRefPtr<DocumentFragment> pastingFragment,
- bool shouldSmartReplace, bool shouldMatchStyle)
+TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, PassRefPtr<DocumentFragment> pastingFragment, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling mailBlockquoteHandling)
: UIEvent(eventNames().textInputEvent, true, true, view, 0)
, m_inputType(TextEventInputPaste)
, m_data(data)
, m_pastingFragment(pastingFragment)
, m_shouldSmartReplace(shouldSmartReplace)
, m_shouldMatchStyle(shouldMatchStyle)
+ , m_mailBlockquoteHandling(mailBlockquoteHandling)
{
}
@@ -95,6 +98,7 @@
, m_data(data)
, m_shouldSmartReplace(false)
, m_shouldMatchStyle(false)
+ , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
, m_dictationAlternatives(dictationAlternatives)
{
}
Modified: branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.h (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.h 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.h 2014-05-12 23:01:49 UTC (rev 168652)
@@ -35,14 +35,16 @@
class DocumentFragment;
+ enum class MailBlockquoteHandling;
+
class TextEvent : public UIEvent {
public:
static PassRefPtr<TextEvent> create();
static PassRefPtr<TextEvent> create(PassRefPtr<AbstractView>, const String& data, TextEventInputType = TextEventInputKeyboard);
- static PassRefPtr<TextEvent> createForPlainTextPaste(PassRefPtr<AbstractView> view, const String& data, bool shouldSmartReplace);
- static PassRefPtr<TextEvent> createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle);
- static PassRefPtr<TextEvent> createForDrop(PassRefPtr<AbstractView> view, const String& data);
+ static PassRefPtr<TextEvent> createForPlainTextPaste(PassRefPtr<AbstractView>, const String& data, bool shouldSmartReplace);
+ static PassRefPtr<TextEvent> createForFragmentPaste(PassRefPtr<AbstractView>, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling);
+ static PassRefPtr<TextEvent> createForDrop(PassRefPtr<AbstractView>, const String& data);
static PassRefPtr<TextEvent> createForDictation(PassRefPtr<AbstractView>, const String& data, const Vector<DictationAlternative>& dictationAlternatives);
virtual ~TextEvent();
@@ -62,6 +64,7 @@
bool shouldSmartReplace() const { return m_shouldSmartReplace; }
bool shouldMatchStyle() const { return m_shouldMatchStyle; }
+ MailBlockquoteHandling mailBlockquoteHandling() const { return m_mailBlockquoteHandling; }
DocumentFragment* pastingFragment() const { return m_pastingFragment.get(); }
const Vector<DictationAlternative>& dictationAlternatives() const { return m_dictationAlternatives; }
@@ -69,8 +72,7 @@
TextEvent();
TextEvent(PassRefPtr<AbstractView>, const String& data, TextEventInputType = TextEventInputKeyboard);
- TextEvent(PassRefPtr<AbstractView>, const String& data, PassRefPtr<DocumentFragment>,
- bool shouldSmartReplace, bool shouldMatchStyle);
+ TextEvent(PassRefPtr<AbstractView>, const String& data, PassRefPtr<DocumentFragment>, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling);
TextEvent(PassRefPtr<AbstractView>, const String& data, const Vector<DictationAlternative>& dictationAlternatives);
virtual bool isTextEvent() const override;
@@ -81,6 +83,7 @@
RefPtr<DocumentFragment> m_pastingFragment;
bool m_shouldSmartReplace;
bool m_shouldMatchStyle;
+ MailBlockquoteHandling m_mailBlockquoteHandling;
Vector<DictationAlternative> m_dictationAlternatives;
};
Modified: branches/safari-538.34-branch/Source/WebCore/editing/Editor.cpp (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/editing/Editor.cpp 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/Editor.cpp 2014-05-12 23:01:49 UTC (rev 168652)
@@ -266,7 +266,7 @@
if (client()->performsTwoStepPaste(event->pastingFragment()))
return true;
#endif
- replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle());
+ replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle(), event->mailBlockquoteHandling());
#if PLATFORM(IOS)
}
#endif
@@ -528,12 +528,12 @@
target->dispatchEvent(TextEvent::createForPlainTextPaste(document().domWindow(), pastingText, smartReplace), IGNORE_EXCEPTION);
}
-void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle)
+void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle, MailBlockquoteHandling respectsMailBlockquote)
{
Node* target = findEventTargetFromSelection();
if (!target)
return;
- target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), pastingFragment, smartReplace, matchStyle), IGNORE_EXCEPTION);
+ target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), pastingFragment, smartReplace, matchStyle, respectsMailBlockquote), IGNORE_EXCEPTION);
}
void Editor::pasteAsPlainTextBypassingDHTML()
@@ -565,7 +565,7 @@
#endif
#if !PLATFORM(COCOA) && !PLATFORM(EFL)
-void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
+void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
{
RefPtr<Range> range = selectedRange();
if (!range)
@@ -574,7 +574,7 @@
bool chosePlainText;
RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, *range, allowPlainText, chosePlainText);
if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
- pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText);
+ pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, mailBlockquoteHandling);
}
#endif
@@ -597,7 +597,7 @@
return client()->shouldInsertNode(fragment.get(), replacingDOMRange.get(), givenAction);
}
-void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle)
+void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle, MailBlockquoteHandling mailBlockquoteHandling)
{
VisibleSelection selection = m_frame.selection().selection();
if (selection.isNone() || !selection.isContentEditable() || !fragment)
@@ -610,6 +610,9 @@
options |= ReplaceSelectionCommand::SmartReplace;
if (matchStyle)
options |= ReplaceSelectionCommand::MatchStyle;
+ if (mailBlockquoteHandling == MailBlockquoteHandling::IgnoreBlockquote)
+ options |= ReplaceSelectionCommand::IgnoreMailBlockquote;
+
applyCommand(ReplaceSelectionCommand::create(document(), fragment, options, EditActionPaste));
revealSelectionAfterEditingOperation();
Modified: branches/safari-538.34-branch/Source/WebCore/editing/Editor.h (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/editing/Editor.h 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/Editor.h 2014-05-12 23:01:49 UTC (rev 168652)
@@ -90,6 +90,11 @@
enum EditorCommandSource { CommandFromMenuOrKeyBinding, CommandFromDOM, CommandFromDOMWithUserInterface };
enum EditorParagraphSeparator { EditorParagraphSeparatorIsDiv, EditorParagraphSeparatorIsP };
+enum class MailBlockquoteHandling {
+ RespectBlockquote,
+ IgnoreBlockquote,
+};
+
class Editor {
public:
explicit Editor(Frame&);
@@ -335,7 +340,7 @@
void handleAlternativeTextUIResult(const String& correction);
void dismissCorrectionPanelAsIgnored();
- void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle);
+ void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
void pasteAsPlainText(const String&, bool smartReplace);
// This is only called on the mac where paste is implemented primarily at the WebKit level.
@@ -377,7 +382,7 @@
void textDidChangeInTextArea(Element*);
WritingDirection baseWritingDirectionForSelectionStart() const;
- void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle);
+ void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
void replaceSelectionWithText(const String&, bool selectReplacement, bool smartReplace);
bool selectionStartHasMarkerFor(DocumentMarker::MarkerType, int from, int length) const;
void updateMarkersForWordsAffectedByEditing(bool onlyHandleWordsContainingSelection);
@@ -431,7 +436,7 @@
#if !PLATFORM(IOS)
bool canCopyExcludingStandaloneImages();
void takeFindStringFromSelection();
- void readSelectionFromPasteboard(const String& pasteboardName);
+ void readSelectionFromPasteboard(const String& pasteboardName, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
void replaceNodeFromPasteboard(Node*, const String& pasteboardName);
PassRefPtr<SharedBuffer> dataSelectionForPasteboard(const String& pasteboardName);
#endif // !PLATFORM(IOS)
@@ -450,7 +455,7 @@
bool canDeleteRange(Range*) const;
bool canSmartReplaceWithPasteboard(Pasteboard&);
void pasteAsPlainTextWithPasteboard(Pasteboard&);
- void pasteWithPasteboard(Pasteboard*, bool allowPlainText);
+ void pasteWithPasteboard(Pasteboard*, bool allowPlainText, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
String plainTextFromPasteboard(const PasteboardPlainText&);
void revealSelectionAfterEditingOperation(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);
Modified: branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.cpp (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.cpp 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.cpp 2014-05-12 23:01:49 UTC (rev 168652)
@@ -378,6 +378,7 @@
, m_editAction(editAction)
, m_sanitizeFragment(options & SanitizeFragment)
, m_shouldMergeEnd(false)
+ , m_ignoreMailBlockquote(options & IgnoreMailBlockquote)
{
}
@@ -933,12 +934,12 @@
Node* startBlock = enclosingBlock(visibleStart.deepEquivalent().deprecatedNode());
Position insertionPos = selection.start();
- bool startIsInsideMailBlockquote = enclosingNodeOfType(insertionPos, isMailBlockquote, CanCrossEditingBoundary);
+ bool shouldHandleMailBlockquote = enclosingNodeOfType(insertionPos, isMailBlockquote, CanCrossEditingBoundary) && !m_ignoreMailBlockquote;
bool selectionIsPlainText = !selection.isContentRichlyEditable();
Element* currentRoot = selection.rootEditableElement();
- if ((selectionStartWasStartOfParagraph && selectionEndWasEndOfParagraph && !startIsInsideMailBlockquote) ||
- startBlock == currentRoot || isListItem(startBlock) || selectionIsPlainText)
+ if ((selectionStartWasStartOfParagraph && selectionEndWasEndOfParagraph && !shouldHandleMailBlockquote)
+ || startBlock == currentRoot || isListItem(startBlock) || selectionIsPlainText)
m_preventNesting = false;
if (selection.isRange()) {
@@ -948,7 +949,7 @@
// will leave hanging block(s).
// Merge blocks if the start of the selection was in a Mail blockquote, since we handle
// that case specially to prevent nesting.
- bool mergeBlocksAfterDelete = startIsInsideMailBlockquote || isEndOfParagraph(visibleEnd) || isStartOfBlock(visibleStart);
+ bool mergeBlocksAfterDelete = shouldHandleMailBlockquote || isEndOfParagraph(visibleEnd) || isStartOfBlock(visibleStart);
// FIXME: We should only expand to include fully selected special elements if we are copying a
// selection and pasting it on top of itself.
deleteSelection(false, mergeBlocksAfterDelete, true, false);
@@ -977,7 +978,7 @@
// As long as the div styles are the same, visually you'd expect: <div>xbar</div><div>bar</div><div>bazx</div>,
// not <div>xbar<div>bar</div><div>bazx</div></div>.
// Don't do this if the selection started in a Mail blockquote.
- if (m_preventNesting && !startIsInsideMailBlockquote && !isEndOfParagraph(visibleStart) && !isStartOfParagraph(visibleStart)) {
+ if (m_preventNesting && !shouldHandleMailBlockquote && !isEndOfParagraph(visibleStart) && !isStartOfParagraph(visibleStart)) {
insertParagraphSeparator();
setEndingSelection(endingSelection().visibleStart().previous());
}
@@ -987,7 +988,7 @@
// We don't want any of the pasted content to end up nested in a Mail blockquote, so first break
// out of any surrounding Mail blockquotes. Unless we're inserting in a table, in which case
// breaking the blockquote will prevent the content from actually being inserted in the table.
- if (startIsInsideMailBlockquote && m_preventNesting && !(enclosingNodeOfType(insertionPos, &isTableStructureNode))) {
+ if (shouldHandleMailBlockquote && m_preventNesting && !(enclosingNodeOfType(insertionPos, &isTableStructureNode))) {
applyCommandToComposite(BreakBlockquoteCommand::create(document()));
// This will leave a br between the split.
Node* br = endingSelection().start().deprecatedNode();
@@ -1016,7 +1017,7 @@
// Adjust insertionPos to prevent nesting.
// If the start was in a Mail blockquote, we will have already handled adjusting insertionPos above.
- if (m_preventNesting && insertionBlock && !isTableCell(insertionBlock.get()) && !startIsInsideMailBlockquote) {
+ if (m_preventNesting && insertionBlock && !isTableCell(insertionBlock.get()) && !shouldHandleMailBlockquote) {
ASSERT(insertionBlock != currentRoot);
VisiblePosition visibleInsertionPos(insertionPos);
if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInsertionPos) && fragment.hasInterchangeNewlineAtEnd()))
@@ -1162,7 +1163,7 @@
// the start merge so that the start merge doesn't effect our decision.
m_shouldMergeEnd = shouldMergeEnd(selectionEndWasEndOfParagraph);
- if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasInterchangeNewlineAtStart(), startIsInsideMailBlockquote)) {
+ if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasInterchangeNewlineAtStart(), shouldHandleMailBlockquote)) {
VisiblePosition startOfParagraphToMove = positionAtStartOfInsertedContent();
VisiblePosition destination = startOfParagraphToMove.previous();
// We need to handle the case where we need to merge the end
@@ -1211,7 +1212,7 @@
} else {
// Use a default paragraph element (a plain div) for the empty paragraph, using the last paragraph
// block's style seems to annoy users.
- insertParagraphSeparator(true, !startIsInsideMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(),
+ insertParagraphSeparator(true, !shouldHandleMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(),
isMailBlockquote, CannotCrossEditingBoundary, insertedNodes.firstNodeInserted()->parentNode()));
}
Modified: branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.h (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.h 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.h 2014-05-12 23:01:49 UTC (rev 168652)
@@ -42,7 +42,8 @@
MatchStyle = 1 << 2,
PreventNesting = 1 << 3,
MovingParagraph = 1 << 4,
- SanitizeFragment = 1 << 5
+ SanitizeFragment = 1 << 5,
+ IgnoreMailBlockquote = 1 << 6,
};
typedef unsigned CommandOptions;
@@ -115,6 +116,7 @@
EditAction m_editAction;
bool m_sanitizeFragment;
bool m_shouldMergeEnd;
+ bool m_ignoreMailBlockquote;
};
} // namespace WebCore
Modified: branches/safari-538.34-branch/Source/WebCore/editing/efl/EditorEfl.cpp (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/editing/efl/EditorEfl.cpp 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/efl/EditorEfl.cpp 2014-05-12 23:01:49 UTC (rev 168652)
@@ -42,7 +42,7 @@
notImplemented();
}
-void Editor::pasteWithPasteboard(Pasteboard*, bool)
+void Editor::pasteWithPasteboard(Pasteboard*, bool, MailBlockquoteHandling)
{
notImplemented();
}
Modified: branches/safari-538.34-branch/Source/WebCore/editing/ios/EditorIOS.mm (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/editing/ios/EditorIOS.mm 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/ios/EditorIOS.mm 2014-05-12 23:01:49 UTC (rev 168652)
@@ -536,7 +536,7 @@
return reader.fragment.release();
}
-void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
+void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
{
RefPtr<Range> range = selectedRange();
@@ -546,7 +546,7 @@
fragment = webContentFromPasteboard(*pasteboard, *range, allowPlainText, chosePlainText);
if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
- pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false);
+ pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false, mailBlockquoteHandling);
}
PassRefPtr<DocumentFragment> Editor::createFragmentAndAddResources(NSAttributedString *string)
Modified: branches/safari-538.34-branch/Source/WebCore/editing/mac/EditorMac.mm (168651 => 168652)
--- branches/safari-538.34-branch/Source/WebCore/editing/mac/EditorMac.mm 2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/mac/EditorMac.mm 2014-05-12 23:01:49 UTC (rev 168652)
@@ -81,7 +81,7 @@
[[NSApplication sharedApplication] orderFrontColorPanel:nil];
}
-void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
+void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
{
RefPtr<Range> range = selectedRange();
@@ -92,7 +92,7 @@
RefPtr<DocumentFragment> fragment = webContentFromPasteboard(*pasteboard, *range, allowPlainText, chosePlainText);
if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
- pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false);
+ pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false, mailBlockquoteHandling);
client()->setInsertionPasteboard(String());
}
@@ -256,15 +256,39 @@
platformStrategies()->pasteboardStrategy()->setStringForType(m_frame.displayStringModifiedByEncoding(selectedTextForDataTransfer()), NSStringPboardType, NSFindPboard);
}
-void Editor::readSelectionFromPasteboard(const String& pasteboardName)
+void Editor::readSelectionFromPasteboard(const String& pasteboardName, MailBlockquoteHandling mailBlockquoteHandling)
{
Pasteboard pasteboard(pasteboardName);
if (m_frame.selection().selection().isContentRichlyEditable())
- pasteWithPasteboard(&pasteboard, true);
+ pasteWithPasteboard(&pasteboard, true, mailBlockquoteHandling);
else
pasteAsPlainTextWithPasteboard(pasteboard);
}
+static void maybeCopyNodeAttributesToFragment(Node* node, DocumentFragment* fragment)
+{
+ // This is only supported for single-Node fragments.
+ Node* firstChild = fragment->firstChild();
+ if (firstChild != fragment->lastChild())
+ return;
+
+ // And only supported for HTML elements.
+ if (!node->isHTMLElement() || !firstChild->isHTMLElement())
+ return;
+
+ // And only if the source Element and destination Element have the same HTML tag name.
+ const Element& oldElement = toHTMLElement(*node);
+ Element& newElement = toHTMLElement(*firstChild);
+ if (!oldElement.hasTagName(newElement.tagQName()))
+ return;
+
+ for (const Attribute& attribute : oldElement.attributesIterator()) {
+ if (newElement.hasAttribute(attribute.name()))
+ continue;
+ newElement.setAttribute(attribute.name(), attribute.value());
+ }
+}
+
void Editor::replaceNodeFromPasteboard(Node* node, const String& pasteboardName)
{
ASSERT(node);
@@ -275,7 +299,25 @@
RefPtr<Range> range = Range::create(node->document(), Position(node, Position::PositionIsBeforeAnchor), Position(node, Position::PositionIsAfterAnchor));
m_frame.selection().setSelection(VisibleSelection(range.get()), FrameSelection::DoNotSetFocus);
- readSelectionFromPasteboard(pasteboardName);
+ Pasteboard pasteboard(pasteboardName);
+
+ if (!m_frame.selection().selection().isContentRichlyEditable()) {
+ pasteAsPlainTextWithPasteboard(pasteboard);
+ return;
+ }
+
+ // FIXME: How can this hard-coded pasteboard name be right, given that the passed-in pasteboard has a name?
+ client()->setInsertionPasteboard(NSGeneralPboard);
+
+ bool chosePlainText;
+ RefPtr<DocumentFragment> fragment = webContentFromPasteboard(pasteboard, *range, true, chosePlainText);
+
+ maybeCopyNodeAttributesToFragment(node, fragment.get());
+
+ if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
+ pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false, MailBlockquoteHandling::IgnoreBlockquote);
+
+ client()->setInsertionPasteboard(String());
}
// FIXME: Makes no sense that selectedTextForDataTransfer always includes alt text, but stringSelectionForPasteboard does not.