OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. |
3 * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved. | 3 * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 Element* enclosingBlockElement = enclosingBlock(pos.computeContainerNode()); | 132 Element* enclosingBlockElement = enclosingBlock(pos.computeContainerNode()); |
133 for (Position nextPosition = pos; nextPosition.computeContainerNode() != enc
losingBlockElement; pos = nextPosition) { | 133 for (Position nextPosition = pos; nextPosition.computeContainerNode() != enc
losingBlockElement; pos = nextPosition) { |
134 if (lineBreakExistsAtPosition(pos)) | 134 if (lineBreakExistsAtPosition(pos)) |
135 break; | 135 break; |
136 | 136 |
137 if (pos.computeContainerNode()->nonShadowBoundaryParentNode()) | 137 if (pos.computeContainerNode()->nonShadowBoundaryParentNode()) |
138 nextPosition = positionInParentAfterNode(*pos.computeContainerNode()
); | 138 nextPosition = positionInParentAfterNode(*pos.computeContainerNode()
); |
139 | 139 |
140 if (nextPosition == pos | 140 if (nextPosition == pos |
141 || enclosingBlock(nextPosition.computeContainerNode()) != enclosingB
lockElement | 141 || enclosingBlock(nextPosition.computeContainerNode()) != enclosingB
lockElement |
142 || VisiblePosition(pos).deepEquivalent() != VisiblePosition(nextPosi
tion).deepEquivalent()) | 142 || createVisiblePosition(pos).deepEquivalent() != createVisiblePosit
ion(nextPosition).deepEquivalent()) |
143 break; | 143 break; |
144 } | 144 } |
145 return pos; | 145 return pos; |
146 } | 146 } |
147 | 147 |
148 ReplacementFragment::ReplacementFragment(Document* document, DocumentFragment* f
ragment, const VisibleSelection& selection) | 148 ReplacementFragment::ReplacementFragment(Document* document, DocumentFragment* f
ragment, const VisibleSelection& selection) |
149 : m_document(document) | 149 : m_document(document) |
150 , m_fragment(fragment) | 150 , m_fragment(fragment) |
151 , m_hasInterchangeNewlineAtStart(false) | 151 , m_hasInterchangeNewlineAtStart(false) |
152 , m_hasInterchangeNewlineAtEnd(false) | 152 , m_hasInterchangeNewlineAtEnd(false) |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 Position inserted = endOfInsertedContent.deepEquivalent(); | 392 Position inserted = endOfInsertedContent.deepEquivalent(); |
393 bool isInsideMailBlockquote = enclosingNodeOfType(inserted, isMailHTMLBlockq
uoteElement, CanCrossEditingBoundary); | 393 bool isInsideMailBlockquote = enclosingNodeOfType(inserted, isMailHTMLBlockq
uoteElement, CanCrossEditingBoundary); |
394 return isInsideMailBlockquote && (numEnclosingMailBlockquotes(existing) == n
umEnclosingMailBlockquotes(inserted)); | 394 return isInsideMailBlockquote && (numEnclosingMailBlockquotes(existing) == n
umEnclosingMailBlockquotes(inserted)); |
395 } | 395 } |
396 | 396 |
397 bool ReplaceSelectionCommand::shouldMergeStart(bool selectionStartWasStartOfPara
graph, bool fragmentHasInterchangeNewlineAtStart, bool selectionStartWasInsideMa
ilBlockquote) | 397 bool ReplaceSelectionCommand::shouldMergeStart(bool selectionStartWasStartOfPara
graph, bool fragmentHasInterchangeNewlineAtStart, bool selectionStartWasInsideMa
ilBlockquote) |
398 { | 398 { |
399 if (m_movingParagraph) | 399 if (m_movingParagraph) |
400 return false; | 400 return false; |
401 | 401 |
402 VisiblePosition startOfInsertedContent(positionAtStartOfInsertedContent()); | 402 VisiblePosition startOfInsertedContent = positionAtStartOfInsertedContent(); |
403 VisiblePosition prev = previousPositionOf(startOfInsertedContent, CannotCros
sEditingBoundary); | 403 VisiblePosition prev = previousPositionOf(startOfInsertedContent, CannotCros
sEditingBoundary); |
404 if (prev.isNull()) | 404 if (prev.isNull()) |
405 return false; | 405 return false; |
406 | 406 |
407 // When we have matching quote levels, its ok to merge more frequently. | 407 // When we have matching quote levels, its ok to merge more frequently. |
408 // For a successful merge, we still need to make sure that the inserted cont
ent starts with the beginning of a paragraph. | 408 // For a successful merge, we still need to make sure that the inserted cont
ent starts with the beginning of a paragraph. |
409 // And we should only merge here if the selection start was inside a mail bl
ockquote. This prevents against removing a | 409 // And we should only merge here if the selection start was inside a mail bl
ockquote. This prevents against removing a |
410 // blockquote from newly pasted quoted content that was pasted into an unquo
ted position. If that unquoted position happens | 410 // blockquote from newly pasted quoted content that was pasted into an unquo
ted position. If that unquoted position happens |
411 // to be right after another blockquote, we don't want to merge and risk str
ipping a valid block (and newline) from the pasted content. | 411 // to be right after another blockquote, we don't want to merge and risk str
ipping a valid block (and newline) from the pasted content. |
412 if (isStartOfParagraph(startOfInsertedContent) && selectionStartWasInsideMai
lBlockquote && hasMatchingQuoteLevel(prev, positionAtEndOfInsertedContent())) | 412 if (isStartOfParagraph(startOfInsertedContent) && selectionStartWasInsideMai
lBlockquote && hasMatchingQuoteLevel(prev, positionAtEndOfInsertedContent())) |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 removeNodePreservingChildren(element); | 536 removeNodePreservingChildren(element); |
537 continue; | 537 continue; |
538 } | 538 } |
539 removeElementAttribute(element, styleAttr); | 539 removeElementAttribute(element, styleAttr); |
540 } else if (newInlineStyle->style()->propertyCount() != inlineStyle->prop
ertyCount()) { | 540 } else if (newInlineStyle->style()->propertyCount() != inlineStyle->prop
ertyCount()) { |
541 setNodeAttribute(element, styleAttr, AtomicString(newInlineStyle->st
yle()->asText())); | 541 setNodeAttribute(element, styleAttr, AtomicString(newInlineStyle->st
yle()->asText())); |
542 } | 542 } |
543 | 543 |
544 // FIXME: Tolerate differences in id, class, and style attributes. | 544 // FIXME: Tolerate differences in id, class, and style attributes. |
545 if (element->parentNode() && isNonTableCellHTMLBlockElement(element) &&
areIdenticalElements(element, element->parentNode()) | 545 if (element->parentNode() && isNonTableCellHTMLBlockElement(element) &&
areIdenticalElements(element, element->parentNode()) |
546 && VisiblePosition(firstPositionInNode(element->parentNode())).deepE
quivalent() == VisiblePosition(firstPositionInNode(element)).deepEquivalent() | 546 && createVisiblePosition(firstPositionInNode(element->parentNode()))
.deepEquivalent() == createVisiblePosition(firstPositionInNode(element)).deepEqu
ivalent() |
547 && VisiblePosition(lastPositionInNode(element->parentNode())).deepEq
uivalent() == VisiblePosition(lastPositionInNode(element)).deepEquivalent()) { | 547 && createVisiblePosition(lastPositionInNode(element->parentNode())).
deepEquivalent() == createVisiblePosition(lastPositionInNode(element)).deepEquiv
alent()) { |
548 insertedNodes.willRemoveNodePreservingChildren(*element); | 548 insertedNodes.willRemoveNodePreservingChildren(*element); |
549 removeNodePreservingChildren(element); | 549 removeNodePreservingChildren(element); |
550 continue; | 550 continue; |
551 } | 551 } |
552 | 552 |
553 if (element->parentNode() && element->parentNode()->layoutObjectIsRichly
Editable()) | 553 if (element->parentNode() && element->parentNode()->layoutObjectIsRichly
Editable()) |
554 removeElementAttribute(element, contenteditableAttr); | 554 removeElementAttribute(element, contenteditableAttr); |
555 | 555 |
556 // WebKit used to not add display: inline and float: none on copy. | 556 // WebKit used to not add display: inline and float: none on copy. |
557 // Keep this code around for backward compatibility | 557 // Keep this code around for backward compatibility |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 } | 658 } |
659 | 659 |
660 void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<El
ement> prpElement, PassRefPtrWillBeRawPtr<ContainerNode> prpAncestor) | 660 void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<El
ement> prpElement, PassRefPtrWillBeRawPtr<ContainerNode> prpAncestor) |
661 { | 661 { |
662 RefPtrWillBeRawPtr<Element> element = prpElement; | 662 RefPtrWillBeRawPtr<Element> element = prpElement; |
663 RefPtrWillBeRawPtr<ContainerNode> ancestor = prpAncestor; | 663 RefPtrWillBeRawPtr<ContainerNode> ancestor = prpAncestor; |
664 | 664 |
665 if (!ancestor->parentNode()->hasEditableStyle()) | 665 if (!ancestor->parentNode()->hasEditableStyle()) |
666 return; | 666 return; |
667 | 667 |
668 VisiblePosition positionAtEndOfNode(lastPositionInOrAfterNode(element.get())
); | 668 VisiblePosition positionAtEndOfNode = createVisiblePosition(lastPositionInOr
AfterNode(element.get())); |
669 VisiblePosition lastPositionInParagraph(lastPositionInNode(ancestor.get())); | 669 VisiblePosition lastPositionInParagraph = createVisiblePosition(lastPosition
InNode(ancestor.get())); |
670 if (positionAtEndOfNode.deepEquivalent() == lastPositionInParagraph.deepEqui
valent()) { | 670 if (positionAtEndOfNode.deepEquivalent() == lastPositionInParagraph.deepEqui
valent()) { |
671 removeNode(element); | 671 removeNode(element); |
672 if (ancestor->nextSibling()) | 672 if (ancestor->nextSibling()) |
673 insertNodeBefore(element, ancestor->nextSibling()); | 673 insertNodeBefore(element, ancestor->nextSibling()); |
674 else | 674 else |
675 appendNode(element, ancestor->parentNode()); | 675 appendNode(element, ancestor->parentNode()); |
676 } else { | 676 } else { |
677 RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(),
ancestor.get(), true); | 677 RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(),
ancestor.get(), true); |
678 removeNode(element); | 678 removeNode(element); |
679 insertNodeBefore(element, nodeToSplitTo); | 679 insertNodeBefore(element, nodeToSplitTo); |
(...skipping 25 matching lines...) Expand all Loading... |
705 if (firstNodeInserted && firstNodeInserted->isTextNode() && !nodeHasVisibleL
ayoutText(toText(*firstNodeInserted))) { | 705 if (firstNodeInserted && firstNodeInserted->isTextNode() && !nodeHasVisibleL
ayoutText(toText(*firstNodeInserted))) { |
706 insertedNodes.willRemoveNode(*firstNodeInserted); | 706 insertedNodes.willRemoveNode(*firstNodeInserted); |
707 removeNode(firstNodeInserted); | 707 removeNode(firstNodeInserted); |
708 } | 708 } |
709 } | 709 } |
710 | 710 |
711 VisiblePosition ReplaceSelectionCommand::positionAtEndOfInsertedContent() const | 711 VisiblePosition ReplaceSelectionCommand::positionAtEndOfInsertedContent() const |
712 { | 712 { |
713 // FIXME: Why is this hack here? What's special about <select> tags? | 713 // FIXME: Why is this hack here? What's special about <select> tags? |
714 HTMLSelectElement* enclosingSelect = toHTMLSelectElement(enclosingElementWit
hTag(m_endOfInsertedContent, selectTag)); | 714 HTMLSelectElement* enclosingSelect = toHTMLSelectElement(enclosingElementWit
hTag(m_endOfInsertedContent, selectTag)); |
715 return VisiblePosition(enclosingSelect ? lastPositionInOrAfterNode(enclosing
Select) : m_endOfInsertedContent); | 715 return createVisiblePosition(enclosingSelect ? lastPositionInOrAfterNode(enc
losingSelect) : m_endOfInsertedContent); |
716 } | 716 } |
717 | 717 |
718 VisiblePosition ReplaceSelectionCommand::positionAtStartOfInsertedContent() cons
t | 718 VisiblePosition ReplaceSelectionCommand::positionAtStartOfInsertedContent() cons
t |
719 { | 719 { |
720 return VisiblePosition(m_startOfInsertedContent); | 720 return createVisiblePosition(m_startOfInsertedContent); |
721 } | 721 } |
722 | 722 |
723 static void removeHeadContents(ReplacementFragment& fragment) | 723 static void removeHeadContents(ReplacementFragment& fragment) |
724 { | 724 { |
725 Node* next = nullptr; | 725 Node* next = nullptr; |
726 for (Node* node = fragment.firstChild(); node; node = next) { | 726 for (Node* node = fragment.firstChild(); node; node = next) { |
727 if (isHTMLBaseElement(*node) | 727 if (isHTMLBaseElement(*node) |
728 || isHTMLLinkElement(*node) | 728 || isHTMLLinkElement(*node) |
729 || isHTMLMetaElement(*node) | 729 || isHTMLMetaElement(*node) |
730 || isHTMLStyleElement(*node) | 730 || isHTMLStyleElement(*node) |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC
ontent) && !isStartOfParagraph(startOfInsertedContent)); | 843 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC
ontent) && !isStartOfParagraph(startOfInsertedContent)); |
844 | 844 |
845 VisiblePosition destination = mergeForward ? nextPositionOf(endOfInsertedCon
tent) : endOfInsertedContent; | 845 VisiblePosition destination = mergeForward ? nextPositionOf(endOfInsertedCon
tent) : endOfInsertedContent; |
846 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end
OfInsertedContent) : nextPositionOf(endOfInsertedContent); | 846 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end
OfInsertedContent) : nextPositionOf(endOfInsertedContent); |
847 | 847 |
848 // Merging forward could result in deleting the destination anchor node. | 848 // Merging forward could result in deleting the destination anchor node. |
849 // To avoid this, we add a placeholder node before the start of the paragrap
h. | 849 // To avoid this, we add a placeholder node before the start of the paragrap
h. |
850 if (endOfParagraph(startOfParagraphToMove).deepEquivalent() == destination.d
eepEquivalent()) { | 850 if (endOfParagraph(startOfParagraphToMove).deepEquivalent() == destination.d
eepEquivalent()) { |
851 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(docum
ent()); | 851 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(docum
ent()); |
852 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().an
chorNode()); | 852 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().an
chorNode()); |
853 destination = VisiblePosition(positionBeforeNode(placeholder.get())); | 853 destination = createVisiblePosition(positionBeforeNode(placeholder.get()
)); |
854 } | 854 } |
855 | 855 |
856 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove)
, destination); | 856 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove)
, destination); |
857 | 857 |
858 // Merging forward will remove m_endOfInsertedContent from the document. | 858 // Merging forward will remove m_endOfInsertedContent from the document. |
859 if (mergeForward) { | 859 if (mergeForward) { |
860 if (m_startOfInsertedContent.isOrphan()) | 860 if (m_startOfInsertedContent.isOrphan()) |
861 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui
valent(); | 861 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui
valent(); |
862 m_endOfInsertedContent = endingSelection().visibleEnd().deepEquivalent()
; | 862 m_endOfInsertedContent = endingSelection().visibleEnd().deepEquivalent()
; |
863 // If we merged text nodes, m_endOfInsertedContent could be null. If | 863 // If we merged text nodes, m_endOfInsertedContent could be null. If |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 // If the downstream node has been removed there's no point in continuing. | 1025 // If the downstream node has been removed there's no point in continuing. |
1026 if (!mostForwardCaretPosition(insertionPos).anchorNode()) | 1026 if (!mostForwardCaretPosition(insertionPos).anchorNode()) |
1027 return; | 1027 return; |
1028 | 1028 |
1029 // NOTE: This would be an incorrect usage of downstream() if downstream() we
re changed to mean the last position after | 1029 // NOTE: This would be an incorrect usage of downstream() if downstream() we
re changed to mean the last position after |
1030 // p that maps to the same visible position as p (since in the case where a
br is at the end of a block and collapsed | 1030 // p that maps to the same visible position as p (since in the case where a
br is at the end of a block and collapsed |
1031 // away, there are positions after the br which map to the same visible posi
tion as [br, 0]). | 1031 // away, there are positions after the br which map to the same visible posi
tion as [br, 0]). |
1032 HTMLBRElement* endBR = isHTMLBRElement(*mostForwardCaretPosition(insertionPo
s).anchorNode()) ? toHTMLBRElement(mostForwardCaretPosition(insertionPos).anchor
Node()) : 0; | 1032 HTMLBRElement* endBR = isHTMLBRElement(*mostForwardCaretPosition(insertionPo
s).anchorNode()) ? toHTMLBRElement(mostForwardCaretPosition(insertionPos).anchor
Node()) : 0; |
1033 VisiblePosition originalVisPosBeforeEndBR; | 1033 VisiblePosition originalVisPosBeforeEndBR; |
1034 if (endBR) | 1034 if (endBR) |
1035 originalVisPosBeforeEndBR = previousPositionOf(VisiblePosition(positionB
eforeNode(endBR))); | 1035 originalVisPosBeforeEndBR = previousPositionOf(createVisiblePosition(pos
itionBeforeNode(endBR))); |
1036 | 1036 |
1037 RefPtrWillBeRawPtr<Element> enclosingBlockOfInsertionPos = enclosingBlock(in
sertionPos.anchorNode()); | 1037 RefPtrWillBeRawPtr<Element> enclosingBlockOfInsertionPos = enclosingBlock(in
sertionPos.anchorNode()); |
1038 | 1038 |
1039 // Adjust insertionPos to prevent nesting. | 1039 // Adjust insertionPos to prevent nesting. |
1040 // If the start was in a Mail blockquote, we will have already handled adjus
ting insertionPos above. | 1040 // If the start was in a Mail blockquote, we will have already handled adjus
ting insertionPos above. |
1041 if (m_preventNesting && enclosingBlockOfInsertionPos && !isTableCell(enclosi
ngBlockOfInsertionPos.get()) && !startIsInsideMailBlockquote) { | 1041 if (m_preventNesting && enclosingBlockOfInsertionPos && !isTableCell(enclosi
ngBlockOfInsertionPos.get()) && !startIsInsideMailBlockquote) { |
1042 ASSERT(enclosingBlockOfInsertionPos != currentRoot); | 1042 ASSERT(enclosingBlockOfInsertionPos != currentRoot); |
1043 VisiblePosition visibleInsertionPos(insertionPos); | 1043 VisiblePosition visibleInsertionPos = createVisiblePosition(insertionPos
); |
1044 if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInserti
onPos) && fragment.hasInterchangeNewlineAtEnd())) | 1044 if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInserti
onPos) && fragment.hasInterchangeNewlineAtEnd())) |
1045 insertionPos = positionInParentAfterNode(*enclosingBlockOfInsertionP
os); | 1045 insertionPos = positionInParentAfterNode(*enclosingBlockOfInsertionP
os); |
1046 else if (isStartOfBlock(visibleInsertionPos)) | 1046 else if (isStartOfBlock(visibleInsertionPos)) |
1047 insertionPos = positionInParentBeforeNode(*enclosingBlockOfInsertion
Pos); | 1047 insertionPos = positionInParentBeforeNode(*enclosingBlockOfInsertion
Pos); |
1048 } | 1048 } |
1049 | 1049 |
1050 // Paste at start or end of link goes outside of link. | 1050 // Paste at start or end of link goes outside of link. |
1051 insertionPos = positionAvoidingSpecialElementBoundary(insertionPos); | 1051 insertionPos = positionAvoidingSpecialElementBoundary(insertionPos); |
1052 | 1052 |
1053 // FIXME: Can this wait until after the operation has been performed? There
doesn't seem to be | 1053 // FIXME: Can this wait until after the operation has been performed? There
doesn't seem to be |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 | 1152 |
1153 // Mutation events (bug 20161) may have already removed the inserted content | 1153 // Mutation events (bug 20161) may have already removed the inserted content |
1154 if (!insertedNodes.firstNodeInserted() || !insertedNodes.firstNodeInserted()
->inDocument()) | 1154 if (!insertedNodes.firstNodeInserted() || !insertedNodes.firstNodeInserted()
->inDocument()) |
1155 return; | 1155 return; |
1156 | 1156 |
1157 // Scripts specified in javascript protocol may remove |enclosingBlockOfInse
rtionPos| | 1157 // Scripts specified in javascript protocol may remove |enclosingBlockOfInse
rtionPos| |
1158 // during insertion, e.g. <iframe src="javascript:..."> | 1158 // during insertion, e.g. <iframe src="javascript:..."> |
1159 if (enclosingBlockOfInsertionPos && !enclosingBlockOfInsertionPos->inDocumen
t()) | 1159 if (enclosingBlockOfInsertionPos && !enclosingBlockOfInsertionPos->inDocumen
t()) |
1160 enclosingBlockOfInsertionPos = nullptr; | 1160 enclosingBlockOfInsertionPos = nullptr; |
1161 | 1161 |
1162 VisiblePosition startOfInsertedContent(firstPositionInOrBeforeNode(insertedN
odes.firstNodeInserted())); | 1162 VisiblePosition startOfInsertedContent = createVisiblePosition(firstPosition
InOrBeforeNode(insertedNodes.firstNodeInserted())); |
1163 | 1163 |
1164 // We inserted before the enclosingBlockOfInsertionPos to prevent nesting, a
nd the content before the enclosingBlockOfInsertionPos wasn't in its own block a
nd | 1164 // We inserted before the enclosingBlockOfInsertionPos to prevent nesting, a
nd the content before the enclosingBlockOfInsertionPos wasn't in its own block a
nd |
1165 // didn't have a br after it, so the inserted content ended up in the same p
aragraph. | 1165 // didn't have a br after it, so the inserted content ended up in the same p
aragraph. |
1166 if (!startOfInsertedContent.isNull() && enclosingBlockOfInsertionPos && inse
rtionPos.anchorNode() == enclosingBlockOfInsertionPos->parentNode() && (unsigned
)insertionPos.computeEditingOffset() < enclosingBlockOfInsertionPos->nodeIndex()
&& !isStartOfParagraph(startOfInsertedContent)) | 1166 if (!startOfInsertedContent.isNull() && enclosingBlockOfInsertionPos && inse
rtionPos.anchorNode() == enclosingBlockOfInsertionPos->parentNode() && (unsigned
)insertionPos.computeEditingOffset() < enclosingBlockOfInsertionPos->nodeIndex()
&& !isStartOfParagraph(startOfInsertedContent)) |
1167 insertNodeAt(createBreakElement(document()).get(), startOfInsertedConten
t.deepEquivalent()); | 1167 insertNodeAt(createBreakElement(document()).get(), startOfInsertedConten
t.deepEquivalent()); |
1168 | 1168 |
1169 if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosB
eforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText))
)) { | 1169 if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosB
eforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText))
)) { |
1170 RefPtrWillBeRawPtr<ContainerNode> parent = endBR->parentNode(); | 1170 RefPtrWillBeRawPtr<ContainerNode> parent = endBR->parentNode(); |
1171 insertedNodes.willRemoveNode(*endBR); | 1171 insertedNodes.willRemoveNode(*endBR); |
1172 removeNode(endBR); | 1172 removeNode(endBR); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); | 1229 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); |
1230 VisiblePosition next = nextPositionOf(endOfInsertedContent, CannotCrossE
ditingBoundary); | 1230 VisiblePosition next = nextPositionOf(endOfInsertedContent, CannotCrossE
ditingBoundary); |
1231 | 1231 |
1232 if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedCont
ent) || next.isNull()) { | 1232 if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedCont
ent) || next.isNull()) { |
1233 if (!isStartOfParagraph(endOfInsertedContent)) { | 1233 if (!isStartOfParagraph(endOfInsertedContent)) { |
1234 setEndingSelection(endOfInsertedContent); | 1234 setEndingSelection(endOfInsertedContent); |
1235 Element* enclosingBlockElement = enclosingBlock(endOfInsertedCon
tent.deepEquivalent().anchorNode()); | 1235 Element* enclosingBlockElement = enclosingBlock(endOfInsertedCon
tent.deepEquivalent().anchorNode()); |
1236 if (isListItem(enclosingBlockElement)) { | 1236 if (isListItem(enclosingBlockElement)) { |
1237 RefPtrWillBeRawPtr<HTMLLIElement> newListItem = createListIt
emElement(document()); | 1237 RefPtrWillBeRawPtr<HTMLLIElement> newListItem = createListIt
emElement(document()); |
1238 insertNodeAfter(newListItem, enclosingBlockElement); | 1238 insertNodeAfter(newListItem, enclosingBlockElement); |
1239 setEndingSelection(VisiblePosition(firstPositionInNode(newLi
stItem.get()))); | 1239 setEndingSelection(createVisiblePosition(firstPositionInNode
(newListItem.get()))); |
1240 } else { | 1240 } else { |
1241 // Use a default paragraph element (a plain div) for the emp
ty paragraph, using the last paragraph | 1241 // Use a default paragraph element (a plain div) for the emp
ty paragraph, using the last paragraph |
1242 // block's style seems to annoy users. | 1242 // block's style seems to annoy users. |
1243 insertParagraphSeparator(true, !startIsInsideMailBlockquote
&& highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(), | 1243 insertParagraphSeparator(true, !startIsInsideMailBlockquote
&& highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(), |
1244 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary,
insertedNodes.firstNodeInserted()->parentNode())); | 1244 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary,
insertedNodes.firstNodeInserted()->parentNode())); |
1245 } | 1245 } |
1246 | 1246 |
1247 // Select up to the paragraph separator that was added. | 1247 // Select up to the paragraph separator that was added. |
1248 lastPositionToSelect = endingSelection().visibleStart().deepEqui
valent(); | 1248 lastPositionToSelect = endingSelection().visibleStart().deepEqui
valent(); |
1249 updateNodesInserted(lastPositionToSelect.anchorNode()); | 1249 updateNodesInserted(lastPositionToSelect.anchorNode()); |
(...skipping 18 matching lines...) Expand all Loading... |
1268 m_matchStyle = false; | 1268 m_matchStyle = false; |
1269 | 1269 |
1270 completeHTMLReplacement(lastPositionToSelect); | 1270 completeHTMLReplacement(lastPositionToSelect); |
1271 } | 1271 } |
1272 | 1272 |
1273 bool ReplaceSelectionCommand::shouldRemoveEndBR(HTMLBRElement* endBR, const Visi
blePosition& originalVisPosBeforeEndBR) | 1273 bool ReplaceSelectionCommand::shouldRemoveEndBR(HTMLBRElement* endBR, const Visi
blePosition& originalVisPosBeforeEndBR) |
1274 { | 1274 { |
1275 if (!endBR || !endBR->inDocument()) | 1275 if (!endBR || !endBR->inDocument()) |
1276 return false; | 1276 return false; |
1277 | 1277 |
1278 VisiblePosition visiblePos(positionBeforeNode(endBR)); | 1278 VisiblePosition visiblePos = createVisiblePosition(positionBeforeNode(endBR)
); |
1279 | 1279 |
1280 // Don't remove the br if nothing was inserted. | 1280 // Don't remove the br if nothing was inserted. |
1281 if (previousPositionOf(visiblePos).deepEquivalent() == originalVisPosBeforeE
ndBR.deepEquivalent()) | 1281 if (previousPositionOf(visiblePos).deepEquivalent() == originalVisPosBeforeE
ndBR.deepEquivalent()) |
1282 return false; | 1282 return false; |
1283 | 1283 |
1284 // Remove the br if it is collapsed away and so is unnecessary. | 1284 // Remove the br if it is collapsed away and so is unnecessary. |
1285 if (!document().inNoQuirksMode() && isEndOfBlock(visiblePos) && !isStartOfPa
ragraph(visiblePos)) | 1285 if (!document().inNoQuirksMode() && isEndOfBlock(visiblePos) && !isStartOfPa
ragraph(visiblePos)) |
1286 return true; | 1286 return true; |
1287 | 1287 |
1288 // A br that was originally holding a line open should be displaced by inser
ted content or turned into a line break. | 1288 // A br that was originally holding a line open should be displaced by inser
ted content or turned into a line break. |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 | 1457 |
1458 // If the user is inserting a list into an existing list, instead of nesting the
list, | 1458 // If the user is inserting a list into an existing list, instead of nesting the
list, |
1459 // we put the list items into the existing list. | 1459 // we put the list items into the existing list. |
1460 Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtrWillBeRawPtr<HTMLElem
ent> prpListElement, Element* insertionBlock, const Position& insertPos, Inserte
dNodes& insertedNodes) | 1460 Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtrWillBeRawPtr<HTMLElem
ent> prpListElement, Element* insertionBlock, const Position& insertPos, Inserte
dNodes& insertedNodes) |
1461 { | 1461 { |
1462 RefPtrWillBeRawPtr<HTMLElement> listElement = prpListElement; | 1462 RefPtrWillBeRawPtr<HTMLElement> listElement = prpListElement; |
1463 | 1463 |
1464 while (listElement->hasOneChild() && isHTMLListElement(listElement->firstChi
ld())) | 1464 while (listElement->hasOneChild() && isHTMLListElement(listElement->firstChi
ld())) |
1465 listElement = toHTMLElement(listElement->firstChild()); | 1465 listElement = toHTMLElement(listElement->firstChild()); |
1466 | 1466 |
1467 bool isStart = isStartOfParagraph(VisiblePosition(insertPos)); | 1467 bool isStart = isStartOfParagraph(createVisiblePosition(insertPos)); |
1468 bool isEnd = isEndOfParagraph(VisiblePosition(insertPos)); | 1468 bool isEnd = isEndOfParagraph(createVisiblePosition(insertPos)); |
1469 bool isMiddle = !isStart && !isEnd; | 1469 bool isMiddle = !isStart && !isEnd; |
1470 Node* lastNode = insertionBlock; | 1470 Node* lastNode = insertionBlock; |
1471 | 1471 |
1472 // If we're in the middle of a list item, we should split it into two separa
te | 1472 // If we're in the middle of a list item, we should split it into two separa
te |
1473 // list items and insert these nodes between them. | 1473 // list items and insert these nodes between them. |
1474 if (isMiddle) { | 1474 if (isMiddle) { |
1475 int textNodeOffset = insertPos.offsetInContainerNode(); | 1475 int textNodeOffset = insertPos.offsetInContainerNode(); |
1476 if (insertPos.anchorNode()->isTextNode() && textNodeOffset > 0) | 1476 if (insertPos.anchorNode()->isTextNode() && textNodeOffset > 0) |
1477 splitTextNode(toText(insertPos.anchorNode()), textNodeOffset); | 1477 splitTextNode(toText(insertPos.anchorNode()), textNodeOffset); |
1478 splitTreeToNode(insertPos.anchorNode(), lastNode, true); | 1478 splitTreeToNode(insertPos.anchorNode(), lastNode, true); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1529 RefPtrWillBeRawPtr<Node> nodeAfterInsertionPos = mostForwardCaretPosition(en
dingSelection().end()).anchorNode(); | 1529 RefPtrWillBeRawPtr<Node> nodeAfterInsertionPos = mostForwardCaretPosition(en
dingSelection().end()).anchorNode(); |
1530 Text* textNode = toText(fragment.firstChild()); | 1530 Text* textNode = toText(fragment.firstChild()); |
1531 // Our fragment creation code handles tabs, spaces, and newlines, so we don'
t have to worry about those here. | 1531 // Our fragment creation code handles tabs, spaces, and newlines, so we don'
t have to worry about those here. |
1532 | 1532 |
1533 Position start = endingSelection().start(); | 1533 Position start = endingSelection().start(); |
1534 Position end = replaceSelectedTextInNode(textNode->data()); | 1534 Position end = replaceSelectedTextInNode(textNode->data()); |
1535 if (end.isNull()) | 1535 if (end.isNull()) |
1536 return false; | 1536 return false; |
1537 | 1537 |
1538 if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBR
Element(*nodeAfterInsertionPos) | 1538 if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBR
Element(*nodeAfterInsertionPos) |
1539 && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), Visib
lePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) | 1539 && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), creat
eVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) |
1540 removeNodeAndPruneAncestors(nodeAfterInsertionPos.get()); | 1540 removeNodeAndPruneAncestors(nodeAfterInsertionPos.get()); |
1541 | 1541 |
1542 VisibleSelection selectionAfterReplace(m_selectReplacement ? start : end, en
d); | 1542 VisibleSelection selectionAfterReplace(m_selectReplacement ? start : end, en
d); |
1543 | 1543 |
1544 setEndingSelection(selectionAfterReplace); | 1544 setEndingSelection(selectionAfterReplace); |
1545 | 1545 |
1546 return true; | 1546 return true; |
1547 } | 1547 } |
1548 | 1548 |
1549 DEFINE_TRACE(ReplaceSelectionCommand) | 1549 DEFINE_TRACE(ReplaceSelectionCommand) |
1550 { | 1550 { |
1551 visitor->trace(m_startOfInsertedContent); | 1551 visitor->trace(m_startOfInsertedContent); |
1552 visitor->trace(m_endOfInsertedContent); | 1552 visitor->trace(m_endOfInsertedContent); |
1553 visitor->trace(m_insertionStyle); | 1553 visitor->trace(m_insertionStyle); |
1554 visitor->trace(m_documentFragment); | 1554 visitor->trace(m_documentFragment); |
1555 CompositeEditCommand::trace(visitor); | 1555 CompositeEditCommand::trace(visitor); |
1556 } | 1556 } |
1557 | 1557 |
1558 } // namespace blink | 1558 } // namespace blink |
OLD | NEW |