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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 return; | 162 return; |
163 | 163 |
164 Element* shadowAncestorElement; | 164 Element* shadowAncestorElement; |
165 if (editableRoot->isInShadowTree()) | 165 if (editableRoot->isInShadowTree()) |
166 shadowAncestorElement = editableRoot->shadowHost(); | 166 shadowAncestorElement = editableRoot->shadowHost(); |
167 else | 167 else |
168 shadowAncestorElement = editableRoot.get(); | 168 shadowAncestorElement = editableRoot.get(); |
169 | 169 |
170 if (!editableRoot->getAttributeEventListener(EventTypeNames::webkitBeforeTex
tInserted) | 170 if (!editableRoot->getAttributeEventListener(EventTypeNames::webkitBeforeTex
tInserted) |
171 // FIXME: Remove these checks once textareas and textfields actually reg
ister an event handler. | 171 // FIXME: Remove these checks once textareas and textfields actually reg
ister an event handler. |
172 && !(shadowAncestorElement && shadowAncestorElement->renderer() && shado
wAncestorElement->renderer()->isTextControl()) | 172 && !(shadowAncestorElement && shadowAncestorElement->layoutObject() && s
hadowAncestorElement->layoutObject()->isTextControl()) |
173 && editableRoot->layoutObjectIsRichlyEditable()) { | 173 && editableRoot->layoutObjectIsRichlyEditable()) { |
174 removeInterchangeNodes(m_fragment.get()); | 174 removeInterchangeNodes(m_fragment.get()); |
175 return; | 175 return; |
176 } | 176 } |
177 | 177 |
178 RefPtrWillBeRawPtr<HTMLElement> holder = insertFragmentForTestRendering(edit
ableRoot.get()); | 178 RefPtrWillBeRawPtr<HTMLElement> holder = insertFragmentForTestRendering(edit
ableRoot.get()); |
179 if (!holder) { | 179 if (!holder) { |
180 removeInterchangeNodes(m_fragment.get()); | 180 removeInterchangeNodes(m_fragment.get()); |
181 return; | 181 return; |
182 } | 182 } |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 // There are other styles that style rules can give to style spans, | 564 // There are other styles that style rules can give to style spans, |
565 // but these are the two important ones because they'll prevent | 565 // but these are the two important ones because they'll prevent |
566 // inserted content from appearing in the right paragraph. | 566 // inserted content from appearing in the right paragraph. |
567 // FIXME: Hyatt is concerned that selectively using display:inline w
ill give inconsistent | 567 // FIXME: Hyatt is concerned that selectively using display:inline w
ill give inconsistent |
568 // results. We already know one issue because td elements ignore the
ir display property | 568 // results. We already know one issue because td elements ignore the
ir display property |
569 // in quirks mode (which Mail.app is always in). We should look for
an alternative. | 569 // in quirks mode (which Mail.app is always in). We should look for
an alternative. |
570 | 570 |
571 // Mutate using the CSSOM wrapper so we get the same event behavior
as a script. | 571 // Mutate using the CSSOM wrapper so we get the same event behavior
as a script. |
572 if (isBlock(element)) | 572 if (isBlock(element)) |
573 element->style()->setPropertyInternal(CSSPropertyDisplay, "inlin
e", false, IGNORE_EXCEPTION); | 573 element->style()->setPropertyInternal(CSSPropertyDisplay, "inlin
e", false, IGNORE_EXCEPTION); |
574 if (element->renderer() && element->renderer()->style()->isFloating(
)) | 574 if (element->layoutObject() && element->layoutObject()->style()->isF
loating()) |
575 element->style()->setPropertyInternal(CSSPropertyFloat, "none",
false, IGNORE_EXCEPTION); | 575 element->style()->setPropertyInternal(CSSPropertyFloat, "none",
false, IGNORE_EXCEPTION); |
576 } | 576 } |
577 } | 577 } |
578 } | 578 } |
579 | 579 |
580 static bool isProhibitedParagraphChild(const AtomicString& name) | 580 static bool isProhibitedParagraphChild(const AtomicString& name) |
581 { | 581 { |
582 // https://dvcs.w3.org/hg/editing/raw-file/57abe6d3cb60/editing.html#prohibi
ted-paragraph-child | 582 // https://dvcs.w3.org/hg/editing/raw-file/57abe6d3cb60/editing.html#prohibi
ted-paragraph-child |
583 DEFINE_STATIC_LOCAL(HashSet<AtomicString>, elements, ()); | 583 DEFINE_STATIC_LOCAL(HashSet<AtomicString>, elements, ()); |
584 if (elements.isEmpty()) { | 584 if (elements.isEmpty()) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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); |
680 } | 680 } |
681 if (!ancestor->hasChildren()) | 681 if (!ancestor->hasChildren()) |
682 removeNode(ancestor.release()); | 682 removeNode(ancestor.release()); |
683 } | 683 } |
684 | 684 |
685 static inline bool nodeHasVisibleRenderText(Text& text) | 685 static inline bool nodeHasVisibleRenderText(Text& text) |
686 { | 686 { |
687 return text.renderer() && text.renderer()->renderedTextLength() > 0; | 687 return text.layoutObject() && text.layoutObject()->renderedTextLength() > 0; |
688 } | 688 } |
689 | 689 |
690 void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds(InsertedNodes& ins
ertedNodes) | 690 void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds(InsertedNodes& ins
ertedNodes) |
691 { | 691 { |
692 document().updateLayoutIgnorePendingStylesheets(); | 692 document().updateLayoutIgnorePendingStylesheets(); |
693 | 693 |
694 Node* lastLeafInserted = insertedNodes.lastLeafInserted(); | 694 Node* lastLeafInserted = insertedNodes.lastLeafInserted(); |
695 if (lastLeafInserted && lastLeafInserted->isTextNode() && !nodeHasVisibleRen
derText(toText(*lastLeafInserted)) | 695 if (lastLeafInserted && lastLeafInserted->isTextNode() && !nodeHasVisibleRen
derText(toText(*lastLeafInserted)) |
696 && !enclosingElementWithTag(firstPositionInOrBeforeNode(lastLeafInserted
), selectTag) | 696 && !enclosingElementWithTag(firstPositionInOrBeforeNode(lastLeafInserted
), selectTag) |
697 && !enclosingElementWithTag(firstPositionInOrBeforeNode(lastLeafInserted
), scriptTag)) { | 697 && !enclosingElementWithTag(firstPositionInOrBeforeNode(lastLeafInserted
), scriptTag)) { |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 return; | 925 return; |
926 | 926 |
927 if (!selection.rootEditableElement()) | 927 if (!selection.rootEditableElement()) |
928 return; | 928 return; |
929 | 929 |
930 ReplacementFragment fragment(&document(), m_documentFragment.get(), selectio
n); | 930 ReplacementFragment fragment(&document(), m_documentFragment.get(), selectio
n); |
931 if (performTrivialReplace(fragment)) | 931 if (performTrivialReplace(fragment)) |
932 return; | 932 return; |
933 | 933 |
934 // We can skip matching the style if the selection is plain text. | 934 // We can skip matching the style if the selection is plain text. |
935 if ((selection.start().deprecatedNode()->renderer() && selection.start().dep
recatedNode()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY) | 935 if ((selection.start().deprecatedNode()->layoutObject() && selection.start()
.deprecatedNode()->layoutObject()->style()->userModify() == READ_WRITE_PLAINTEXT
_ONLY) |
936 && (selection.end().deprecatedNode()->renderer() && selection.end().depr
ecatedNode()->renderer()->style()->userModify() == READ_WRITE_PLAINTEXT_ONLY)) | 936 && (selection.end().deprecatedNode()->layoutObject() && selection.end().
deprecatedNode()->layoutObject()->style()->userModify() == READ_WRITE_PLAINTEXT_
ONLY)) |
937 m_matchStyle = false; | 937 m_matchStyle = false; |
938 | 938 |
939 if (m_matchStyle) { | 939 if (m_matchStyle) { |
940 m_insertionStyle = EditingStyle::create(selection.start()); | 940 m_insertionStyle = EditingStyle::create(selection.start()); |
941 m_insertionStyle->mergeTypingStyle(&document()); | 941 m_insertionStyle->mergeTypingStyle(&document()); |
942 } | 942 } |
943 | 943 |
944 VisiblePosition visibleStart = selection.visibleStart(); | 944 VisiblePosition visibleStart = selection.visibleStart(); |
945 VisiblePosition visibleEnd = selection.visibleEnd(); | 945 VisiblePosition visibleEnd = selection.visibleEnd(); |
946 | 946 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 | 1104 |
1105 InsertedNodes insertedNodes; | 1105 InsertedNodes insertedNodes; |
1106 RefPtrWillBeRawPtr<Node> refNode = fragment.firstChild(); | 1106 RefPtrWillBeRawPtr<Node> refNode = fragment.firstChild(); |
1107 ASSERT(refNode); | 1107 ASSERT(refNode); |
1108 RefPtrWillBeRawPtr<Node> node = refNode->nextSibling(); | 1108 RefPtrWillBeRawPtr<Node> node = refNode->nextSibling(); |
1109 | 1109 |
1110 fragment.removeNode(refNode); | 1110 fragment.removeNode(refNode); |
1111 | 1111 |
1112 Element* blockStart = enclosingBlock(insertionPos.deprecatedNode()); | 1112 Element* blockStart = enclosingBlock(insertionPos.deprecatedNode()); |
1113 if ((isHTMLListElement(refNode.get()) || (isLegacyAppleHTMLSpanElement(refNo
de.get()) && isHTMLListElement(refNode->firstChild()))) | 1113 if ((isHTMLListElement(refNode.get()) || (isLegacyAppleHTMLSpanElement(refNo
de.get()) && isHTMLListElement(refNode->firstChild()))) |
1114 && blockStart && blockStart->renderer()->isListItem()) | 1114 && blockStart && blockStart->layoutObject()->isListItem()) |
1115 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio
nPos, insertedNodes); | 1115 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio
nPos, insertedNodes); |
1116 else { | 1116 else { |
1117 insertNodeAt(refNode, insertionPos); | 1117 insertNodeAt(refNode, insertionPos); |
1118 insertedNodes.respondToNodeInsertion(*refNode); | 1118 insertedNodes.respondToNodeInsertion(*refNode); |
1119 } | 1119 } |
1120 | 1120 |
1121 // Mutation events (bug 22634) may have already removed the inserted content | 1121 // Mutation events (bug 22634) may have already removed the inserted content |
1122 if (!refNode->inDocument()) | 1122 if (!refNode->inDocument()) |
1123 return; | 1123 return; |
1124 | 1124 |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 Position endUpstream = endOfInsertedContent.deepEquivalent().upstream(); | 1310 Position endUpstream = endOfInsertedContent.deepEquivalent().upstream(); |
1311 Node* endNode = endUpstream.computeNodeBeforePosition(); | 1311 Node* endNode = endUpstream.computeNodeBeforePosition(); |
1312 int endOffset = endNode && endNode->isTextNode() ? toText(endNode)->length()
: 0; | 1312 int endOffset = endNode && endNode->isTextNode() ? toText(endNode)->length()
: 0; |
1313 if (endUpstream.anchorType() == Position::PositionIsOffsetInAnchor) { | 1313 if (endUpstream.anchorType() == Position::PositionIsOffsetInAnchor) { |
1314 endNode = endUpstream.containerNode(); | 1314 endNode = endUpstream.containerNode(); |
1315 endOffset = endUpstream.offsetInContainerNode(); | 1315 endOffset = endUpstream.offsetInContainerNode(); |
1316 } | 1316 } |
1317 | 1317 |
1318 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar
acterSmartReplaceExemptConsideringNonBreakingSpace(endOfInsertedContent.characte
rAfter(), false); | 1318 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar
acterSmartReplaceExemptConsideringNonBreakingSpace(endOfInsertedContent.characte
rAfter(), false); |
1319 if (needsTrailingSpace && endNode) { | 1319 if (needsTrailingSpace && endNode) { |
1320 bool collapseWhiteSpace = !endNode->renderer() || endNode->renderer()->s
tyle()->collapseWhiteSpace(); | 1320 bool collapseWhiteSpace = !endNode->layoutObject() || endNode->layoutObj
ect()->style()->collapseWhiteSpace(); |
1321 if (endNode->isTextNode()) { | 1321 if (endNode->isTextNode()) { |
1322 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ?
nonBreakingSpaceString() : " "); | 1322 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ?
nonBreakingSpaceString() : " "); |
1323 if (m_endOfInsertedContent.containerNode() == endNode) | 1323 if (m_endOfInsertedContent.containerNode() == endNode) |
1324 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse
tInContainerNode() + 1); | 1324 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse
tInContainerNode() + 1); |
1325 } else { | 1325 } else { |
1326 RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(col
lapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1326 RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(col
lapseWhiteSpace ? nonBreakingSpaceString() : " "); |
1327 insertNodeAfter(node, endNode); | 1327 insertNodeAfter(node, endNode); |
1328 updateNodesInserted(node.get()); | 1328 updateNodesInserted(node.get()); |
1329 } | 1329 } |
1330 } | 1330 } |
1331 | 1331 |
1332 document().updateLayout(); | 1332 document().updateLayout(); |
1333 | 1333 |
1334 Position startDownstream = startOfInsertedContent.deepEquivalent().downstrea
m(); | 1334 Position startDownstream = startOfInsertedContent.deepEquivalent().downstrea
m(); |
1335 Node* startNode = startDownstream.computeNodeAfterPosition(); | 1335 Node* startNode = startDownstream.computeNodeAfterPosition(); |
1336 unsigned startOffset = 0; | 1336 unsigned startOffset = 0; |
1337 if (startDownstream.anchorType() == Position::PositionIsOffsetInAnchor) { | 1337 if (startDownstream.anchorType() == Position::PositionIsOffsetInAnchor) { |
1338 startNode = startDownstream.containerNode(); | 1338 startNode = startDownstream.containerNode(); |
1339 startOffset = startDownstream.offsetInContainerNode(); | 1339 startOffset = startDownstream.offsetInContainerNode(); |
1340 } | 1340 } |
1341 | 1341 |
1342 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC
haracterSmartReplaceExemptConsideringNonBreakingSpace(startOfInsertedContent.pre
vious().characterAfter(), true); | 1342 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC
haracterSmartReplaceExemptConsideringNonBreakingSpace(startOfInsertedContent.pre
vious().characterAfter(), true); |
1343 if (needsLeadingSpace && startNode) { | 1343 if (needsLeadingSpace && startNode) { |
1344 bool collapseWhiteSpace = !startNode->renderer() || startNode->renderer(
)->style()->collapseWhiteSpace(); | 1344 bool collapseWhiteSpace = !startNode->layoutObject() || startNode->layou
tObject()->style()->collapseWhiteSpace(); |
1345 if (startNode->isTextNode()) { | 1345 if (startNode->isTextNode()) { |
1346 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac
e ? nonBreakingSpaceString() : " "); | 1346 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac
e ? nonBreakingSpaceString() : " "); |
1347 if (m_endOfInsertedContent.containerNode() == startNode && m_endOfIn
sertedContent.offsetInContainerNode()) | 1347 if (m_endOfInsertedContent.containerNode() == startNode && m_endOfIn
sertedContent.offsetInContainerNode()) |
1348 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse
tInContainerNode() + 1); | 1348 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse
tInContainerNode() + 1); |
1349 } else { | 1349 } else { |
1350 RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(col
lapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1350 RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(col
lapseWhiteSpace ? nonBreakingSpaceString() : " "); |
1351 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont
ent to be the node containing the leading space, | 1351 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont
ent to be the node containing the leading space, |
1352 // but m_endOfInsertedContent is supposed to mark the end of pasted
content. | 1352 // but m_endOfInsertedContent is supposed to mark the end of pasted
content. |
1353 insertNodeBefore(node, startNode); | 1353 insertNodeBefore(node, startNode); |
1354 m_startOfInsertedContent = firstPositionInNode(node.get()); | 1354 m_startOfInsertedContent = firstPositionInNode(node.get()); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1542 DEFINE_TRACE(ReplaceSelectionCommand) | 1542 DEFINE_TRACE(ReplaceSelectionCommand) |
1543 { | 1543 { |
1544 visitor->trace(m_startOfInsertedContent); | 1544 visitor->trace(m_startOfInsertedContent); |
1545 visitor->trace(m_endOfInsertedContent); | 1545 visitor->trace(m_endOfInsertedContent); |
1546 visitor->trace(m_insertionStyle); | 1546 visitor->trace(m_insertionStyle); |
1547 visitor->trace(m_documentFragment); | 1547 visitor->trace(m_documentFragment); |
1548 CompositeEditCommand::trace(visitor); | 1548 CompositeEditCommand::trace(visitor); |
1549 } | 1549 } |
1550 | 1550 |
1551 } // namespace blink | 1551 } // namespace blink |
OLD | NEW |