| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 ReplacementFragment(Document*, DocumentFragment*, const VisibleSelection&); | 76 ReplacementFragment(Document*, DocumentFragment*, const VisibleSelection&); |
| 77 | 77 |
| 78 Node* firstChild() const; | 78 Node* firstChild() const; |
| 79 Node* lastChild() const; | 79 Node* lastChild() const; |
| 80 | 80 |
| 81 bool isEmpty() const; | 81 bool isEmpty() const; |
| 82 | 82 |
| 83 bool hasInterchangeNewlineAtStart() const { return m_hasInterchangeNewlineAt
Start; } | 83 bool hasInterchangeNewlineAtStart() const { return m_hasInterchangeNewlineAt
Start; } |
| 84 bool hasInterchangeNewlineAtEnd() const { return m_hasInterchangeNewlineAtEn
d; } | 84 bool hasInterchangeNewlineAtEnd() const { return m_hasInterchangeNewlineAtEn
d; } |
| 85 | 85 |
| 86 void removeNode(PassRefPtrWillBeRawPtr<Node>); | 86 void removeNode(RawPtr<Node>); |
| 87 void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<ContainerNode>); | 87 void removeNodePreservingChildren(RawPtr<ContainerNode>); |
| 88 | 88 |
| 89 private: | 89 private: |
| 90 PassRefPtrWillBeRawPtr<HTMLElement> insertFragmentForTestRendering(Element*
rootEditableElement); | 90 RawPtr<HTMLElement> insertFragmentForTestRendering(Element* rootEditableElem
ent); |
| 91 void removeUnrenderedNodes(ContainerNode*); | 91 void removeUnrenderedNodes(ContainerNode*); |
| 92 void restoreAndRemoveTestRenderingNodesToFragment(Element*); | 92 void restoreAndRemoveTestRenderingNodesToFragment(Element*); |
| 93 void removeInterchangeNodes(ContainerNode*); | 93 void removeInterchangeNodes(ContainerNode*); |
| 94 | 94 |
| 95 void insertNodeBefore(PassRefPtrWillBeRawPtr<Node>, Node* refNode); | 95 void insertNodeBefore(RawPtr<Node>, Node* refNode); |
| 96 | 96 |
| 97 RefPtrWillBeMember<Document> m_document; | 97 Member<Document> m_document; |
| 98 RefPtrWillBeMember<DocumentFragment> m_fragment; | 98 Member<DocumentFragment> m_fragment; |
| 99 bool m_hasInterchangeNewlineAtStart; | 99 bool m_hasInterchangeNewlineAtStart; |
| 100 bool m_hasInterchangeNewlineAtEnd; | 100 bool m_hasInterchangeNewlineAtEnd; |
| 101 }; | 101 }; |
| 102 | 102 |
| 103 static bool isInterchangeHTMLBRElement(const Node* node) | 103 static bool isInterchangeHTMLBRElement(const Node* node) |
| 104 { | 104 { |
| 105 DEFINE_STATIC_LOCAL(String, interchangeNewlineClassString, (AppleInterchange
Newline)); | 105 DEFINE_STATIC_LOCAL(String, interchangeNewlineClassString, (AppleInterchange
Newline)); |
| 106 if (!isHTMLBRElement(node) || toHTMLBRElement(node)->getAttribute(classAttr)
!= interchangeNewlineClassString) | 106 if (!isHTMLBRElement(node) || toHTMLBRElement(node)->getAttribute(classAttr)
!= interchangeNewlineClassString) |
| 107 return false; | 107 return false; |
| 108 UseCounter::count(node->document(), UseCounter::EditingAppleInterchangeNewli
ne); | 108 UseCounter::count(node->document(), UseCounter::EditingAppleInterchangeNewli
ne); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 : m_document(document) | 148 : m_document(document) |
| 149 , m_fragment(fragment) | 149 , m_fragment(fragment) |
| 150 , m_hasInterchangeNewlineAtStart(false) | 150 , m_hasInterchangeNewlineAtStart(false) |
| 151 , m_hasInterchangeNewlineAtEnd(false) | 151 , m_hasInterchangeNewlineAtEnd(false) |
| 152 { | 152 { |
| 153 if (!m_document) | 153 if (!m_document) |
| 154 return; | 154 return; |
| 155 if (!m_fragment || !m_fragment->hasChildren()) | 155 if (!m_fragment || !m_fragment->hasChildren()) |
| 156 return; | 156 return; |
| 157 | 157 |
| 158 RefPtrWillBeRawPtr<Element> editableRoot = selection.rootEditableElement(); | 158 RawPtr<Element> editableRoot = selection.rootEditableElement(); |
| 159 ASSERT(editableRoot); | 159 ASSERT(editableRoot); |
| 160 if (!editableRoot) | 160 if (!editableRoot) |
| 161 return; | 161 return; |
| 162 | 162 |
| 163 Element* shadowAncestorElement; | 163 Element* shadowAncestorElement; |
| 164 if (editableRoot->isInShadowTree()) | 164 if (editableRoot->isInShadowTree()) |
| 165 shadowAncestorElement = editableRoot->shadowHost(); | 165 shadowAncestorElement = editableRoot->shadowHost(); |
| 166 else | 166 else |
| 167 shadowAncestorElement = editableRoot.get(); | 167 shadowAncestorElement = editableRoot.get(); |
| 168 | 168 |
| 169 if (!editableRoot->getAttributeEventListener(EventTypeNames::webkitBeforeTex
tInserted) | 169 if (!editableRoot->getAttributeEventListener(EventTypeNames::webkitBeforeTex
tInserted) |
| 170 // FIXME: Remove these checks once textareas and textfields actually reg
ister an event handler. | 170 // FIXME: Remove these checks once textareas and textfields actually reg
ister an event handler. |
| 171 && !(shadowAncestorElement && shadowAncestorElement->layoutObject() && s
hadowAncestorElement->layoutObject()->isTextControl()) | 171 && !(shadowAncestorElement && shadowAncestorElement->layoutObject() && s
hadowAncestorElement->layoutObject()->isTextControl()) |
| 172 && editableRoot->layoutObjectIsRichlyEditable()) { | 172 && editableRoot->layoutObjectIsRichlyEditable()) { |
| 173 removeInterchangeNodes(m_fragment.get()); | 173 removeInterchangeNodes(m_fragment.get()); |
| 174 return; | 174 return; |
| 175 } | 175 } |
| 176 | 176 |
| 177 RefPtrWillBeRawPtr<HTMLElement> holder = insertFragmentForTestRendering(edit
ableRoot.get()); | 177 RawPtr<HTMLElement> holder = insertFragmentForTestRendering(editableRoot.get
()); |
| 178 if (!holder) { | 178 if (!holder) { |
| 179 removeInterchangeNodes(m_fragment.get()); | 179 removeInterchangeNodes(m_fragment.get()); |
| 180 return; | 180 return; |
| 181 } | 181 } |
| 182 | 182 |
| 183 const EphemeralRange range = VisibleSelection::selectionFromContentsOfNode(h
older.get()).toNormalizedEphemeralRange(); | 183 const EphemeralRange range = VisibleSelection::selectionFromContentsOfNode(h
older.get()).toNormalizedEphemeralRange(); |
| 184 String text = plainText(range, static_cast<TextIteratorBehavior>(TextIterato
rEmitsOriginalText | TextIteratorIgnoresStyleVisibility)); | 184 String text = plainText(range, static_cast<TextIteratorBehavior>(TextIterato
rEmitsOriginalText | TextIteratorIgnoresStyleVisibility)); |
| 185 | 185 |
| 186 removeInterchangeNodes(holder.get()); | 186 removeInterchangeNodes(holder.get()); |
| 187 removeUnrenderedNodes(holder.get()); | 187 removeUnrenderedNodes(holder.get()); |
| 188 restoreAndRemoveTestRenderingNodesToFragment(holder.get()); | 188 restoreAndRemoveTestRenderingNodesToFragment(holder.get()); |
| 189 | 189 |
| 190 // Give the root a chance to change the text. | 190 // Give the root a chance to change the text. |
| 191 RefPtrWillBeRawPtr<BeforeTextInsertedEvent> evt = BeforeTextInsertedEvent::c
reate(text); | 191 RawPtr<BeforeTextInsertedEvent> evt = BeforeTextInsertedEvent::create(text); |
| 192 editableRoot->dispatchEvent(evt); | 192 editableRoot->dispatchEvent(evt); |
| 193 if (text != evt->text() || !editableRoot->layoutObjectIsRichlyEditable()) { | 193 if (text != evt->text() || !editableRoot->layoutObjectIsRichlyEditable()) { |
| 194 restoreAndRemoveTestRenderingNodesToFragment(holder.get()); | 194 restoreAndRemoveTestRenderingNodesToFragment(holder.get()); |
| 195 | 195 |
| 196 m_fragment = createFragmentFromText(selection.toNormalizedEphemeralRange
(), evt->text()); | 196 m_fragment = createFragmentFromText(selection.toNormalizedEphemeralRange
(), evt->text()); |
| 197 if (!m_fragment->hasChildren()) | 197 if (!m_fragment->hasChildren()) |
| 198 return; | 198 return; |
| 199 | 199 |
| 200 holder = insertFragmentForTestRendering(editableRoot.get()); | 200 holder = insertFragmentForTestRendering(editableRoot.get()); |
| 201 removeInterchangeNodes(holder.get()); | 201 removeInterchangeNodes(holder.get()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 212 Node* ReplacementFragment::firstChild() const | 212 Node* ReplacementFragment::firstChild() const |
| 213 { | 213 { |
| 214 return m_fragment ? m_fragment->firstChild() : 0; | 214 return m_fragment ? m_fragment->firstChild() : 0; |
| 215 } | 215 } |
| 216 | 216 |
| 217 Node* ReplacementFragment::lastChild() const | 217 Node* ReplacementFragment::lastChild() const |
| 218 { | 218 { |
| 219 return m_fragment ? m_fragment->lastChild() : 0; | 219 return m_fragment ? m_fragment->lastChild() : 0; |
| 220 } | 220 } |
| 221 | 221 |
| 222 void ReplacementFragment::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Co
ntainerNode> node) | 222 void ReplacementFragment::removeNodePreservingChildren(RawPtr<ContainerNode> nod
e) |
| 223 { | 223 { |
| 224 if (!node) | 224 if (!node) |
| 225 return; | 225 return; |
| 226 | 226 |
| 227 while (RefPtrWillBeRawPtr<Node> n = node->firstChild()) { | 227 while (RawPtr<Node> n = node->firstChild()) { |
| 228 removeNode(n); | 228 removeNode(n); |
| 229 insertNodeBefore(n.release(), node.get()); | 229 insertNodeBefore(n.release(), node.get()); |
| 230 } | 230 } |
| 231 removeNode(node); | 231 removeNode(node); |
| 232 } | 232 } |
| 233 | 233 |
| 234 void ReplacementFragment::removeNode(PassRefPtrWillBeRawPtr<Node> node) | 234 void ReplacementFragment::removeNode(RawPtr<Node> node) |
| 235 { | 235 { |
| 236 if (!node) | 236 if (!node) |
| 237 return; | 237 return; |
| 238 | 238 |
| 239 ContainerNode* parent = node->nonShadowBoundaryParentNode(); | 239 ContainerNode* parent = node->nonShadowBoundaryParentNode(); |
| 240 if (!parent) | 240 if (!parent) |
| 241 return; | 241 return; |
| 242 | 242 |
| 243 parent->removeChild(node.get()); | 243 parent->removeChild(node.get()); |
| 244 } | 244 } |
| 245 | 245 |
| 246 void ReplacementFragment::insertNodeBefore(PassRefPtrWillBeRawPtr<Node> node, No
de* refNode) | 246 void ReplacementFragment::insertNodeBefore(RawPtr<Node> node, Node* refNode) |
| 247 { | 247 { |
| 248 if (!node || !refNode) | 248 if (!node || !refNode) |
| 249 return; | 249 return; |
| 250 | 250 |
| 251 ContainerNode* parent = refNode->nonShadowBoundaryParentNode(); | 251 ContainerNode* parent = refNode->nonShadowBoundaryParentNode(); |
| 252 if (!parent) | 252 if (!parent) |
| 253 return; | 253 return; |
| 254 | 254 |
| 255 parent->insertBefore(node, refNode); | 255 parent->insertBefore(node, refNode); |
| 256 } | 256 } |
| 257 | 257 |
| 258 PassRefPtrWillBeRawPtr<HTMLElement> ReplacementFragment::insertFragmentForTestRe
ndering(Element* rootEditableElement) | 258 RawPtr<HTMLElement> ReplacementFragment::insertFragmentForTestRendering(Element*
rootEditableElement) |
| 259 { | 259 { |
| 260 ASSERT(m_document); | 260 ASSERT(m_document); |
| 261 RefPtrWillBeRawPtr<HTMLElement> holder = createDefaultParagraphElement(*m_do
cument.get()); | 261 RawPtr<HTMLElement> holder = createDefaultParagraphElement(*m_document.get()
); |
| 262 | 262 |
| 263 holder->appendChild(m_fragment); | 263 holder->appendChild(m_fragment); |
| 264 rootEditableElement->appendChild(holder.get()); | 264 rootEditableElement->appendChild(holder.get()); |
| 265 m_document->updateLayoutIgnorePendingStylesheets(); | 265 m_document->updateLayoutIgnorePendingStylesheets(); |
| 266 | 266 |
| 267 return holder.release(); | 267 return holder.release(); |
| 268 } | 268 } |
| 269 | 269 |
| 270 void ReplacementFragment::restoreAndRemoveTestRenderingNodesToFragment(Element*
holder) | 270 void ReplacementFragment::restoreAndRemoveTestRenderingNodesToFragment(Element*
holder) |
| 271 { | 271 { |
| 272 if (!holder) | 272 if (!holder) |
| 273 return; | 273 return; |
| 274 | 274 |
| 275 while (RefPtrWillBeRawPtr<Node> node = holder->firstChild()) { | 275 while (RawPtr<Node> node = holder->firstChild()) { |
| 276 holder->removeChild(node.get()); | 276 holder->removeChild(node.get()); |
| 277 m_fragment->appendChild(node.get()); | 277 m_fragment->appendChild(node.get()); |
| 278 } | 278 } |
| 279 | 279 |
| 280 removeNode(holder); | 280 removeNode(holder); |
| 281 } | 281 } |
| 282 | 282 |
| 283 void ReplacementFragment::removeUnrenderedNodes(ContainerNode* holder) | 283 void ReplacementFragment::removeUnrenderedNodes(ContainerNode* holder) |
| 284 { | 284 { |
| 285 WillBeHeapVector<RefPtrWillBeMember<Node>> unrendered; | 285 HeapVector<Member<Node>> unrendered; |
| 286 | 286 |
| 287 for (Node& node : NodeTraversal::descendantsOf(*holder)) { | 287 for (Node& node : NodeTraversal::descendantsOf(*holder)) { |
| 288 if (!isNodeRendered(node) && !isTableStructureNode(&node)) | 288 if (!isNodeRendered(node) && !isTableStructureNode(&node)) |
| 289 unrendered.append(&node); | 289 unrendered.append(&node); |
| 290 } | 290 } |
| 291 | 291 |
| 292 for (auto& node : unrendered) | 292 for (auto& node : unrendered) |
| 293 removeNode(node); | 293 removeNode(node); |
| 294 } | 294 } |
| 295 | 295 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 318 if (isInterchangeHTMLBRElement(node)) { | 318 if (isInterchangeHTMLBRElement(node)) { |
| 319 m_hasInterchangeNewlineAtEnd = true; | 319 m_hasInterchangeNewlineAtEnd = true; |
| 320 removeNode(node); | 320 removeNode(node); |
| 321 break; | 321 break; |
| 322 } | 322 } |
| 323 node = node->lastChild(); | 323 node = node->lastChild(); |
| 324 } | 324 } |
| 325 | 325 |
| 326 node = container->firstChild(); | 326 node = container->firstChild(); |
| 327 while (node) { | 327 while (node) { |
| 328 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*node); | 328 RawPtr<Node> next = NodeTraversal::next(*node); |
| 329 if (isHTMLInterchangeConvertedSpaceSpan(node)) { | 329 if (isHTMLInterchangeConvertedSpaceSpan(node)) { |
| 330 HTMLElement& element = toHTMLElement(*node); | 330 HTMLElement& element = toHTMLElement(*node); |
| 331 next = NodeTraversal::nextSkippingChildren(element); | 331 next = NodeTraversal::nextSkippingChildren(element); |
| 332 removeNodePreservingChildren(&element); | 332 removeNodePreservingChildren(&element); |
| 333 } | 333 } |
| 334 node = next.get(); | 334 node = next.get(); |
| 335 } | 335 } |
| 336 } | 336 } |
| 337 | 337 |
| 338 inline void ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion(Node&
node) | 338 inline void ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion(Node&
node) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 364 } | 364 } |
| 365 | 365 |
| 366 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(Node& node, N
ode& newNode) | 366 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(Node& node, N
ode& newNode) |
| 367 { | 367 { |
| 368 if (m_firstNodeInserted.get() == node) | 368 if (m_firstNodeInserted.get() == node) |
| 369 m_firstNodeInserted = &newNode; | 369 m_firstNodeInserted = &newNode; |
| 370 if (m_lastNodeInserted.get() == node) | 370 if (m_lastNodeInserted.get() == node) |
| 371 m_lastNodeInserted = &newNode; | 371 m_lastNodeInserted = &newNode; |
| 372 } | 372 } |
| 373 | 373 |
| 374 ReplaceSelectionCommand::ReplaceSelectionCommand(Document& document, PassRefPtrW
illBeRawPtr<DocumentFragment> fragment, CommandOptions options, EditAction editA
ction) | 374 ReplaceSelectionCommand::ReplaceSelectionCommand(Document& document, RawPtr<Docu
mentFragment> fragment, CommandOptions options, EditAction editAction) |
| 375 : CompositeEditCommand(document) | 375 : CompositeEditCommand(document) |
| 376 , m_selectReplacement(options & SelectReplacement) | 376 , m_selectReplacement(options & SelectReplacement) |
| 377 , m_smartReplace(options & SmartReplace) | 377 , m_smartReplace(options & SmartReplace) |
| 378 , m_matchStyle(options & MatchStyle) | 378 , m_matchStyle(options & MatchStyle) |
| 379 , m_documentFragment(fragment) | 379 , m_documentFragment(fragment) |
| 380 , m_preventNesting(options & PreventNesting) | 380 , m_preventNesting(options & PreventNesting) |
| 381 , m_movingParagraph(options & MovingParagraph) | 381 , m_movingParagraph(options & MovingParagraph) |
| 382 , m_editAction(editAction) | 382 , m_editAction(editAction) |
| 383 , m_sanitizeFragment(options & SanitizeFragment) | 383 , m_sanitizeFragment(options & SanitizeFragment) |
| 384 , m_shouldMergeEnd(false) | 384 , m_shouldMergeEnd(false) |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 && (!isHTMLHeaderElement(sourceBlock) || haveSameTagName(sourceBlock, de
stinationBlock)) | 477 && (!isHTMLHeaderElement(sourceBlock) || haveSameTagName(sourceBlock, de
stinationBlock)) |
| 478 // Don't merge to or from a position before or after a block because it
would | 478 // Don't merge to or from a position before or after a block because it
would |
| 479 // be a no-op and cause infinite recursion. | 479 // be a no-op and cause infinite recursion. |
| 480 && !isEnclosingBlock(sourceNode) && !isEnclosingBlock(destinationNode); | 480 && !isEnclosingBlock(sourceNode) && !isEnclosingBlock(destinationNode); |
| 481 } | 481 } |
| 482 | 482 |
| 483 // Style rules that match just inserted elements could change their appearance,
like | 483 // Style rules that match just inserted elements could change their appearance,
like |
| 484 // a div inserted into a document with div { display:inline; }. | 484 // a div inserted into a document with div { display:inline; }. |
| 485 void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert
edNodes& insertedNodes) | 485 void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert
edNodes& insertedNodes) |
| 486 { | 486 { |
| 487 RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); | 487 RawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); |
| 488 RefPtrWillBeRawPtr<Node> next = nullptr; | 488 RawPtr<Node> next = nullptr; |
| 489 for (RefPtrWillBeRawPtr<Node> node = insertedNodes.firstNodeInserted(); node
&& node != pastEndNode; node = next) { | 489 for (RawPtr<Node> node = insertedNodes.firstNodeInserted(); node && node !=
pastEndNode; node = next) { |
| 490 // FIXME: <rdar://problem/5371536> Style rules that match pasted content
can change it's appearance | 490 // FIXME: <rdar://problem/5371536> Style rules that match pasted content
can change it's appearance |
| 491 | 491 |
| 492 next = NodeTraversal::next(*node); | 492 next = NodeTraversal::next(*node); |
| 493 if (!node->isStyledElement()) | 493 if (!node->isStyledElement()) |
| 494 continue; | 494 continue; |
| 495 | 495 |
| 496 Element* element = toElement(node); | 496 Element* element = toElement(node); |
| 497 | 497 |
| 498 const StylePropertySet* inlineStyle = element->inlineStyle(); | 498 const StylePropertySet* inlineStyle = element->inlineStyle(); |
| 499 RefPtrWillBeRawPtr<EditingStyle> newInlineStyle = EditingStyle::create(i
nlineStyle); | 499 RawPtr<EditingStyle> newInlineStyle = EditingStyle::create(inlineStyle); |
| 500 if (inlineStyle) { | 500 if (inlineStyle) { |
| 501 if (element->isHTMLElement()) { | 501 if (element->isHTMLElement()) { |
| 502 Vector<QualifiedName> attributes; | 502 Vector<QualifiedName> attributes; |
| 503 HTMLElement* htmlElement = toHTMLElement(element); | 503 HTMLElement* htmlElement = toHTMLElement(element); |
| 504 ASSERT(htmlElement); | 504 ASSERT(htmlElement); |
| 505 | 505 |
| 506 if (newInlineStyle->conflictsWithImplicitStyleOfElement(htmlElem
ent)) { | 506 if (newInlineStyle->conflictsWithImplicitStyleOfElement(htmlElem
ent)) { |
| 507 // e.g. <b style="font-weight: normal;"> is converted to <sp
an style="font-weight: normal;"> | 507 // e.g. <b style="font-weight: normal;"> is converted to <sp
an style="font-weight: normal;"> |
| 508 element = replaceElementWithSpanPreservingChildrenAndAttribu
tes(htmlElement); | 508 element = replaceElementWithSpanPreservingChildrenAndAttribu
tes(htmlElement); |
| 509 inlineStyle = element->inlineStyle(); | 509 inlineStyle = element->inlineStyle(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 elements.add(theadTag.localName()); | 628 elements.add(theadTag.localName()); |
| 629 elements.add(trTag.localName()); | 629 elements.add(trTag.localName()); |
| 630 elements.add(ulTag.localName()); | 630 elements.add(ulTag.localName()); |
| 631 elements.add(xmpTag.localName()); | 631 elements.add(xmpTag.localName()); |
| 632 } | 632 } |
| 633 return elements.contains(name); | 633 return elements.contains(name); |
| 634 } | 634 } |
| 635 | 635 |
| 636 void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuild
er(const InsertedNodes& insertedNodes) | 636 void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuild
er(const InsertedNodes& insertedNodes) |
| 637 { | 637 { |
| 638 RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); | 638 RawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); |
| 639 RefPtrWillBeRawPtr<Node> next = nullptr; | 639 RawPtr<Node> next = nullptr; |
| 640 for (RefPtrWillBeRawPtr<Node> node = insertedNodes.firstNodeInserted(); node
&& node != pastEndNode; node = next) { | 640 for (RawPtr<Node> node = insertedNodes.firstNodeInserted(); node && node !=
pastEndNode; node = next) { |
| 641 next = NodeTraversal::next(*node); | 641 next = NodeTraversal::next(*node); |
| 642 | 642 |
| 643 if (!node->isHTMLElement()) | 643 if (!node->isHTMLElement()) |
| 644 continue; | 644 continue; |
| 645 // moveElementOutOfAncestor() in a previous iteration might have failed, | 645 // moveElementOutOfAncestor() in a previous iteration might have failed, |
| 646 // and |node| might have been detached from the document tree. | 646 // and |node| might have been detached from the document tree. |
| 647 if (!node->inDocument()) | 647 if (!node->inDocument()) |
| 648 continue; | 648 continue; |
| 649 | 649 |
| 650 HTMLElement& element = toHTMLElement(*node); | 650 HTMLElement& element = toHTMLElement(*node); |
| 651 if (isProhibitedParagraphChild(element.localName())) { | 651 if (isProhibitedParagraphChild(element.localName())) { |
| 652 if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWi
thTag(positionInParentBeforeNode(element), pTag))) | 652 if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWi
thTag(positionInParentBeforeNode(element), pTag))) |
| 653 moveElementOutOfAncestor(&element, paragraphElement); | 653 moveElementOutOfAncestor(&element, paragraphElement); |
| 654 } | 654 } |
| 655 | 655 |
| 656 if (isHTMLHeaderElement(&element)) { | 656 if (isHTMLHeaderElement(&element)) { |
| 657 if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeO
fType(positionInParentBeforeNode(element), isHTMLHeaderElement))) | 657 if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeO
fType(positionInParentBeforeNode(element), isHTMLHeaderElement))) |
| 658 moveElementOutOfAncestor(&element, headerElement); | 658 moveElementOutOfAncestor(&element, headerElement); |
| 659 } | 659 } |
| 660 } | 660 } |
| 661 } | 661 } |
| 662 | 662 |
| 663 void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<El
ement> prpElement, PassRefPtrWillBeRawPtr<Element> prpAncestor) | 663 void ReplaceSelectionCommand::moveElementOutOfAncestor(RawPtr<Element> prpElemen
t, RawPtr<Element> prpAncestor) |
| 664 { | 664 { |
| 665 RefPtrWillBeRawPtr<Element> element = prpElement; | 665 RawPtr<Element> element = prpElement; |
| 666 RefPtrWillBeRawPtr<Element> ancestor = prpAncestor; | 666 RawPtr<Element> ancestor = prpAncestor; |
| 667 | 667 |
| 668 if (!ancestor->parentNode()->hasEditableStyle()) | 668 if (!ancestor->parentNode()->hasEditableStyle()) |
| 669 return; | 669 return; |
| 670 | 670 |
| 671 VisiblePosition positionAtEndOfNode = createVisiblePosition(lastPositionInOr
AfterNode(element.get())); | 671 VisiblePosition positionAtEndOfNode = createVisiblePosition(lastPositionInOr
AfterNode(element.get())); |
| 672 VisiblePosition lastPositionInParagraph = createVisiblePosition(lastPosition
InNode(ancestor.get())); | 672 VisiblePosition lastPositionInParagraph = createVisiblePosition(lastPosition
InNode(ancestor.get())); |
| 673 if (positionAtEndOfNode.deepEquivalent() == lastPositionInParagraph.deepEqui
valent()) { | 673 if (positionAtEndOfNode.deepEquivalent() == lastPositionInParagraph.deepEqui
valent()) { |
| 674 removeNode(element); | 674 removeNode(element); |
| 675 if (ancestor->nextSibling()) | 675 if (ancestor->nextSibling()) |
| 676 insertNodeBefore(element, ancestor->nextSibling()); | 676 insertNodeBefore(element, ancestor->nextSibling()); |
| 677 else | 677 else |
| 678 appendNode(element, ancestor->parentNode()); | 678 appendNode(element, ancestor->parentNode()); |
| 679 } else { | 679 } else { |
| 680 RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(),
ancestor.get(), true); | 680 RawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(), ancestor.get
(), true); |
| 681 removeNode(element); | 681 removeNode(element); |
| 682 insertNodeBefore(element, nodeToSplitTo); | 682 insertNodeBefore(element, nodeToSplitTo); |
| 683 } | 683 } |
| 684 if (!ancestor->hasChildren()) | 684 if (!ancestor->hasChildren()) |
| 685 removeNode(ancestor.release()); | 685 removeNode(ancestor.release()); |
| 686 } | 686 } |
| 687 | 687 |
| 688 static inline bool nodeHasVisibleLayoutText(Text& text) | 688 static inline bool nodeHasVisibleLayoutText(Text& text) |
| 689 { | 689 { |
| 690 return text.layoutObject() && text.layoutObject()->resolvedTextLength() > 0; | 690 return text.layoutObject() && text.layoutObject()->resolvedTextLength() > 0; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 // and doesn't receive the optimization. | 750 // and doesn't receive the optimization. |
| 751 if (isMailPasteAsQuotationHTMLBlockQuoteElement(topNode) || enclosingNodeOfT
ype(firstPositionInOrBeforeNode(topNode), isMailHTMLBlockquoteElement, CanCrossE
ditingBoundary)) | 751 if (isMailPasteAsQuotationHTMLBlockQuoteElement(topNode) || enclosingNodeOfT
ype(firstPositionInOrBeforeNode(topNode), isMailHTMLBlockquoteElement, CanCrossE
ditingBoundary)) |
| 752 return false; | 752 return false; |
| 753 | 753 |
| 754 // Either there are no style spans in the fragment or a WebKit client has ad
ded content to the fragment | 754 // Either there are no style spans in the fragment or a WebKit client has ad
ded content to the fragment |
| 755 // before inserting it. Look for and handle style spans after insertion. | 755 // before inserting it. Look for and handle style spans after insertion. |
| 756 if (!isLegacyAppleHTMLSpanElement(topNode)) | 756 if (!isLegacyAppleHTMLSpanElement(topNode)) |
| 757 return false; | 757 return false; |
| 758 | 758 |
| 759 HTMLSpanElement* wrappingStyleSpan = toHTMLSpanElement(topNode); | 759 HTMLSpanElement* wrappingStyleSpan = toHTMLSpanElement(topNode); |
| 760 RefPtrWillBeRawPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(
insertionPos.parentAnchoredEquivalent()); | 760 RawPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(insertionPos
.parentAnchoredEquivalent()); |
| 761 String styleText = styleAtInsertionPos->style()->asText(); | 761 String styleText = styleAtInsertionPos->style()->asText(); |
| 762 | 762 |
| 763 // FIXME: This string comparison is a naive way of comparing two styles. | 763 // FIXME: This string comparison is a naive way of comparing two styles. |
| 764 // We should be taking the diff and check that the diff is empty. | 764 // We should be taking the diff and check that the diff is empty. |
| 765 if (styleText != wrappingStyleSpan->getAttribute(styleAttr)) | 765 if (styleText != wrappingStyleSpan->getAttribute(styleAttr)) |
| 766 return false; | 766 return false; |
| 767 | 767 |
| 768 fragment.removeNodePreservingChildren(wrappingStyleSpan); | 768 fragment.removeNodePreservingChildren(wrappingStyleSpan); |
| 769 return true; | 769 return true; |
| 770 } | 770 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 789 wrappingStyleSpan = toHTMLSpanElement(&node); | 789 wrappingStyleSpan = toHTMLSpanElement(&node); |
| 790 break; | 790 break; |
| 791 } | 791 } |
| 792 } | 792 } |
| 793 | 793 |
| 794 // There might not be any style spans if we're pasting from another applicat
ion or if | 794 // There might not be any style spans if we're pasting from another applicat
ion or if |
| 795 // we are here because of a document.execCommand("InsertHTML", ...) call. | 795 // we are here because of a document.execCommand("InsertHTML", ...) call. |
| 796 if (!wrappingStyleSpan) | 796 if (!wrappingStyleSpan) |
| 797 return; | 797 return; |
| 798 | 798 |
| 799 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(wrappingStyleS
pan->inlineStyle()); | 799 RawPtr<EditingStyle> style = EditingStyle::create(wrappingStyleSpan->inlineS
tyle()); |
| 800 ContainerNode* context = wrappingStyleSpan->parentNode(); | 800 ContainerNode* context = wrappingStyleSpan->parentNode(); |
| 801 | 801 |
| 802 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if yo
u're pasting into a quoted region, | 802 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if yo
u're pasting into a quoted region, |
| 803 // styles from blockquoteElement are allowed to override those from the sour
ce document, see <rdar://problem/4930986> and <rdar://problem/5089327>. | 803 // styles from blockquoteElement are allowed to override those from the sour
ce document, see <rdar://problem/4930986> and <rdar://problem/5089327>. |
| 804 HTMLQuoteElement* blockquoteElement = isMailPasteAsQuotationHTMLBlockQuoteEl
ement(context) ? | 804 HTMLQuoteElement* blockquoteElement = isMailPasteAsQuotationHTMLBlockQuoteEl
ement(context) ? |
| 805 toHTMLQuoteElement(context) : | 805 toHTMLQuoteElement(context) : |
| 806 toHTMLQuoteElement(enclosingNodeOfType(firstPositionInNode(context), isM
ailHTMLBlockquoteElement, CanCrossEditingBoundary)); | 806 toHTMLQuoteElement(enclosingNodeOfType(firstPositionInNode(context), isM
ailHTMLBlockquoteElement, CanCrossEditingBoundary)); |
| 807 if (blockquoteElement) | 807 if (blockquoteElement) |
| 808 context = document().documentElement(); | 808 context = document().documentElement(); |
| 809 | 809 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 844 // include the what was the start of the selection that was pasted into, so
that we preserve that paragraph's | 844 // include the what was the start of the selection that was pasted into, so
that we preserve that paragraph's |
| 845 // block styles. | 845 // block styles. |
| 846 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC
ontent) && !isStartOfParagraph(startOfInsertedContent)); | 846 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC
ontent) && !isStartOfParagraph(startOfInsertedContent)); |
| 847 | 847 |
| 848 VisiblePosition destination = mergeForward ? nextPositionOf(endOfInsertedCon
tent) : endOfInsertedContent; | 848 VisiblePosition destination = mergeForward ? nextPositionOf(endOfInsertedCon
tent) : endOfInsertedContent; |
| 849 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end
OfInsertedContent) : nextPositionOf(endOfInsertedContent); | 849 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end
OfInsertedContent) : nextPositionOf(endOfInsertedContent); |
| 850 | 850 |
| 851 // Merging forward could result in deleting the destination anchor node. | 851 // Merging forward could result in deleting the destination anchor node. |
| 852 // To avoid this, we add a placeholder node before the start of the paragrap
h. | 852 // To avoid this, we add a placeholder node before the start of the paragrap
h. |
| 853 if (endOfParagraph(startOfParagraphToMove).deepEquivalent() == destination.d
eepEquivalent()) { | 853 if (endOfParagraph(startOfParagraphToMove).deepEquivalent() == destination.d
eepEquivalent()) { |
| 854 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(do
cument()); | 854 RawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document()); |
| 855 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().an
chorNode()); | 855 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().an
chorNode()); |
| 856 destination = createVisiblePosition(positionBeforeNode(placeholder.get()
)); | 856 destination = createVisiblePosition(positionBeforeNode(placeholder.get()
)); |
| 857 } | 857 } |
| 858 | 858 |
| 859 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove)
, destination); | 859 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove)
, destination); |
| 860 | 860 |
| 861 // Merging forward will remove m_endOfInsertedContent from the document. | 861 // Merging forward will remove m_endOfInsertedContent from the document. |
| 862 if (mergeForward) { | 862 if (mergeForward) { |
| 863 if (m_startOfInsertedContent.isOrphan()) | 863 if (m_startOfInsertedContent.isOrphan()) |
| 864 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui
valent(); | 864 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui
valent(); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1024 return; | 1024 return; |
| 1025 | 1025 |
| 1026 // NOTE: This would be an incorrect usage of downstream() if downstream() we
re changed to mean the last position after | 1026 // NOTE: This would be an incorrect usage of downstream() if downstream() we
re changed to mean the last position after |
| 1027 // 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 | 1027 // 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 |
| 1028 // away, there are positions after the br which map to the same visible posi
tion as [br, 0]). | 1028 // away, there are positions after the br which map to the same visible posi
tion as [br, 0]). |
| 1029 HTMLBRElement* endBR = isHTMLBRElement(*mostForwardCaretPosition(insertionPo
s).anchorNode()) ? toHTMLBRElement(mostForwardCaretPosition(insertionPos).anchor
Node()) : 0; | 1029 HTMLBRElement* endBR = isHTMLBRElement(*mostForwardCaretPosition(insertionPo
s).anchorNode()) ? toHTMLBRElement(mostForwardCaretPosition(insertionPos).anchor
Node()) : 0; |
| 1030 VisiblePosition originalVisPosBeforeEndBR; | 1030 VisiblePosition originalVisPosBeforeEndBR; |
| 1031 if (endBR) | 1031 if (endBR) |
| 1032 originalVisPosBeforeEndBR = previousPositionOf(createVisiblePosition(pos
itionBeforeNode(endBR))); | 1032 originalVisPosBeforeEndBR = previousPositionOf(createVisiblePosition(pos
itionBeforeNode(endBR))); |
| 1033 | 1033 |
| 1034 RefPtrWillBeRawPtr<Element> enclosingBlockOfInsertionPos = enclosingBlock(in
sertionPos.anchorNode()); | 1034 RawPtr<Element> enclosingBlockOfInsertionPos = enclosingBlock(insertionPos.a
nchorNode()); |
| 1035 | 1035 |
| 1036 // Adjust insertionPos to prevent nesting. | 1036 // Adjust insertionPos to prevent nesting. |
| 1037 // If the start was in a Mail blockquote, we will have already handled adjus
ting insertionPos above. | 1037 // If the start was in a Mail blockquote, we will have already handled adjus
ting insertionPos above. |
| 1038 if (m_preventNesting && enclosingBlockOfInsertionPos && !isTableCell(enclosi
ngBlockOfInsertionPos.get()) && !startIsInsideMailBlockquote) { | 1038 if (m_preventNesting && enclosingBlockOfInsertionPos && !isTableCell(enclosi
ngBlockOfInsertionPos.get()) && !startIsInsideMailBlockquote) { |
| 1039 ASSERT(enclosingBlockOfInsertionPos != currentRoot); | 1039 ASSERT(enclosingBlockOfInsertionPos != currentRoot); |
| 1040 VisiblePosition visibleInsertionPos = createVisiblePosition(insertionPos
); | 1040 VisiblePosition visibleInsertionPos = createVisiblePosition(insertionPos
); |
| 1041 if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInserti
onPos) && fragment.hasInterchangeNewlineAtEnd())) | 1041 if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInserti
onPos) && fragment.hasInterchangeNewlineAtEnd())) |
| 1042 insertionPos = positionInParentAfterNode(*enclosingBlockOfInsertionP
os); | 1042 insertionPos = positionInParentAfterNode(*enclosingBlockOfInsertionP
os); |
| 1043 else if (isStartOfBlock(visibleInsertionPos)) | 1043 else if (isStartOfBlock(visibleInsertionPos)) |
| 1044 insertionPos = positionInParentBeforeNode(*enclosingBlockOfInsertion
Pos); | 1044 insertionPos = positionInParentBeforeNode(*enclosingBlockOfInsertion
Pos); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1073 // This way we can produce a less verbose markup. | 1073 // This way we can produce a less verbose markup. |
| 1074 // We can skip this optimization for fragments not wrapped in one of | 1074 // We can skip this optimization for fragments not wrapped in one of |
| 1075 // our style spans and for positions inside list items | 1075 // our style spans and for positions inside list items |
| 1076 // since insertAsListItems already does the right thing. | 1076 // since insertAsListItems already does the right thing. |
| 1077 if (!m_matchStyle && !enclosingList(insertionPos.computeContainerNode())) { | 1077 if (!m_matchStyle && !enclosingList(insertionPos.computeContainerNode())) { |
| 1078 if (insertionPos.computeContainerNode()->isTextNode() && insertionPos.of
fsetInContainerNode() && !insertionPos.atLastEditingPositionForNode()) { | 1078 if (insertionPos.computeContainerNode()->isTextNode() && insertionPos.of
fsetInContainerNode() && !insertionPos.atLastEditingPositionForNode()) { |
| 1079 splitTextNode(toText(insertionPos.computeContainerNode()), insertion
Pos.offsetInContainerNode()); | 1079 splitTextNode(toText(insertionPos.computeContainerNode()), insertion
Pos.offsetInContainerNode()); |
| 1080 insertionPos = firstPositionInNode(insertionPos.computeContainerNode
()); | 1080 insertionPos = firstPositionInNode(insertionPos.computeContainerNode
()); |
| 1081 } | 1081 } |
| 1082 | 1082 |
| 1083 if (RefPtrWillBeRawPtr<HTMLElement> elementToSplitTo = elementToSplitToA
voidPastingIntoInlineElementsWithStyle(insertionPos)) { | 1083 if (RawPtr<HTMLElement> elementToSplitTo = elementToSplitToAvoidPastingI
ntoInlineElementsWithStyle(insertionPos)) { |
| 1084 if (insertionPos.computeContainerNode() != elementToSplitTo->parentN
ode()) { | 1084 if (insertionPos.computeContainerNode() != elementToSplitTo->parentN
ode()) { |
| 1085 Node* splitStart = insertionPos.computeNodeAfterPosition(); | 1085 Node* splitStart = insertionPos.computeNodeAfterPosition(); |
| 1086 if (!splitStart) | 1086 if (!splitStart) |
| 1087 splitStart = insertionPos.computeContainerNode(); | 1087 splitStart = insertionPos.computeContainerNode(); |
| 1088 RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(splitSt
art, elementToSplitTo->parentNode()).get(); | 1088 RawPtr<Node> nodeToSplitTo = splitTreeToNode(splitStart, element
ToSplitTo->parentNode()).get(); |
| 1089 insertionPos = positionInParentBeforeNode(*nodeToSplitTo); | 1089 insertionPos = positionInParentBeforeNode(*nodeToSplitTo); |
| 1090 } | 1090 } |
| 1091 } | 1091 } |
| 1092 } | 1092 } |
| 1093 | 1093 |
| 1094 // FIXME: When pasting rich content we're often prevented from heading down
the fast path by style spans. Try | 1094 // FIXME: When pasting rich content we're often prevented from heading down
the fast path by style spans. Try |
| 1095 // again here if they've been removed. | 1095 // again here if they've been removed. |
| 1096 | 1096 |
| 1097 // 1) Insert the content. | 1097 // 1) Insert the content. |
| 1098 // 2) Remove redundant styles and style tags, this inner <b> for example: <b
>foo <b>bar</b> baz</b>. | 1098 // 2) Remove redundant styles and style tags, this inner <b> for example: <b
>foo <b>bar</b> baz</b>. |
| 1099 // 3) Merge the start of the added content with the content before the posit
ion being pasted into. | 1099 // 3) Merge the start of the added content with the content before the posit
ion being pasted into. |
| 1100 // 4) Do one of the following: a) expand the last br if the fragment ends wi
th one and it collapsed, | 1100 // 4) Do one of the following: a) expand the last br if the fragment ends wi
th one and it collapsed, |
| 1101 // b) merge the last paragraph of the incoming fragment with the paragraph t
hat contained the | 1101 // b) merge the last paragraph of the incoming fragment with the paragraph t
hat contained the |
| 1102 // end of the selection that was pasted into, or c) handle an interchange ne
wline at the end of the | 1102 // end of the selection that was pasted into, or c) handle an interchange ne
wline at the end of the |
| 1103 // incoming fragment. | 1103 // incoming fragment. |
| 1104 // 5) Add spaces for smart replace. | 1104 // 5) Add spaces for smart replace. |
| 1105 // 6) Select the replacement if requested, and match style if requested. | 1105 // 6) Select the replacement if requested, and match style if requested. |
| 1106 | 1106 |
| 1107 InsertedNodes insertedNodes; | 1107 InsertedNodes insertedNodes; |
| 1108 RefPtrWillBeRawPtr<Node> refNode = fragment.firstChild(); | 1108 RawPtr<Node> refNode = fragment.firstChild(); |
| 1109 ASSERT(refNode); | 1109 ASSERT(refNode); |
| 1110 RefPtrWillBeRawPtr<Node> node = refNode->nextSibling(); | 1110 RawPtr<Node> node = refNode->nextSibling(); |
| 1111 | 1111 |
| 1112 fragment.removeNode(refNode); | 1112 fragment.removeNode(refNode); |
| 1113 | 1113 |
| 1114 Element* blockStart = enclosingBlock(insertionPos.anchorNode()); | 1114 Element* blockStart = enclosingBlock(insertionPos.anchorNode()); |
| 1115 if ((isHTMLListElement(refNode.get()) || (isLegacyAppleHTMLSpanElement(refNo
de.get()) && isHTMLListElement(refNode->firstChild()))) | 1115 if ((isHTMLListElement(refNode.get()) || (isLegacyAppleHTMLSpanElement(refNo
de.get()) && isHTMLListElement(refNode->firstChild()))) |
| 1116 && blockStart && blockStart->layoutObject()->isListItem() && blockStart-
>parentNode()->hasEditableStyle()) { | 1116 && blockStart && blockStart->layoutObject()->isListItem() && blockStart-
>parentNode()->hasEditableStyle()) { |
| 1117 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio
nPos, insertedNodes); | 1117 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio
nPos, insertedNodes); |
| 1118 } else { | 1118 } else { |
| 1119 insertNodeAt(refNode, insertionPos); | 1119 insertNodeAt(refNode, insertionPos); |
| 1120 insertedNodes.respondToNodeInsertion(*refNode); | 1120 insertedNodes.respondToNodeInsertion(*refNode); |
| 1121 } | 1121 } |
| 1122 | 1122 |
| 1123 // Mutation events (bug 22634) may have already removed the inserted content | 1123 // Mutation events (bug 22634) may have already removed the inserted content |
| 1124 if (!refNode->inDocument()) | 1124 if (!refNode->inDocument()) |
| 1125 return; | 1125 return; |
| 1126 | 1126 |
| 1127 bool plainTextFragment = isPlainTextMarkup(refNode.get()); | 1127 bool plainTextFragment = isPlainTextMarkup(refNode.get()); |
| 1128 | 1128 |
| 1129 while (node) { | 1129 while (node) { |
| 1130 RefPtrWillBeRawPtr<Node> next = node->nextSibling(); | 1130 RawPtr<Node> next = node->nextSibling(); |
| 1131 fragment.removeNode(node.get()); | 1131 fragment.removeNode(node.get()); |
| 1132 insertNodeAfter(node, refNode); | 1132 insertNodeAfter(node, refNode); |
| 1133 insertedNodes.respondToNodeInsertion(*node); | 1133 insertedNodes.respondToNodeInsertion(*node); |
| 1134 | 1134 |
| 1135 // Mutation events (bug 22634) may have already removed the inserted con
tent | 1135 // Mutation events (bug 22634) may have already removed the inserted con
tent |
| 1136 if (!node->inDocument()) | 1136 if (!node->inDocument()) |
| 1137 return; | 1137 return; |
| 1138 | 1138 |
| 1139 refNode = node; | 1139 refNode = node; |
| 1140 if (node && plainTextFragment) | 1140 if (node && plainTextFragment) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1157 enclosingBlockOfInsertionPos = nullptr; | 1157 enclosingBlockOfInsertionPos = nullptr; |
| 1158 | 1158 |
| 1159 VisiblePosition startOfInsertedContent = createVisiblePosition(firstPosition
InOrBeforeNode(insertedNodes.firstNodeInserted())); | 1159 VisiblePosition startOfInsertedContent = createVisiblePosition(firstPosition
InOrBeforeNode(insertedNodes.firstNodeInserted())); |
| 1160 | 1160 |
| 1161 // We inserted before the enclosingBlockOfInsertionPos to prevent nesting, a
nd the content before the enclosingBlockOfInsertionPos wasn't in its own block a
nd | 1161 // We inserted before the enclosingBlockOfInsertionPos to prevent nesting, a
nd the content before the enclosingBlockOfInsertionPos wasn't in its own block a
nd |
| 1162 // didn't have a br after it, so the inserted content ended up in the same p
aragraph. | 1162 // didn't have a br after it, so the inserted content ended up in the same p
aragraph. |
| 1163 if (!startOfInsertedContent.isNull() && enclosingBlockOfInsertionPos && inse
rtionPos.anchorNode() == enclosingBlockOfInsertionPos->parentNode() && (unsigned
)insertionPos.computeEditingOffset() < enclosingBlockOfInsertionPos->nodeIndex()
&& !isStartOfParagraph(startOfInsertedContent)) | 1163 if (!startOfInsertedContent.isNull() && enclosingBlockOfInsertionPos && inse
rtionPos.anchorNode() == enclosingBlockOfInsertionPos->parentNode() && (unsigned
)insertionPos.computeEditingOffset() < enclosingBlockOfInsertionPos->nodeIndex()
&& !isStartOfParagraph(startOfInsertedContent)) |
| 1164 insertNodeAt(HTMLBRElement::create(document()).get(), startOfInsertedCon
tent.deepEquivalent()); | 1164 insertNodeAt(HTMLBRElement::create(document()).get(), startOfInsertedCon
tent.deepEquivalent()); |
| 1165 | 1165 |
| 1166 if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosB
eforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText))
)) { | 1166 if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosB
eforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText))
)) { |
| 1167 RefPtrWillBeRawPtr<ContainerNode> parent = endBR->parentNode(); | 1167 RawPtr<ContainerNode> parent = endBR->parentNode(); |
| 1168 insertedNodes.willRemoveNode(*endBR); | 1168 insertedNodes.willRemoveNode(*endBR); |
| 1169 removeNode(endBR); | 1169 removeNode(endBR); |
| 1170 if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) { | 1170 if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) { |
| 1171 insertedNodes.willRemoveNode(*nodeToRemove); | 1171 insertedNodes.willRemoveNode(*nodeToRemove); |
| 1172 removeNode(nodeToRemove); | 1172 removeNode(nodeToRemove); |
| 1173 } | 1173 } |
| 1174 } | 1174 } |
| 1175 | 1175 |
| 1176 makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes); | 1176 makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes); |
| 1177 | 1177 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1224 Position lastPositionToSelect; | 1224 Position lastPositionToSelect; |
| 1225 if (fragment.hasInterchangeNewlineAtEnd()) { | 1225 if (fragment.hasInterchangeNewlineAtEnd()) { |
| 1226 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); | 1226 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); |
| 1227 VisiblePosition next = nextPositionOf(endOfInsertedContent, CannotCrossE
ditingBoundary); | 1227 VisiblePosition next = nextPositionOf(endOfInsertedContent, CannotCrossE
ditingBoundary); |
| 1228 | 1228 |
| 1229 if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedCont
ent) || next.isNull()) { | 1229 if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedCont
ent) || next.isNull()) { |
| 1230 if (!isStartOfParagraph(endOfInsertedContent)) { | 1230 if (!isStartOfParagraph(endOfInsertedContent)) { |
| 1231 setEndingSelection(endOfInsertedContent); | 1231 setEndingSelection(endOfInsertedContent); |
| 1232 Element* enclosingBlockElement = enclosingBlock(endOfInsertedCon
tent.deepEquivalent().anchorNode()); | 1232 Element* enclosingBlockElement = enclosingBlock(endOfInsertedCon
tent.deepEquivalent().anchorNode()); |
| 1233 if (isListItem(enclosingBlockElement)) { | 1233 if (isListItem(enclosingBlockElement)) { |
| 1234 RefPtrWillBeRawPtr<HTMLLIElement> newListItem = HTMLLIElemen
t::create(document()); | 1234 RawPtr<HTMLLIElement> newListItem = HTMLLIElement::create(do
cument()); |
| 1235 insertNodeAfter(newListItem, enclosingBlockElement); | 1235 insertNodeAfter(newListItem, enclosingBlockElement); |
| 1236 setEndingSelection(createVisiblePosition(firstPositionInNode
(newListItem.get()))); | 1236 setEndingSelection(createVisiblePosition(firstPositionInNode
(newListItem.get()))); |
| 1237 } else { | 1237 } else { |
| 1238 // Use a default paragraph element (a plain div) for the emp
ty paragraph, using the last paragraph | 1238 // Use a default paragraph element (a plain div) for the emp
ty paragraph, using the last paragraph |
| 1239 // block's style seems to annoy users. | 1239 // block's style seems to annoy users. |
| 1240 insertParagraphSeparator(true, !startIsInsideMailBlockquote
&& highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(), | 1240 insertParagraphSeparator(true, !startIsInsideMailBlockquote
&& highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(), |
| 1241 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary,
insertedNodes.firstNodeInserted()->parentNode())); | 1241 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary,
insertedNodes.firstNodeInserted()->parentNode())); |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 // Select up to the paragraph separator that was added. | 1244 // Select up to the paragraph separator that was added. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1318 } | 1318 } |
| 1319 | 1319 |
| 1320 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar
acterSmartReplaceExemptConsideringNonBreakingSpace(characterAfter(endOfInsertedC
ontent), false); | 1320 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar
acterSmartReplaceExemptConsideringNonBreakingSpace(characterAfter(endOfInsertedC
ontent), false); |
| 1321 if (needsTrailingSpace && endNode) { | 1321 if (needsTrailingSpace && endNode) { |
| 1322 bool collapseWhiteSpace = !endNode->layoutObject() || endNode->layoutObj
ect()->style()->collapseWhiteSpace(); | 1322 bool collapseWhiteSpace = !endNode->layoutObject() || endNode->layoutObj
ect()->style()->collapseWhiteSpace(); |
| 1323 if (endNode->isTextNode()) { | 1323 if (endNode->isTextNode()) { |
| 1324 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ?
nonBreakingSpaceString() : " "); | 1324 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ?
nonBreakingSpaceString() : " "); |
| 1325 if (m_endOfInsertedContent.computeContainerNode() == endNode) | 1325 if (m_endOfInsertedContent.computeContainerNode() == endNode) |
| 1326 m_endOfInsertedContent = Position(endNode, m_endOfInsertedConten
t.offsetInContainerNode() + 1); | 1326 m_endOfInsertedContent = Position(endNode, m_endOfInsertedConten
t.offsetInContainerNode() + 1); |
| 1327 } else { | 1327 } else { |
| 1328 RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(col
lapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1328 RawPtr<Text> node = document().createEditingTextNode(collapseWhiteSp
ace ? nonBreakingSpaceString() : " "); |
| 1329 insertNodeAfter(node, endNode); | 1329 insertNodeAfter(node, endNode); |
| 1330 updateNodesInserted(node.get()); | 1330 updateNodesInserted(node.get()); |
| 1331 } | 1331 } |
| 1332 } | 1332 } |
| 1333 | 1333 |
| 1334 document().updateLayout(); | 1334 document().updateLayout(); |
| 1335 | 1335 |
| 1336 Position startDownstream = mostForwardCaretPosition(startOfInsertedContent.d
eepEquivalent()); | 1336 Position startDownstream = mostForwardCaretPosition(startOfInsertedContent.d
eepEquivalent()); |
| 1337 Node* startNode = startDownstream.computeNodeAfterPosition(); | 1337 Node* startNode = startDownstream.computeNodeAfterPosition(); |
| 1338 unsigned startOffset = 0; | 1338 unsigned startOffset = 0; |
| 1339 if (startDownstream.isOffsetInAnchor()) { | 1339 if (startDownstream.isOffsetInAnchor()) { |
| 1340 startNode = startDownstream.computeContainerNode(); | 1340 startNode = startDownstream.computeContainerNode(); |
| 1341 startOffset = startDownstream.offsetInContainerNode(); | 1341 startOffset = startDownstream.offsetInContainerNode(); |
| 1342 } | 1342 } |
| 1343 | 1343 |
| 1344 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC
haracterSmartReplaceExemptConsideringNonBreakingSpace(characterBefore(startOfIns
ertedContent), true); | 1344 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC
haracterSmartReplaceExemptConsideringNonBreakingSpace(characterBefore(startOfIns
ertedContent), true); |
| 1345 if (needsLeadingSpace && startNode) { | 1345 if (needsLeadingSpace && startNode) { |
| 1346 bool collapseWhiteSpace = !startNode->layoutObject() || startNode->layou
tObject()->style()->collapseWhiteSpace(); | 1346 bool collapseWhiteSpace = !startNode->layoutObject() || startNode->layou
tObject()->style()->collapseWhiteSpace(); |
| 1347 if (startNode->isTextNode()) { | 1347 if (startNode->isTextNode()) { |
| 1348 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac
e ? nonBreakingSpaceString() : " "); | 1348 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac
e ? nonBreakingSpaceString() : " "); |
| 1349 if (m_endOfInsertedContent.computeContainerNode() == startNode && m_
endOfInsertedContent.offsetInContainerNode()) | 1349 if (m_endOfInsertedContent.computeContainerNode() == startNode && m_
endOfInsertedContent.offsetInContainerNode()) |
| 1350 m_endOfInsertedContent = Position(startNode, m_endOfInsertedCont
ent.offsetInContainerNode() + 1); | 1350 m_endOfInsertedContent = Position(startNode, m_endOfInsertedCont
ent.offsetInContainerNode() + 1); |
| 1351 } else { | 1351 } else { |
| 1352 RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(col
lapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1352 RawPtr<Text> node = document().createEditingTextNode(collapseWhiteSp
ace ? nonBreakingSpaceString() : " "); |
| 1353 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont
ent to be the node containing the leading space, | 1353 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont
ent to be the node containing the leading space, |
| 1354 // but m_endOfInsertedContent is supposed to mark the end of pasted
content. | 1354 // but m_endOfInsertedContent is supposed to mark the end of pasted
content. |
| 1355 insertNodeBefore(node, startNode); | 1355 insertNodeBefore(node, startNode); |
| 1356 m_startOfInsertedContent = firstPositionInNode(node.get()); | 1356 m_startOfInsertedContent = firstPositionInNode(node.get()); |
| 1357 } | 1357 } |
| 1358 } | 1358 } |
| 1359 } | 1359 } |
| 1360 | 1360 |
| 1361 void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositi
onToSelect) | 1361 void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositi
onToSelect) |
| 1362 { | 1362 { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1390 if (m_selectReplacement) | 1390 if (m_selectReplacement) |
| 1391 setEndingSelection(VisibleSelection(start, end, SelDefaultAffinity, endi
ngSelection().isDirectional())); | 1391 setEndingSelection(VisibleSelection(start, end, SelDefaultAffinity, endi
ngSelection().isDirectional())); |
| 1392 else | 1392 else |
| 1393 setEndingSelection(VisibleSelection(end, SelDefaultAffinity, endingSelec
tion().isDirectional())); | 1393 setEndingSelection(VisibleSelection(end, SelDefaultAffinity, endingSelec
tion().isDirectional())); |
| 1394 } | 1394 } |
| 1395 | 1395 |
| 1396 void ReplaceSelectionCommand::mergeTextNodesAroundPosition(Position& position, P
osition& positionOnlyToBeUpdated) | 1396 void ReplaceSelectionCommand::mergeTextNodesAroundPosition(Position& position, P
osition& positionOnlyToBeUpdated) |
| 1397 { | 1397 { |
| 1398 bool positionIsOffsetInAnchor = position.isOffsetInAnchor(); | 1398 bool positionIsOffsetInAnchor = position.isOffsetInAnchor(); |
| 1399 bool positionOnlyToBeUpdatedIsOffsetInAnchor = positionOnlyToBeUpdated.isOff
setInAnchor(); | 1399 bool positionOnlyToBeUpdatedIsOffsetInAnchor = positionOnlyToBeUpdated.isOff
setInAnchor(); |
| 1400 RefPtrWillBeRawPtr<Text> text = nullptr; | 1400 RawPtr<Text> text = nullptr; |
| 1401 if (positionIsOffsetInAnchor && position.computeContainerNode() && position.
computeContainerNode()->isTextNode()) { | 1401 if (positionIsOffsetInAnchor && position.computeContainerNode() && position.
computeContainerNode()->isTextNode()) { |
| 1402 text = toText(position.computeContainerNode()); | 1402 text = toText(position.computeContainerNode()); |
| 1403 } else { | 1403 } else { |
| 1404 Node* before = position.computeNodeBeforePosition(); | 1404 Node* before = position.computeNodeBeforePosition(); |
| 1405 if (before && before->isTextNode()) { | 1405 if (before && before->isTextNode()) { |
| 1406 text = toText(before); | 1406 text = toText(before); |
| 1407 } else { | 1407 } else { |
| 1408 Node* after = position.computeNodeAfterPosition(); | 1408 Node* after = position.computeNodeAfterPosition(); |
| 1409 if (after && after->isTextNode()) | 1409 if (after && after->isTextNode()) |
| 1410 text = toText(after); | 1410 text = toText(after); |
| 1411 } | 1411 } |
| 1412 } | 1412 } |
| 1413 if (!text) | 1413 if (!text) |
| 1414 return; | 1414 return; |
| 1415 | 1415 |
| 1416 if (text->previousSibling() && text->previousSibling()->isTextNode()) { | 1416 if (text->previousSibling() && text->previousSibling()->isTextNode()) { |
| 1417 RefPtrWillBeRawPtr<Text> previous = toText(text->previousSibling()); | 1417 RawPtr<Text> previous = toText(text->previousSibling()); |
| 1418 insertTextIntoNode(text, 0, previous->data()); | 1418 insertTextIntoNode(text, 0, previous->data()); |
| 1419 | 1419 |
| 1420 if (positionIsOffsetInAnchor) | 1420 if (positionIsOffsetInAnchor) |
| 1421 position = Position(position.computeContainerNode(), previous->lengt
h() + position.offsetInContainerNode()); | 1421 position = Position(position.computeContainerNode(), previous->lengt
h() + position.offsetInContainerNode()); |
| 1422 else | 1422 else |
| 1423 updatePositionForNodeRemoval(position, *previous); | 1423 updatePositionForNodeRemoval(position, *previous); |
| 1424 | 1424 |
| 1425 if (positionOnlyToBeUpdatedIsOffsetInAnchor) { | 1425 if (positionOnlyToBeUpdatedIsOffsetInAnchor) { |
| 1426 if (positionOnlyToBeUpdated.computeContainerNode() == text) | 1426 if (positionOnlyToBeUpdated.computeContainerNode() == text) |
| 1427 positionOnlyToBeUpdated = Position(text, previous->length() + po
sitionOnlyToBeUpdated.offsetInContainerNode()); | 1427 positionOnlyToBeUpdated = Position(text, previous->length() + po
sitionOnlyToBeUpdated.offsetInContainerNode()); |
| 1428 else if (positionOnlyToBeUpdated.computeContainerNode() == previous) | 1428 else if (positionOnlyToBeUpdated.computeContainerNode() == previous) |
| 1429 positionOnlyToBeUpdated = Position(text, positionOnlyToBeUpdated
.offsetInContainerNode()); | 1429 positionOnlyToBeUpdated = Position(text, positionOnlyToBeUpdated
.offsetInContainerNode()); |
| 1430 } else { | 1430 } else { |
| 1431 updatePositionForNodeRemoval(positionOnlyToBeUpdated, *previous); | 1431 updatePositionForNodeRemoval(positionOnlyToBeUpdated, *previous); |
| 1432 } | 1432 } |
| 1433 | 1433 |
| 1434 removeNode(previous); | 1434 removeNode(previous); |
| 1435 } | 1435 } |
| 1436 if (text->nextSibling() && text->nextSibling()->isTextNode()) { | 1436 if (text->nextSibling() && text->nextSibling()->isTextNode()) { |
| 1437 RefPtrWillBeRawPtr<Text> next = toText(text->nextSibling()); | 1437 RawPtr<Text> next = toText(text->nextSibling()); |
| 1438 unsigned originalLength = text->length(); | 1438 unsigned originalLength = text->length(); |
| 1439 insertTextIntoNode(text, originalLength, next->data()); | 1439 insertTextIntoNode(text, originalLength, next->data()); |
| 1440 | 1440 |
| 1441 if (!positionIsOffsetInAnchor) | 1441 if (!positionIsOffsetInAnchor) |
| 1442 updatePositionForNodeRemoval(position, *next); | 1442 updatePositionForNodeRemoval(position, *next); |
| 1443 | 1443 |
| 1444 if (positionOnlyToBeUpdatedIsOffsetInAnchor && positionOnlyToBeUpdated.c
omputeContainerNode() == next) | 1444 if (positionOnlyToBeUpdatedIsOffsetInAnchor && positionOnlyToBeUpdated.c
omputeContainerNode() == next) |
| 1445 positionOnlyToBeUpdated = Position(text, originalLength + positionOn
lyToBeUpdated.offsetInContainerNode()); | 1445 positionOnlyToBeUpdated = Position(text, originalLength + positionOn
lyToBeUpdated.offsetInContainerNode()); |
| 1446 else | 1446 else |
| 1447 updatePositionForNodeRemoval(positionOnlyToBeUpdated, *next); | 1447 updatePositionForNodeRemoval(positionOnlyToBeUpdated, *next); |
| 1448 | 1448 |
| 1449 removeNode(next); | 1449 removeNode(next); |
| 1450 } | 1450 } |
| 1451 } | 1451 } |
| 1452 | 1452 |
| 1453 EditAction ReplaceSelectionCommand::editingAction() const | 1453 EditAction ReplaceSelectionCommand::editingAction() const |
| 1454 { | 1454 { |
| 1455 return m_editAction; | 1455 return m_editAction; |
| 1456 } | 1456 } |
| 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(RawPtr<HTMLElement> prpListElem
ent, Element* insertionBlock, const Position& insertPos, InsertedNodes& inserted
Nodes) |
| 1461 { | 1461 { |
| 1462 RefPtrWillBeRawPtr<HTMLElement> listElement = prpListElement; | 1462 RawPtr<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(createVisiblePosition(insertPos)); | 1467 bool isStart = isStartOfParagraph(createVisiblePosition(insertPos)); |
| 1468 bool isEnd = isEndOfParagraph(createVisiblePosition(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); |
| 1479 } | 1479 } |
| 1480 | 1480 |
| 1481 while (RefPtrWillBeRawPtr<Node> listItem = listElement->firstChild()) { | 1481 while (RawPtr<Node> listItem = listElement->firstChild()) { |
| 1482 listElement->removeChild(listItem.get(), ASSERT_NO_EXCEPTION); | 1482 listElement->removeChild(listItem.get(), ASSERT_NO_EXCEPTION); |
| 1483 if (isStart || isMiddle) { | 1483 if (isStart || isMiddle) { |
| 1484 insertNodeBefore(listItem, lastNode); | 1484 insertNodeBefore(listItem, lastNode); |
| 1485 insertedNodes.respondToNodeInsertion(*listItem); | 1485 insertedNodes.respondToNodeInsertion(*listItem); |
| 1486 } else if (isEnd) { | 1486 } else if (isEnd) { |
| 1487 insertNodeAfter(listItem, lastNode); | 1487 insertNodeAfter(listItem, lastNode); |
| 1488 insertedNodes.respondToNodeInsertion(*listItem); | 1488 insertedNodes.respondToNodeInsertion(*listItem); |
| 1489 lastNode = listItem.get(); | 1489 lastNode = listItem.get(); |
| 1490 } else { | 1490 } else { |
| 1491 ASSERT_NOT_REACHED(); | 1491 ASSERT_NOT_REACHED(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1519 return false; | 1519 return false; |
| 1520 | 1520 |
| 1521 // FIXME: Would be nice to handle smart replace in the fast path. | 1521 // FIXME: Would be nice to handle smart replace in the fast path. |
| 1522 if (m_smartReplace || fragment.hasInterchangeNewlineAtStart() || fragment.ha
sInterchangeNewlineAtEnd()) | 1522 if (m_smartReplace || fragment.hasInterchangeNewlineAtStart() || fragment.ha
sInterchangeNewlineAtEnd()) |
| 1523 return false; | 1523 return false; |
| 1524 | 1524 |
| 1525 // e.g. when "bar" is inserted after "foo" in <div><u>foo</u></div>, "bar" s
hould not be underlined. | 1525 // e.g. when "bar" is inserted after "foo" in <div><u>foo</u></div>, "bar" s
hould not be underlined. |
| 1526 if (elementToSplitToAvoidPastingIntoInlineElementsWithStyle(endingSelection(
).start())) | 1526 if (elementToSplitToAvoidPastingIntoInlineElementsWithStyle(endingSelection(
).start())) |
| 1527 return false; | 1527 return false; |
| 1528 | 1528 |
| 1529 RefPtrWillBeRawPtr<Node> nodeAfterInsertionPos = mostForwardCaretPosition(en
dingSelection().end()).anchorNode(); | 1529 RawPtr<Node> nodeAfterInsertionPos = mostForwardCaretPosition(endingSelectio
n().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()), creat
eVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) | 1539 && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), creat
eVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1564 visitor->trace(m_startOfInsertedContent); | 1564 visitor->trace(m_startOfInsertedContent); |
| 1565 visitor->trace(m_endOfInsertedContent); | 1565 visitor->trace(m_endOfInsertedContent); |
| 1566 visitor->trace(m_insertionStyle); | 1566 visitor->trace(m_insertionStyle); |
| 1567 visitor->trace(m_documentFragment); | 1567 visitor->trace(m_documentFragment); |
| 1568 visitor->trace(m_startOfInsertedRange); | 1568 visitor->trace(m_startOfInsertedRange); |
| 1569 visitor->trace(m_endOfInsertedRange); | 1569 visitor->trace(m_endOfInsertedRange); |
| 1570 CompositeEditCommand::trace(visitor); | 1570 CompositeEditCommand::trace(visitor); |
| 1571 } | 1571 } |
| 1572 | 1572 |
| 1573 } // namespace blink | 1573 } // namespace blink |
| OLD | NEW |