| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 ReplacementFragment(Document*, DocumentFragment*, const VisibleSelection&); | 77 ReplacementFragment(Document*, DocumentFragment*, const VisibleSelection&); |
| 78 | 78 |
| 79 Node* firstChild() const; | 79 Node* firstChild() const; |
| 80 Node* lastChild() const; | 80 Node* lastChild() const; |
| 81 | 81 |
| 82 bool isEmpty() const; | 82 bool isEmpty() const; |
| 83 | 83 |
| 84 bool hasInterchangeNewlineAtStart() const { return m_hasInterchangeNewlineAt
Start; } | 84 bool hasInterchangeNewlineAtStart() const { return m_hasInterchangeNewlineAt
Start; } |
| 85 bool hasInterchangeNewlineAtEnd() const { return m_hasInterchangeNewlineAtEn
d; } | 85 bool hasInterchangeNewlineAtEnd() const { return m_hasInterchangeNewlineAtEn
d; } |
| 86 | 86 |
| 87 void removeNode(PassRefPtrWillBeRawPtr<Node>); | 87 void removeNode(RawPtr<Node>); |
| 88 void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<ContainerNode>); | 88 void removeNodePreservingChildren(RawPtr<ContainerNode>); |
| 89 | 89 |
| 90 private: | 90 private: |
| 91 PassRefPtrWillBeRawPtr<HTMLElement> insertFragmentForTestRendering(Element*
rootEditableElement); | 91 RawPtr<HTMLElement> insertFragmentForTestRendering(Element* rootEditableElem
ent); |
| 92 void removeUnrenderedNodes(ContainerNode*); | 92 void removeUnrenderedNodes(ContainerNode*); |
| 93 void restoreAndRemoveTestRenderingNodesToFragment(Element*); | 93 void restoreAndRemoveTestRenderingNodesToFragment(Element*); |
| 94 void removeInterchangeNodes(ContainerNode*); | 94 void removeInterchangeNodes(ContainerNode*); |
| 95 | 95 |
| 96 void insertNodeBefore(PassRefPtrWillBeRawPtr<Node>, Node* refNode); | 96 void insertNodeBefore(RawPtr<Node>, Node* refNode); |
| 97 | 97 |
| 98 RefPtrWillBeMember<Document> m_document; | 98 Member<Document> m_document; |
| 99 RefPtrWillBeMember<DocumentFragment> m_fragment; | 99 Member<DocumentFragment> m_fragment; |
| 100 bool m_hasInterchangeNewlineAtStart; | 100 bool m_hasInterchangeNewlineAtStart; |
| 101 bool m_hasInterchangeNewlineAtEnd; | 101 bool m_hasInterchangeNewlineAtEnd; |
| 102 }; | 102 }; |
| 103 | 103 |
| 104 static bool isInterchangeHTMLBRElement(const Node* node) | 104 static bool isInterchangeHTMLBRElement(const Node* node) |
| 105 { | 105 { |
| 106 DEFINE_STATIC_LOCAL(String, interchangeNewlineClassString, (AppleInterchange
Newline)); | 106 DEFINE_STATIC_LOCAL(String, interchangeNewlineClassString, (AppleInterchange
Newline)); |
| 107 if (!isHTMLBRElement(node) || toHTMLBRElement(node)->getAttribute(classAttr)
!= interchangeNewlineClassString) | 107 if (!isHTMLBRElement(node) || toHTMLBRElement(node)->getAttribute(classAttr)
!= interchangeNewlineClassString) |
| 108 return false; | 108 return false; |
| 109 UseCounter::count(node->document(), UseCounter::EditingAppleInterchangeNewli
ne); | 109 UseCounter::count(node->document(), UseCounter::EditingAppleInterchangeNewli
ne); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 , m_fragment(fragment) | 150 , m_fragment(fragment) |
| 151 , m_hasInterchangeNewlineAtStart(false) | 151 , m_hasInterchangeNewlineAtStart(false) |
| 152 , m_hasInterchangeNewlineAtEnd(false) | 152 , m_hasInterchangeNewlineAtEnd(false) |
| 153 { | 153 { |
| 154 if (!m_document) | 154 if (!m_document) |
| 155 return; | 155 return; |
| 156 if (!m_fragment || !m_fragment->hasChildren()) | 156 if (!m_fragment || !m_fragment->hasChildren()) |
| 157 return; | 157 return; |
| 158 | 158 |
| 159 TRACE_EVENT0("blink", "ReplacementFragment constructor"); | 159 TRACE_EVENT0("blink", "ReplacementFragment constructor"); |
| 160 RefPtrWillBeRawPtr<Element> editableRoot = selection.rootEditableElement(); | 160 RawPtr<Element> editableRoot = selection.rootEditableElement(); |
| 161 ASSERT(editableRoot); | 161 ASSERT(editableRoot); |
| 162 if (!editableRoot) | 162 if (!editableRoot) |
| 163 return; | 163 return; |
| 164 | 164 |
| 165 Element* shadowAncestorElement; | 165 Element* shadowAncestorElement; |
| 166 if (editableRoot->isInShadowTree()) | 166 if (editableRoot->isInShadowTree()) |
| 167 shadowAncestorElement = editableRoot->shadowHost(); | 167 shadowAncestorElement = editableRoot->shadowHost(); |
| 168 else | 168 else |
| 169 shadowAncestorElement = editableRoot.get(); | 169 shadowAncestorElement = editableRoot.get(); |
| 170 | 170 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 183 continue; | 183 continue; |
| 184 if (!node.isTextNode()) { | 184 if (!node.isTextNode()) { |
| 185 isPlainText = false; | 185 isPlainText = false; |
| 186 break; | 186 break; |
| 187 } | 187 } |
| 188 } | 188 } |
| 189 // We don't need TestRendering for plain-text editing + plain-text inser
tion. | 189 // We don't need TestRendering for plain-text editing + plain-text inser
tion. |
| 190 if (isPlainText) { | 190 if (isPlainText) { |
| 191 removeInterchangeNodes(m_fragment.get()); | 191 removeInterchangeNodes(m_fragment.get()); |
| 192 String originalText = m_fragment->textContent(); | 192 String originalText = m_fragment->textContent(); |
| 193 RefPtrWillBeRawPtr<BeforeTextInsertedEvent> event = BeforeTextInsert
edEvent::create(originalText); | 193 RawPtr<BeforeTextInsertedEvent> event = BeforeTextInsertedEvent::cre
ate(originalText); |
| 194 editableRoot->dispatchEvent(event); | 194 editableRoot->dispatchEvent(event); |
| 195 if (originalText != event->text()) { | 195 if (originalText != event->text()) { |
| 196 m_fragment = createFragmentFromText(selection.toNormalizedEpheme
ralRange(), event->text()); | 196 m_fragment = createFragmentFromText(selection.toNormalizedEpheme
ralRange(), event->text()); |
| 197 removeInterchangeNodes(m_fragment.get()); | 197 removeInterchangeNodes(m_fragment.get()); |
| 198 } | 198 } |
| 199 return; | 199 return; |
| 200 } | 200 } |
| 201 } | 201 } |
| 202 | 202 |
| 203 RefPtrWillBeRawPtr<HTMLElement> holder = insertFragmentForTestRendering(edit
ableRoot.get()); | 203 RawPtr<HTMLElement> holder = insertFragmentForTestRendering(editableRoot.get
()); |
| 204 if (!holder) { | 204 if (!holder) { |
| 205 removeInterchangeNodes(m_fragment.get()); | 205 removeInterchangeNodes(m_fragment.get()); |
| 206 return; | 206 return; |
| 207 } | 207 } |
| 208 | 208 |
| 209 const EphemeralRange range = VisibleSelection::selectionFromContentsOfNode(h
older.get()).toNormalizedEphemeralRange(); | 209 const EphemeralRange range = VisibleSelection::selectionFromContentsOfNode(h
older.get()).toNormalizedEphemeralRange(); |
| 210 String text = plainText(range, static_cast<TextIteratorBehavior>(TextIterato
rEmitsOriginalText | TextIteratorIgnoresStyleVisibility)); | 210 String text = plainText(range, static_cast<TextIteratorBehavior>(TextIterato
rEmitsOriginalText | TextIteratorIgnoresStyleVisibility)); |
| 211 | 211 |
| 212 removeInterchangeNodes(holder.get()); | 212 removeInterchangeNodes(holder.get()); |
| 213 removeUnrenderedNodes(holder.get()); | 213 removeUnrenderedNodes(holder.get()); |
| 214 restoreAndRemoveTestRenderingNodesToFragment(holder.get()); | 214 restoreAndRemoveTestRenderingNodesToFragment(holder.get()); |
| 215 | 215 |
| 216 // Give the root a chance to change the text. | 216 // Give the root a chance to change the text. |
| 217 RefPtrWillBeRawPtr<BeforeTextInsertedEvent> evt = BeforeTextInsertedEvent::c
reate(text); | 217 RawPtr<BeforeTextInsertedEvent> evt = BeforeTextInsertedEvent::create(text); |
| 218 editableRoot->dispatchEvent(evt); | 218 editableRoot->dispatchEvent(evt); |
| 219 if (text != evt->text() || !editableRoot->layoutObjectIsRichlyEditable()) { | 219 if (text != evt->text() || !editableRoot->layoutObjectIsRichlyEditable()) { |
| 220 restoreAndRemoveTestRenderingNodesToFragment(holder.get()); | 220 restoreAndRemoveTestRenderingNodesToFragment(holder.get()); |
| 221 | 221 |
| 222 m_fragment = createFragmentFromText(selection.toNormalizedEphemeralRange
(), evt->text()); | 222 m_fragment = createFragmentFromText(selection.toNormalizedEphemeralRange
(), evt->text()); |
| 223 if (!m_fragment->hasChildren()) | 223 if (!m_fragment->hasChildren()) |
| 224 return; | 224 return; |
| 225 | 225 |
| 226 holder = insertFragmentForTestRendering(editableRoot.get()); | 226 holder = insertFragmentForTestRendering(editableRoot.get()); |
| 227 removeInterchangeNodes(holder.get()); | 227 removeInterchangeNodes(holder.get()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 238 Node* ReplacementFragment::firstChild() const | 238 Node* ReplacementFragment::firstChild() const |
| 239 { | 239 { |
| 240 return m_fragment ? m_fragment->firstChild() : 0; | 240 return m_fragment ? m_fragment->firstChild() : 0; |
| 241 } | 241 } |
| 242 | 242 |
| 243 Node* ReplacementFragment::lastChild() const | 243 Node* ReplacementFragment::lastChild() const |
| 244 { | 244 { |
| 245 return m_fragment ? m_fragment->lastChild() : 0; | 245 return m_fragment ? m_fragment->lastChild() : 0; |
| 246 } | 246 } |
| 247 | 247 |
| 248 void ReplacementFragment::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Co
ntainerNode> node) | 248 void ReplacementFragment::removeNodePreservingChildren(RawPtr<ContainerNode> nod
e) |
| 249 { | 249 { |
| 250 if (!node) | 250 if (!node) |
| 251 return; | 251 return; |
| 252 | 252 |
| 253 while (RefPtrWillBeRawPtr<Node> n = node->firstChild()) { | 253 while (RawPtr<Node> n = node->firstChild()) { |
| 254 removeNode(n); | 254 removeNode(n); |
| 255 insertNodeBefore(n.release(), node.get()); | 255 insertNodeBefore(n.release(), node.get()); |
| 256 } | 256 } |
| 257 removeNode(node); | 257 removeNode(node); |
| 258 } | 258 } |
| 259 | 259 |
| 260 void ReplacementFragment::removeNode(PassRefPtrWillBeRawPtr<Node> node) | 260 void ReplacementFragment::removeNode(RawPtr<Node> node) |
| 261 { | 261 { |
| 262 if (!node) | 262 if (!node) |
| 263 return; | 263 return; |
| 264 | 264 |
| 265 ContainerNode* parent = node->nonShadowBoundaryParentNode(); | 265 ContainerNode* parent = node->nonShadowBoundaryParentNode(); |
| 266 if (!parent) | 266 if (!parent) |
| 267 return; | 267 return; |
| 268 | 268 |
| 269 parent->removeChild(node.get()); | 269 parent->removeChild(node.get()); |
| 270 } | 270 } |
| 271 | 271 |
| 272 void ReplacementFragment::insertNodeBefore(PassRefPtrWillBeRawPtr<Node> node, No
de* refNode) | 272 void ReplacementFragment::insertNodeBefore(RawPtr<Node> node, Node* refNode) |
| 273 { | 273 { |
| 274 if (!node || !refNode) | 274 if (!node || !refNode) |
| 275 return; | 275 return; |
| 276 | 276 |
| 277 ContainerNode* parent = refNode->nonShadowBoundaryParentNode(); | 277 ContainerNode* parent = refNode->nonShadowBoundaryParentNode(); |
| 278 if (!parent) | 278 if (!parent) |
| 279 return; | 279 return; |
| 280 | 280 |
| 281 parent->insertBefore(node, refNode); | 281 parent->insertBefore(node, refNode); |
| 282 } | 282 } |
| 283 | 283 |
| 284 PassRefPtrWillBeRawPtr<HTMLElement> ReplacementFragment::insertFragmentForTestRe
ndering(Element* rootEditableElement) | 284 RawPtr<HTMLElement> ReplacementFragment::insertFragmentForTestRendering(Element*
rootEditableElement) |
| 285 { | 285 { |
| 286 TRACE_EVENT0("blink", "ReplacementFragment::insertFragmentForTestRendering")
; | 286 TRACE_EVENT0("blink", "ReplacementFragment::insertFragmentForTestRendering")
; |
| 287 ASSERT(m_document); | 287 ASSERT(m_document); |
| 288 RefPtrWillBeRawPtr<HTMLElement> holder = createDefaultParagraphElement(*m_do
cument.get()); | 288 RawPtr<HTMLElement> holder = createDefaultParagraphElement(*m_document.get()
); |
| 289 | 289 |
| 290 holder->appendChild(m_fragment); | 290 holder->appendChild(m_fragment); |
| 291 rootEditableElement->appendChild(holder.get()); | 291 rootEditableElement->appendChild(holder.get()); |
| 292 m_document->updateLayoutIgnorePendingStylesheets(); | 292 m_document->updateLayoutIgnorePendingStylesheets(); |
| 293 | 293 |
| 294 return holder.release(); | 294 return holder.release(); |
| 295 } | 295 } |
| 296 | 296 |
| 297 void ReplacementFragment::restoreAndRemoveTestRenderingNodesToFragment(Element*
holder) | 297 void ReplacementFragment::restoreAndRemoveTestRenderingNodesToFragment(Element*
holder) |
| 298 { | 298 { |
| 299 if (!holder) | 299 if (!holder) |
| 300 return; | 300 return; |
| 301 | 301 |
| 302 while (RefPtrWillBeRawPtr<Node> node = holder->firstChild()) { | 302 while (RawPtr<Node> node = holder->firstChild()) { |
| 303 holder->removeChild(node.get()); | 303 holder->removeChild(node.get()); |
| 304 m_fragment->appendChild(node.get()); | 304 m_fragment->appendChild(node.get()); |
| 305 } | 305 } |
| 306 | 306 |
| 307 removeNode(holder); | 307 removeNode(holder); |
| 308 } | 308 } |
| 309 | 309 |
| 310 void ReplacementFragment::removeUnrenderedNodes(ContainerNode* holder) | 310 void ReplacementFragment::removeUnrenderedNodes(ContainerNode* holder) |
| 311 { | 311 { |
| 312 WillBeHeapVector<RefPtrWillBeMember<Node>> unrendered; | 312 HeapVector<Member<Node>> unrendered; |
| 313 | 313 |
| 314 for (Node& node : NodeTraversal::descendantsOf(*holder)) { | 314 for (Node& node : NodeTraversal::descendantsOf(*holder)) { |
| 315 if (!isNodeRendered(node) && !isTableStructureNode(&node)) | 315 if (!isNodeRendered(node) && !isTableStructureNode(&node)) |
| 316 unrendered.append(&node); | 316 unrendered.append(&node); |
| 317 } | 317 } |
| 318 | 318 |
| 319 for (auto& node : unrendered) | 319 for (auto& node : unrendered) |
| 320 removeNode(node); | 320 removeNode(node); |
| 321 } | 321 } |
| 322 | 322 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 345 if (isInterchangeHTMLBRElement(node)) { | 345 if (isInterchangeHTMLBRElement(node)) { |
| 346 m_hasInterchangeNewlineAtEnd = true; | 346 m_hasInterchangeNewlineAtEnd = true; |
| 347 removeNode(node); | 347 removeNode(node); |
| 348 break; | 348 break; |
| 349 } | 349 } |
| 350 node = node->lastChild(); | 350 node = node->lastChild(); |
| 351 } | 351 } |
| 352 | 352 |
| 353 node = container->firstChild(); | 353 node = container->firstChild(); |
| 354 while (node) { | 354 while (node) { |
| 355 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*node); | 355 RawPtr<Node> next = NodeTraversal::next(*node); |
| 356 if (isHTMLInterchangeConvertedSpaceSpan(node)) { | 356 if (isHTMLInterchangeConvertedSpaceSpan(node)) { |
| 357 HTMLElement& element = toHTMLElement(*node); | 357 HTMLElement& element = toHTMLElement(*node); |
| 358 next = NodeTraversal::nextSkippingChildren(element); | 358 next = NodeTraversal::nextSkippingChildren(element); |
| 359 removeNodePreservingChildren(&element); | 359 removeNodePreservingChildren(&element); |
| 360 } | 360 } |
| 361 node = next.get(); | 361 node = next.get(); |
| 362 } | 362 } |
| 363 } | 363 } |
| 364 | 364 |
| 365 inline void ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion(Node&
node) | 365 inline void ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion(Node&
node) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 391 } | 391 } |
| 392 | 392 |
| 393 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(Node& node, N
ode& newNode) | 393 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(Node& node, N
ode& newNode) |
| 394 { | 394 { |
| 395 if (m_firstNodeInserted.get() == node) | 395 if (m_firstNodeInserted.get() == node) |
| 396 m_firstNodeInserted = &newNode; | 396 m_firstNodeInserted = &newNode; |
| 397 if (m_lastNodeInserted.get() == node) | 397 if (m_lastNodeInserted.get() == node) |
| 398 m_lastNodeInserted = &newNode; | 398 m_lastNodeInserted = &newNode; |
| 399 } | 399 } |
| 400 | 400 |
| 401 ReplaceSelectionCommand::ReplaceSelectionCommand(Document& document, PassRefPtrW
illBeRawPtr<DocumentFragment> fragment, CommandOptions options, EditAction editA
ction) | 401 ReplaceSelectionCommand::ReplaceSelectionCommand(Document& document, RawPtr<Docu
mentFragment> fragment, CommandOptions options, EditAction editAction) |
| 402 : CompositeEditCommand(document) | 402 : CompositeEditCommand(document) |
| 403 , m_selectReplacement(options & SelectReplacement) | 403 , m_selectReplacement(options & SelectReplacement) |
| 404 , m_smartReplace(options & SmartReplace) | 404 , m_smartReplace(options & SmartReplace) |
| 405 , m_matchStyle(options & MatchStyle) | 405 , m_matchStyle(options & MatchStyle) |
| 406 , m_documentFragment(fragment) | 406 , m_documentFragment(fragment) |
| 407 , m_preventNesting(options & PreventNesting) | 407 , m_preventNesting(options & PreventNesting) |
| 408 , m_movingParagraph(options & MovingParagraph) | 408 , m_movingParagraph(options & MovingParagraph) |
| 409 , m_editAction(editAction) | 409 , m_editAction(editAction) |
| 410 , m_sanitizeFragment(options & SanitizeFragment) | 410 , m_sanitizeFragment(options & SanitizeFragment) |
| 411 , m_shouldMergeEnd(false) | 411 , m_shouldMergeEnd(false) |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 && (!isHTMLHeaderElement(sourceBlock) || haveSameTagName(sourceBlock, de
stinationBlock)) | 504 && (!isHTMLHeaderElement(sourceBlock) || haveSameTagName(sourceBlock, de
stinationBlock)) |
| 505 // Don't merge to or from a position before or after a block because it
would | 505 // Don't merge to or from a position before or after a block because it
would |
| 506 // be a no-op and cause infinite recursion. | 506 // be a no-op and cause infinite recursion. |
| 507 && !isEnclosingBlock(sourceNode) && !isEnclosingBlock(destinationNode); | 507 && !isEnclosingBlock(sourceNode) && !isEnclosingBlock(destinationNode); |
| 508 } | 508 } |
| 509 | 509 |
| 510 // Style rules that match just inserted elements could change their appearance,
like | 510 // Style rules that match just inserted elements could change their appearance,
like |
| 511 // a div inserted into a document with div { display:inline; }. | 511 // a div inserted into a document with div { display:inline; }. |
| 512 void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert
edNodes& insertedNodes, EditingState* editingState) | 512 void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert
edNodes& insertedNodes, EditingState* editingState) |
| 513 { | 513 { |
| 514 RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); | 514 RawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); |
| 515 RefPtrWillBeRawPtr<Node> next = nullptr; | 515 RawPtr<Node> next = nullptr; |
| 516 for (RefPtrWillBeRawPtr<Node> node = insertedNodes.firstNodeInserted(); node
&& node != pastEndNode; node = next) { | 516 for (RawPtr<Node> node = insertedNodes.firstNodeInserted(); node && node !=
pastEndNode; node = next) { |
| 517 // FIXME: <rdar://problem/5371536> Style rules that match pasted content
can change it's appearance | 517 // FIXME: <rdar://problem/5371536> Style rules that match pasted content
can change it's appearance |
| 518 | 518 |
| 519 next = NodeTraversal::next(*node); | 519 next = NodeTraversal::next(*node); |
| 520 if (!node->isStyledElement()) | 520 if (!node->isStyledElement()) |
| 521 continue; | 521 continue; |
| 522 | 522 |
| 523 Element* element = toElement(node); | 523 Element* element = toElement(node); |
| 524 | 524 |
| 525 const StylePropertySet* inlineStyle = element->inlineStyle(); | 525 const StylePropertySet* inlineStyle = element->inlineStyle(); |
| 526 RefPtrWillBeRawPtr<EditingStyle> newInlineStyle = EditingStyle::create(i
nlineStyle); | 526 RawPtr<EditingStyle> newInlineStyle = EditingStyle::create(inlineStyle); |
| 527 if (inlineStyle) { | 527 if (inlineStyle) { |
| 528 if (element->isHTMLElement()) { | 528 if (element->isHTMLElement()) { |
| 529 Vector<QualifiedName> attributes; | 529 Vector<QualifiedName> attributes; |
| 530 HTMLElement* htmlElement = toHTMLElement(element); | 530 HTMLElement* htmlElement = toHTMLElement(element); |
| 531 ASSERT(htmlElement); | 531 ASSERT(htmlElement); |
| 532 | 532 |
| 533 if (newInlineStyle->conflictsWithImplicitStyleOfElement(htmlElem
ent)) { | 533 if (newInlineStyle->conflictsWithImplicitStyleOfElement(htmlElem
ent)) { |
| 534 // e.g. <b style="font-weight: normal;"> is converted to <sp
an style="font-weight: normal;"> | 534 // e.g. <b style="font-weight: normal;"> is converted to <sp
an style="font-weight: normal;"> |
| 535 element = replaceElementWithSpanPreservingChildrenAndAttribu
tes(htmlElement); | 535 element = replaceElementWithSpanPreservingChildrenAndAttribu
tes(htmlElement); |
| 536 inlineStyle = element->inlineStyle(); | 536 inlineStyle = element->inlineStyle(); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 elements.add(theadTag.localName()); | 661 elements.add(theadTag.localName()); |
| 662 elements.add(trTag.localName()); | 662 elements.add(trTag.localName()); |
| 663 elements.add(ulTag.localName()); | 663 elements.add(ulTag.localName()); |
| 664 elements.add(xmpTag.localName()); | 664 elements.add(xmpTag.localName()); |
| 665 } | 665 } |
| 666 return elements.contains(name); | 666 return elements.contains(name); |
| 667 } | 667 } |
| 668 | 668 |
| 669 void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuild
er(const InsertedNodes& insertedNodes, EditingState* editingState) | 669 void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuild
er(const InsertedNodes& insertedNodes, EditingState* editingState) |
| 670 { | 670 { |
| 671 RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); | 671 RawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); |
| 672 RefPtrWillBeRawPtr<Node> next = nullptr; | 672 RawPtr<Node> next = nullptr; |
| 673 for (RefPtrWillBeRawPtr<Node> node = insertedNodes.firstNodeInserted(); node
&& node != pastEndNode; node = next) { | 673 for (RawPtr<Node> node = insertedNodes.firstNodeInserted(); node && node !=
pastEndNode; node = next) { |
| 674 next = NodeTraversal::next(*node); | 674 next = NodeTraversal::next(*node); |
| 675 | 675 |
| 676 if (!node->isHTMLElement()) | 676 if (!node->isHTMLElement()) |
| 677 continue; | 677 continue; |
| 678 // moveElementOutOfAncestor() in a previous iteration might have failed, | 678 // moveElementOutOfAncestor() in a previous iteration might have failed, |
| 679 // and |node| might have been detached from the document tree. | 679 // and |node| might have been detached from the document tree. |
| 680 if (!node->inDocument()) | 680 if (!node->inDocument()) |
| 681 continue; | 681 continue; |
| 682 | 682 |
| 683 HTMLElement& element = toHTMLElement(*node); | 683 HTMLElement& element = toHTMLElement(*node); |
| 684 if (isProhibitedParagraphChild(element.localName())) { | 684 if (isProhibitedParagraphChild(element.localName())) { |
| 685 if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWi
thTag(positionInParentBeforeNode(element), pTag))) { | 685 if (HTMLElement* paragraphElement = toHTMLElement(enclosingElementWi
thTag(positionInParentBeforeNode(element), pTag))) { |
| 686 moveElementOutOfAncestor(&element, paragraphElement, editingStat
e); | 686 moveElementOutOfAncestor(&element, paragraphElement, editingStat
e); |
| 687 if (editingState->isAborted()) | 687 if (editingState->isAborted()) |
| 688 return; | 688 return; |
| 689 } | 689 } |
| 690 } | 690 } |
| 691 | 691 |
| 692 if (isHTMLHeaderElement(&element)) { | 692 if (isHTMLHeaderElement(&element)) { |
| 693 if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeO
fType(positionInParentBeforeNode(element), isHTMLHeaderElement))) { | 693 if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeO
fType(positionInParentBeforeNode(element), isHTMLHeaderElement))) { |
| 694 moveElementOutOfAncestor(&element, headerElement, editingState); | 694 moveElementOutOfAncestor(&element, headerElement, editingState); |
| 695 if (editingState->isAborted()) | 695 if (editingState->isAborted()) |
| 696 return; | 696 return; |
| 697 } | 697 } |
| 698 } | 698 } |
| 699 } | 699 } |
| 700 } | 700 } |
| 701 | 701 |
| 702 void ReplaceSelectionCommand::moveElementOutOfAncestor(PassRefPtrWillBeRawPtr<El
ement> prpElement, PassRefPtrWillBeRawPtr<Element> prpAncestor, EditingState* ed
itingState) | 702 void ReplaceSelectionCommand::moveElementOutOfAncestor(RawPtr<Element> prpElemen
t, RawPtr<Element> prpAncestor, EditingState* editingState) |
| 703 { | 703 { |
| 704 RefPtrWillBeRawPtr<Element> element = prpElement; | 704 RawPtr<Element> element = prpElement; |
| 705 RefPtrWillBeRawPtr<Element> ancestor = prpAncestor; | 705 RawPtr<Element> ancestor = prpAncestor; |
| 706 | 706 |
| 707 if (!ancestor->parentNode()->hasEditableStyle()) | 707 if (!ancestor->parentNode()->hasEditableStyle()) |
| 708 return; | 708 return; |
| 709 | 709 |
| 710 VisiblePosition positionAtEndOfNode = createVisiblePosition(lastPositionInOr
AfterNode(element.get())); | 710 VisiblePosition positionAtEndOfNode = createVisiblePosition(lastPositionInOr
AfterNode(element.get())); |
| 711 VisiblePosition lastPositionInParagraph = createVisiblePosition(lastPosition
InNode(ancestor.get())); | 711 VisiblePosition lastPositionInParagraph = createVisiblePosition(lastPosition
InNode(ancestor.get())); |
| 712 if (positionAtEndOfNode.deepEquivalent() == lastPositionInParagraph.deepEqui
valent()) { | 712 if (positionAtEndOfNode.deepEquivalent() == lastPositionInParagraph.deepEqui
valent()) { |
| 713 removeNode(element, editingState); | 713 removeNode(element, editingState); |
| 714 if (editingState->isAborted()) | 714 if (editingState->isAborted()) |
| 715 return; | 715 return; |
| 716 if (ancestor->nextSibling()) | 716 if (ancestor->nextSibling()) |
| 717 insertNodeBefore(element, ancestor->nextSibling(), editingState); | 717 insertNodeBefore(element, ancestor->nextSibling(), editingState); |
| 718 else | 718 else |
| 719 appendNode(element, ancestor->parentNode(), editingState); | 719 appendNode(element, ancestor->parentNode(), editingState); |
| 720 if (editingState->isAborted()) | 720 if (editingState->isAborted()) |
| 721 return; | 721 return; |
| 722 } else { | 722 } else { |
| 723 RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(),
ancestor.get(), true); | 723 RawPtr<Node> nodeToSplitTo = splitTreeToNode(element.get(), ancestor.get
(), true); |
| 724 removeNode(element, editingState); | 724 removeNode(element, editingState); |
| 725 if (editingState->isAborted()) | 725 if (editingState->isAborted()) |
| 726 return; | 726 return; |
| 727 insertNodeBefore(element, nodeToSplitTo, editingState); | 727 insertNodeBefore(element, nodeToSplitTo, editingState); |
| 728 if (editingState->isAborted()) | 728 if (editingState->isAborted()) |
| 729 return; | 729 return; |
| 730 } | 730 } |
| 731 if (!ancestor->hasChildren()) | 731 if (!ancestor->hasChildren()) |
| 732 removeNode(ancestor.release(), editingState); | 732 removeNode(ancestor.release(), editingState); |
| 733 } | 733 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 // and doesn't receive the optimization. | 799 // and doesn't receive the optimization. |
| 800 if (isMailPasteAsQuotationHTMLBlockQuoteElement(topNode) || enclosingNodeOfT
ype(firstPositionInOrBeforeNode(topNode), isMailHTMLBlockquoteElement, CanCrossE
ditingBoundary)) | 800 if (isMailPasteAsQuotationHTMLBlockQuoteElement(topNode) || enclosingNodeOfT
ype(firstPositionInOrBeforeNode(topNode), isMailHTMLBlockquoteElement, CanCrossE
ditingBoundary)) |
| 801 return false; | 801 return false; |
| 802 | 802 |
| 803 // Either there are no style spans in the fragment or a WebKit client has ad
ded content to the fragment | 803 // Either there are no style spans in the fragment or a WebKit client has ad
ded content to the fragment |
| 804 // before inserting it. Look for and handle style spans after insertion. | 804 // before inserting it. Look for and handle style spans after insertion. |
| 805 if (!isLegacyAppleHTMLSpanElement(topNode)) | 805 if (!isLegacyAppleHTMLSpanElement(topNode)) |
| 806 return false; | 806 return false; |
| 807 | 807 |
| 808 HTMLSpanElement* wrappingStyleSpan = toHTMLSpanElement(topNode); | 808 HTMLSpanElement* wrappingStyleSpan = toHTMLSpanElement(topNode); |
| 809 RefPtrWillBeRawPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(
insertionPos.parentAnchoredEquivalent()); | 809 RawPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(insertionPos
.parentAnchoredEquivalent()); |
| 810 String styleText = styleAtInsertionPos->style()->asText(); | 810 String styleText = styleAtInsertionPos->style()->asText(); |
| 811 | 811 |
| 812 // FIXME: This string comparison is a naive way of comparing two styles. | 812 // FIXME: This string comparison is a naive way of comparing two styles. |
| 813 // We should be taking the diff and check that the diff is empty. | 813 // We should be taking the diff and check that the diff is empty. |
| 814 if (styleText != wrappingStyleSpan->getAttribute(styleAttr)) | 814 if (styleText != wrappingStyleSpan->getAttribute(styleAttr)) |
| 815 return false; | 815 return false; |
| 816 | 816 |
| 817 fragment.removeNodePreservingChildren(wrappingStyleSpan); | 817 fragment.removeNodePreservingChildren(wrappingStyleSpan); |
| 818 return true; | 818 return true; |
| 819 } | 819 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 838 wrappingStyleSpan = toHTMLSpanElement(&node); | 838 wrappingStyleSpan = toHTMLSpanElement(&node); |
| 839 break; | 839 break; |
| 840 } | 840 } |
| 841 } | 841 } |
| 842 | 842 |
| 843 // There might not be any style spans if we're pasting from another applicat
ion or if | 843 // There might not be any style spans if we're pasting from another applicat
ion or if |
| 844 // we are here because of a document.execCommand("InsertHTML", ...) call. | 844 // we are here because of a document.execCommand("InsertHTML", ...) call. |
| 845 if (!wrappingStyleSpan) | 845 if (!wrappingStyleSpan) |
| 846 return; | 846 return; |
| 847 | 847 |
| 848 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(wrappingStyleS
pan->inlineStyle()); | 848 RawPtr<EditingStyle> style = EditingStyle::create(wrappingStyleSpan->inlineS
tyle()); |
| 849 ContainerNode* context = wrappingStyleSpan->parentNode(); | 849 ContainerNode* context = wrappingStyleSpan->parentNode(); |
| 850 | 850 |
| 851 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if yo
u're pasting into a quoted region, | 851 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if yo
u're pasting into a quoted region, |
| 852 // styles from blockquoteElement are allowed to override those from the sour
ce document, see <rdar://problem/4930986> and <rdar://problem/5089327>. | 852 // styles from blockquoteElement are allowed to override those from the sour
ce document, see <rdar://problem/4930986> and <rdar://problem/5089327>. |
| 853 HTMLQuoteElement* blockquoteElement = isMailPasteAsQuotationHTMLBlockQuoteEl
ement(context) ? | 853 HTMLQuoteElement* blockquoteElement = isMailPasteAsQuotationHTMLBlockQuoteEl
ement(context) ? |
| 854 toHTMLQuoteElement(context) : | 854 toHTMLQuoteElement(context) : |
| 855 toHTMLQuoteElement(enclosingNodeOfType(firstPositionInNode(context), isM
ailHTMLBlockquoteElement, CanCrossEditingBoundary)); | 855 toHTMLQuoteElement(enclosingNodeOfType(firstPositionInNode(context), isM
ailHTMLBlockquoteElement, CanCrossEditingBoundary)); |
| 856 if (blockquoteElement) | 856 if (blockquoteElement) |
| 857 context = document().documentElement(); | 857 context = document().documentElement(); |
| 858 | 858 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 // include the what was the start of the selection that was pasted into, so
that we preserve that paragraph's | 893 // include the what was the start of the selection that was pasted into, so
that we preserve that paragraph's |
| 894 // block styles. | 894 // block styles. |
| 895 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC
ontent) && !isStartOfParagraph(startOfInsertedContent)); | 895 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC
ontent) && !isStartOfParagraph(startOfInsertedContent)); |
| 896 | 896 |
| 897 VisiblePosition destination = mergeForward ? nextPositionOf(endOfInsertedCon
tent) : endOfInsertedContent; | 897 VisiblePosition destination = mergeForward ? nextPositionOf(endOfInsertedCon
tent) : endOfInsertedContent; |
| 898 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end
OfInsertedContent) : nextPositionOf(endOfInsertedContent); | 898 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end
OfInsertedContent) : nextPositionOf(endOfInsertedContent); |
| 899 | 899 |
| 900 // Merging forward could result in deleting the destination anchor node. | 900 // Merging forward could result in deleting the destination anchor node. |
| 901 // To avoid this, we add a placeholder node before the start of the paragrap
h. | 901 // To avoid this, we add a placeholder node before the start of the paragrap
h. |
| 902 if (endOfParagraph(startOfParagraphToMove).deepEquivalent() == destination.d
eepEquivalent()) { | 902 if (endOfParagraph(startOfParagraphToMove).deepEquivalent() == destination.d
eepEquivalent()) { |
| 903 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(do
cument()); | 903 RawPtr<HTMLBRElement> placeholder = HTMLBRElement::create(document()); |
| 904 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().an
chorNode(), editingState); | 904 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().an
chorNode(), editingState); |
| 905 if (editingState->isAborted()) | 905 if (editingState->isAborted()) |
| 906 return; | 906 return; |
| 907 destination = createVisiblePosition(positionBeforeNode(placeholder.get()
)); | 907 destination = createVisiblePosition(positionBeforeNode(placeholder.get()
)); |
| 908 } | 908 } |
| 909 | 909 |
| 910 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove)
, destination, editingState); | 910 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove)
, destination, editingState); |
| 911 if (editingState->isAborted()) | 911 if (editingState->isAborted()) |
| 912 return; | 912 return; |
| 913 | 913 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1093 return; | 1093 return; |
| 1094 | 1094 |
| 1095 // NOTE: This would be an incorrect usage of downstream() if downstream() we
re changed to mean the last position after | 1095 // NOTE: This would be an incorrect usage of downstream() if downstream() we
re changed to mean the last position after |
| 1096 // 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 | 1096 // 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 |
| 1097 // away, there are positions after the br which map to the same visible posi
tion as [br, 0]). | 1097 // away, there are positions after the br which map to the same visible posi
tion as [br, 0]). |
| 1098 HTMLBRElement* endBR = isHTMLBRElement(*mostForwardCaretPosition(insertionPo
s).anchorNode()) ? toHTMLBRElement(mostForwardCaretPosition(insertionPos).anchor
Node()) : 0; | 1098 HTMLBRElement* endBR = isHTMLBRElement(*mostForwardCaretPosition(insertionPo
s).anchorNode()) ? toHTMLBRElement(mostForwardCaretPosition(insertionPos).anchor
Node()) : 0; |
| 1099 VisiblePosition originalVisPosBeforeEndBR; | 1099 VisiblePosition originalVisPosBeforeEndBR; |
| 1100 if (endBR) | 1100 if (endBR) |
| 1101 originalVisPosBeforeEndBR = previousPositionOf(createVisiblePosition(pos
itionBeforeNode(endBR))); | 1101 originalVisPosBeforeEndBR = previousPositionOf(createVisiblePosition(pos
itionBeforeNode(endBR))); |
| 1102 | 1102 |
| 1103 RefPtrWillBeRawPtr<Element> enclosingBlockOfInsertionPos = enclosingBlock(in
sertionPos.anchorNode()); | 1103 RawPtr<Element> enclosingBlockOfInsertionPos = enclosingBlock(insertionPos.a
nchorNode()); |
| 1104 | 1104 |
| 1105 // Adjust insertionPos to prevent nesting. | 1105 // Adjust insertionPos to prevent nesting. |
| 1106 // If the start was in a Mail blockquote, we will have already handled adjus
ting insertionPos above. | 1106 // If the start was in a Mail blockquote, we will have already handled adjus
ting insertionPos above. |
| 1107 if (m_preventNesting && enclosingBlockOfInsertionPos && !isTableCell(enclosi
ngBlockOfInsertionPos.get()) && !startIsInsideMailBlockquote) { | 1107 if (m_preventNesting && enclosingBlockOfInsertionPos && !isTableCell(enclosi
ngBlockOfInsertionPos.get()) && !startIsInsideMailBlockquote) { |
| 1108 ASSERT(enclosingBlockOfInsertionPos != currentRoot); | 1108 ASSERT(enclosingBlockOfInsertionPos != currentRoot); |
| 1109 VisiblePosition visibleInsertionPos = createVisiblePosition(insertionPos
); | 1109 VisiblePosition visibleInsertionPos = createVisiblePosition(insertionPos
); |
| 1110 if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInserti
onPos) && fragment.hasInterchangeNewlineAtEnd())) | 1110 if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInserti
onPos) && fragment.hasInterchangeNewlineAtEnd())) |
| 1111 insertionPos = positionInParentAfterNode(*enclosingBlockOfInsertionP
os); | 1111 insertionPos = positionInParentAfterNode(*enclosingBlockOfInsertionP
os); |
| 1112 else if (isStartOfBlock(visibleInsertionPos)) | 1112 else if (isStartOfBlock(visibleInsertionPos)) |
| 1113 insertionPos = positionInParentBeforeNode(*enclosingBlockOfInsertion
Pos); | 1113 insertionPos = positionInParentBeforeNode(*enclosingBlockOfInsertion
Pos); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1144 // This way we can produce a less verbose markup. | 1144 // This way we can produce a less verbose markup. |
| 1145 // We can skip this optimization for fragments not wrapped in one of | 1145 // We can skip this optimization for fragments not wrapped in one of |
| 1146 // our style spans and for positions inside list items | 1146 // our style spans and for positions inside list items |
| 1147 // since insertAsListItems already does the right thing. | 1147 // since insertAsListItems already does the right thing. |
| 1148 if (!m_matchStyle && !enclosingList(insertionPos.computeContainerNode())) { | 1148 if (!m_matchStyle && !enclosingList(insertionPos.computeContainerNode())) { |
| 1149 if (insertionPos.computeContainerNode()->isTextNode() && insertionPos.of
fsetInContainerNode() && !insertionPos.atLastEditingPositionForNode()) { | 1149 if (insertionPos.computeContainerNode()->isTextNode() && insertionPos.of
fsetInContainerNode() && !insertionPos.atLastEditingPositionForNode()) { |
| 1150 splitTextNode(toText(insertionPos.computeContainerNode()), insertion
Pos.offsetInContainerNode()); | 1150 splitTextNode(toText(insertionPos.computeContainerNode()), insertion
Pos.offsetInContainerNode()); |
| 1151 insertionPos = firstPositionInNode(insertionPos.computeContainerNode
()); | 1151 insertionPos = firstPositionInNode(insertionPos.computeContainerNode
()); |
| 1152 } | 1152 } |
| 1153 | 1153 |
| 1154 if (RefPtrWillBeRawPtr<HTMLElement> elementToSplitTo = elementToSplitToA
voidPastingIntoInlineElementsWithStyle(insertionPos)) { | 1154 if (RawPtr<HTMLElement> elementToSplitTo = elementToSplitToAvoidPastingI
ntoInlineElementsWithStyle(insertionPos)) { |
| 1155 if (insertionPos.computeContainerNode() != elementToSplitTo->parentN
ode()) { | 1155 if (insertionPos.computeContainerNode() != elementToSplitTo->parentN
ode()) { |
| 1156 Node* splitStart = insertionPos.computeNodeAfterPosition(); | 1156 Node* splitStart = insertionPos.computeNodeAfterPosition(); |
| 1157 if (!splitStart) | 1157 if (!splitStart) |
| 1158 splitStart = insertionPos.computeContainerNode(); | 1158 splitStart = insertionPos.computeContainerNode(); |
| 1159 RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(splitSt
art, elementToSplitTo->parentNode()).get(); | 1159 RawPtr<Node> nodeToSplitTo = splitTreeToNode(splitStart, element
ToSplitTo->parentNode()).get(); |
| 1160 insertionPos = positionInParentBeforeNode(*nodeToSplitTo); | 1160 insertionPos = positionInParentBeforeNode(*nodeToSplitTo); |
| 1161 } | 1161 } |
| 1162 } | 1162 } |
| 1163 } | 1163 } |
| 1164 | 1164 |
| 1165 // FIXME: When pasting rich content we're often prevented from heading down
the fast path by style spans. Try | 1165 // FIXME: When pasting rich content we're often prevented from heading down
the fast path by style spans. Try |
| 1166 // again here if they've been removed. | 1166 // again here if they've been removed. |
| 1167 | 1167 |
| 1168 // 1) Insert the content. | 1168 // 1) Insert the content. |
| 1169 // 2) Remove redundant styles and style tags, this inner <b> for example: <b
>foo <b>bar</b> baz</b>. | 1169 // 2) Remove redundant styles and style tags, this inner <b> for example: <b
>foo <b>bar</b> baz</b>. |
| 1170 // 3) Merge the start of the added content with the content before the posit
ion being pasted into. | 1170 // 3) Merge the start of the added content with the content before the posit
ion being pasted into. |
| 1171 // 4) Do one of the following: a) expand the last br if the fragment ends wi
th one and it collapsed, | 1171 // 4) Do one of the following: a) expand the last br if the fragment ends wi
th one and it collapsed, |
| 1172 // b) merge the last paragraph of the incoming fragment with the paragraph t
hat contained the | 1172 // b) merge the last paragraph of the incoming fragment with the paragraph t
hat contained the |
| 1173 // end of the selection that was pasted into, or c) handle an interchange ne
wline at the end of the | 1173 // end of the selection that was pasted into, or c) handle an interchange ne
wline at the end of the |
| 1174 // incoming fragment. | 1174 // incoming fragment. |
| 1175 // 5) Add spaces for smart replace. | 1175 // 5) Add spaces for smart replace. |
| 1176 // 6) Select the replacement if requested, and match style if requested. | 1176 // 6) Select the replacement if requested, and match style if requested. |
| 1177 | 1177 |
| 1178 InsertedNodes insertedNodes; | 1178 InsertedNodes insertedNodes; |
| 1179 RefPtrWillBeRawPtr<Node> refNode = fragment.firstChild(); | 1179 RawPtr<Node> refNode = fragment.firstChild(); |
| 1180 ASSERT(refNode); | 1180 ASSERT(refNode); |
| 1181 RefPtrWillBeRawPtr<Node> node = refNode->nextSibling(); | 1181 RawPtr<Node> node = refNode->nextSibling(); |
| 1182 | 1182 |
| 1183 fragment.removeNode(refNode); | 1183 fragment.removeNode(refNode); |
| 1184 | 1184 |
| 1185 Element* blockStart = enclosingBlock(insertionPos.anchorNode()); | 1185 Element* blockStart = enclosingBlock(insertionPos.anchorNode()); |
| 1186 if ((isHTMLListElement(refNode.get()) || (isLegacyAppleHTMLSpanElement(refNo
de.get()) && isHTMLListElement(refNode->firstChild()))) | 1186 if ((isHTMLListElement(refNode.get()) || (isLegacyAppleHTMLSpanElement(refNo
de.get()) && isHTMLListElement(refNode->firstChild()))) |
| 1187 && blockStart && blockStart->layoutObject()->isListItem() && blockStart-
>parentNode()->hasEditableStyle()) { | 1187 && blockStart && blockStart->layoutObject()->isListItem() && blockStart-
>parentNode()->hasEditableStyle()) { |
| 1188 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio
nPos, insertedNodes, editingState); | 1188 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio
nPos, insertedNodes, editingState); |
| 1189 if (editingState->isAborted()) | 1189 if (editingState->isAborted()) |
| 1190 return; | 1190 return; |
| 1191 } else { | 1191 } else { |
| 1192 insertNodeAt(refNode, insertionPos, editingState); | 1192 insertNodeAt(refNode, insertionPos, editingState); |
| 1193 if (editingState->isAborted()) | 1193 if (editingState->isAborted()) |
| 1194 return; | 1194 return; |
| 1195 insertedNodes.respondToNodeInsertion(*refNode); | 1195 insertedNodes.respondToNodeInsertion(*refNode); |
| 1196 } | 1196 } |
| 1197 | 1197 |
| 1198 // Mutation events (bug 22634) may have already removed the inserted content | 1198 // Mutation events (bug 22634) may have already removed the inserted content |
| 1199 if (!refNode->inDocument()) | 1199 if (!refNode->inDocument()) |
| 1200 return; | 1200 return; |
| 1201 | 1201 |
| 1202 bool plainTextFragment = isPlainTextMarkup(refNode.get()); | 1202 bool plainTextFragment = isPlainTextMarkup(refNode.get()); |
| 1203 | 1203 |
| 1204 while (node) { | 1204 while (node) { |
| 1205 RefPtrWillBeRawPtr<Node> next = node->nextSibling(); | 1205 RawPtr<Node> next = node->nextSibling(); |
| 1206 fragment.removeNode(node.get()); | 1206 fragment.removeNode(node.get()); |
| 1207 insertNodeAfter(node, refNode, editingState); | 1207 insertNodeAfter(node, refNode, editingState); |
| 1208 if (editingState->isAborted()) | 1208 if (editingState->isAborted()) |
| 1209 return; | 1209 return; |
| 1210 insertedNodes.respondToNodeInsertion(*node); | 1210 insertedNodes.respondToNodeInsertion(*node); |
| 1211 | 1211 |
| 1212 // Mutation events (bug 22634) may have already removed the inserted con
tent | 1212 // Mutation events (bug 22634) may have already removed the inserted con
tent |
| 1213 if (!node->inDocument()) | 1213 if (!node->inDocument()) |
| 1214 return; | 1214 return; |
| 1215 | 1215 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1241 | 1241 |
| 1242 // We inserted before the enclosingBlockOfInsertionPos to prevent nesting, a
nd the content before the enclosingBlockOfInsertionPos wasn't in its own block a
nd | 1242 // We inserted before the enclosingBlockOfInsertionPos to prevent nesting, a
nd the content before the enclosingBlockOfInsertionPos wasn't in its own block a
nd |
| 1243 // didn't have a br after it, so the inserted content ended up in the same p
aragraph. | 1243 // didn't have a br after it, so the inserted content ended up in the same p
aragraph. |
| 1244 if (!startOfInsertedContent.isNull() && enclosingBlockOfInsertionPos && inse
rtionPos.anchorNode() == enclosingBlockOfInsertionPos->parentNode() && (unsigned
)insertionPos.computeEditingOffset() < enclosingBlockOfInsertionPos->nodeIndex()
&& !isStartOfParagraph(startOfInsertedContent)) { | 1244 if (!startOfInsertedContent.isNull() && enclosingBlockOfInsertionPos && inse
rtionPos.anchorNode() == enclosingBlockOfInsertionPos->parentNode() && (unsigned
)insertionPos.computeEditingOffset() < enclosingBlockOfInsertionPos->nodeIndex()
&& !isStartOfParagraph(startOfInsertedContent)) { |
| 1245 insertNodeAt(HTMLBRElement::create(document()).get(), startOfInsertedCon
tent.deepEquivalent(), editingState); | 1245 insertNodeAt(HTMLBRElement::create(document()).get(), startOfInsertedCon
tent.deepEquivalent(), editingState); |
| 1246 if (editingState->isAborted()) | 1246 if (editingState->isAborted()) |
| 1247 return; | 1247 return; |
| 1248 } | 1248 } |
| 1249 | 1249 |
| 1250 if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosB
eforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText))
)) { | 1250 if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosB
eforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText))
)) { |
| 1251 RefPtrWillBeRawPtr<ContainerNode> parent = endBR->parentNode(); | 1251 RawPtr<ContainerNode> parent = endBR->parentNode(); |
| 1252 insertedNodes.willRemoveNode(*endBR); | 1252 insertedNodes.willRemoveNode(*endBR); |
| 1253 removeNode(endBR, editingState); | 1253 removeNode(endBR, editingState); |
| 1254 if (editingState->isAborted()) | 1254 if (editingState->isAborted()) |
| 1255 return; | 1255 return; |
| 1256 if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) { | 1256 if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) { |
| 1257 insertedNodes.willRemoveNode(*nodeToRemove); | 1257 insertedNodes.willRemoveNode(*nodeToRemove); |
| 1258 removeNode(nodeToRemove, editingState); | 1258 removeNode(nodeToRemove, editingState); |
| 1259 if (editingState->isAborted()) | 1259 if (editingState->isAborted()) |
| 1260 return; | 1260 return; |
| 1261 } | 1261 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 if (editingState->isAborted()) | 1335 if (editingState->isAborted()) |
| 1336 return; | 1336 return; |
| 1337 } | 1337 } |
| 1338 setEndingSelection(createVisiblePosition(positionAfterNode(inser
tedNodes.lastLeafInserted()))); | 1338 setEndingSelection(createVisiblePosition(positionAfterNode(inser
tedNodes.lastLeafInserted()))); |
| 1339 // Select up to the paragraph separator that was added. | 1339 // Select up to the paragraph separator that was added. |
| 1340 lastPositionToSelect = endingSelection().visibleStart().deepEqui
valent(); | 1340 lastPositionToSelect = endingSelection().visibleStart().deepEqui
valent(); |
| 1341 } else if (!isStartOfParagraph(endOfInsertedContent)) { | 1341 } else if (!isStartOfParagraph(endOfInsertedContent)) { |
| 1342 setEndingSelection(endOfInsertedContent); | 1342 setEndingSelection(endOfInsertedContent); |
| 1343 Element* enclosingBlockElement = enclosingBlock(endOfInsertedCon
tent.deepEquivalent().anchorNode()); | 1343 Element* enclosingBlockElement = enclosingBlock(endOfInsertedCon
tent.deepEquivalent().anchorNode()); |
| 1344 if (isListItem(enclosingBlockElement)) { | 1344 if (isListItem(enclosingBlockElement)) { |
| 1345 RefPtrWillBeRawPtr<HTMLLIElement> newListItem = HTMLLIElemen
t::create(document()); | 1345 RawPtr<HTMLLIElement> newListItem = HTMLLIElement::create(do
cument()); |
| 1346 insertNodeAfter(newListItem, enclosingBlockElement, editingS
tate); | 1346 insertNodeAfter(newListItem, enclosingBlockElement, editingS
tate); |
| 1347 if (editingState->isAborted()) | 1347 if (editingState->isAborted()) |
| 1348 return; | 1348 return; |
| 1349 setEndingSelection(createVisiblePosition(firstPositionInNode
(newListItem.get()))); | 1349 setEndingSelection(createVisiblePosition(firstPositionInNode
(newListItem.get()))); |
| 1350 } else { | 1350 } else { |
| 1351 // Use a default paragraph element (a plain div) for the emp
ty paragraph, using the last paragraph | 1351 // Use a default paragraph element (a plain div) for the emp
ty paragraph, using the last paragraph |
| 1352 // block's style seems to annoy users. | 1352 // block's style seems to annoy users. |
| 1353 insertParagraphSeparator(editingState, true, !startIsInsideM
ailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(
), | 1353 insertParagraphSeparator(editingState, true, !startIsInsideM
ailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(
), |
| 1354 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary,
insertedNodes.firstNodeInserted()->parentNode())); | 1354 isMailHTMLBlockquoteElement, CannotCrossEditingBoundary,
insertedNodes.firstNodeInserted()->parentNode())); |
| 1355 if (editingState->isAborted()) | 1355 if (editingState->isAborted()) |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 } | 1438 } |
| 1439 | 1439 |
| 1440 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar
acterSmartReplaceExemptConsideringNonBreakingSpace(characterAfter(endOfInsertedC
ontent), false); | 1440 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar
acterSmartReplaceExemptConsideringNonBreakingSpace(characterAfter(endOfInsertedC
ontent), false); |
| 1441 if (needsTrailingSpace && endNode) { | 1441 if (needsTrailingSpace && endNode) { |
| 1442 bool collapseWhiteSpace = !endNode->layoutObject() || endNode->layoutObj
ect()->style()->collapseWhiteSpace(); | 1442 bool collapseWhiteSpace = !endNode->layoutObject() || endNode->layoutObj
ect()->style()->collapseWhiteSpace(); |
| 1443 if (endNode->isTextNode()) { | 1443 if (endNode->isTextNode()) { |
| 1444 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ?
nonBreakingSpaceString() : " "); | 1444 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ?
nonBreakingSpaceString() : " "); |
| 1445 if (m_endOfInsertedContent.computeContainerNode() == endNode) | 1445 if (m_endOfInsertedContent.computeContainerNode() == endNode) |
| 1446 m_endOfInsertedContent = Position(endNode, m_endOfInsertedConten
t.offsetInContainerNode() + 1); | 1446 m_endOfInsertedContent = Position(endNode, m_endOfInsertedConten
t.offsetInContainerNode() + 1); |
| 1447 } else { | 1447 } else { |
| 1448 RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(col
lapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1448 RawPtr<Text> node = document().createEditingTextNode(collapseWhiteSp
ace ? nonBreakingSpaceString() : " "); |
| 1449 insertNodeAfter(node, endNode, editingState); | 1449 insertNodeAfter(node, endNode, editingState); |
| 1450 if (editingState->isAborted()) | 1450 if (editingState->isAborted()) |
| 1451 return; | 1451 return; |
| 1452 updateNodesInserted(node.get()); | 1452 updateNodesInserted(node.get()); |
| 1453 } | 1453 } |
| 1454 } | 1454 } |
| 1455 | 1455 |
| 1456 document().updateLayout(); | 1456 document().updateLayout(); |
| 1457 | 1457 |
| 1458 Position startDownstream = mostForwardCaretPosition(startOfInsertedContent.d
eepEquivalent()); | 1458 Position startDownstream = mostForwardCaretPosition(startOfInsertedContent.d
eepEquivalent()); |
| 1459 Node* startNode = startDownstream.computeNodeAfterPosition(); | 1459 Node* startNode = startDownstream.computeNodeAfterPosition(); |
| 1460 unsigned startOffset = 0; | 1460 unsigned startOffset = 0; |
| 1461 if (startDownstream.isOffsetInAnchor()) { | 1461 if (startDownstream.isOffsetInAnchor()) { |
| 1462 startNode = startDownstream.computeContainerNode(); | 1462 startNode = startDownstream.computeContainerNode(); |
| 1463 startOffset = startDownstream.offsetInContainerNode(); | 1463 startOffset = startDownstream.offsetInContainerNode(); |
| 1464 } | 1464 } |
| 1465 | 1465 |
| 1466 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC
haracterSmartReplaceExemptConsideringNonBreakingSpace(characterBefore(startOfIns
ertedContent), true); | 1466 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC
haracterSmartReplaceExemptConsideringNonBreakingSpace(characterBefore(startOfIns
ertedContent), true); |
| 1467 if (needsLeadingSpace && startNode) { | 1467 if (needsLeadingSpace && startNode) { |
| 1468 bool collapseWhiteSpace = !startNode->layoutObject() || startNode->layou
tObject()->style()->collapseWhiteSpace(); | 1468 bool collapseWhiteSpace = !startNode->layoutObject() || startNode->layou
tObject()->style()->collapseWhiteSpace(); |
| 1469 if (startNode->isTextNode()) { | 1469 if (startNode->isTextNode()) { |
| 1470 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac
e ? nonBreakingSpaceString() : " "); | 1470 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac
e ? nonBreakingSpaceString() : " "); |
| 1471 if (m_endOfInsertedContent.computeContainerNode() == startNode && m_
endOfInsertedContent.offsetInContainerNode()) | 1471 if (m_endOfInsertedContent.computeContainerNode() == startNode && m_
endOfInsertedContent.offsetInContainerNode()) |
| 1472 m_endOfInsertedContent = Position(startNode, m_endOfInsertedCont
ent.offsetInContainerNode() + 1); | 1472 m_endOfInsertedContent = Position(startNode, m_endOfInsertedCont
ent.offsetInContainerNode() + 1); |
| 1473 } else { | 1473 } else { |
| 1474 RefPtrWillBeRawPtr<Text> node = document().createEditingTextNode(col
lapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1474 RawPtr<Text> node = document().createEditingTextNode(collapseWhiteSp
ace ? nonBreakingSpaceString() : " "); |
| 1475 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont
ent to be the node containing the leading space, | 1475 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont
ent to be the node containing the leading space, |
| 1476 // but m_endOfInsertedContent is supposed to mark the end of pasted
content. | 1476 // but m_endOfInsertedContent is supposed to mark the end of pasted
content. |
| 1477 insertNodeBefore(node, startNode, editingState); | 1477 insertNodeBefore(node, startNode, editingState); |
| 1478 if (editingState->isAborted()) | 1478 if (editingState->isAborted()) |
| 1479 return; | 1479 return; |
| 1480 m_startOfInsertedContent = firstPositionInNode(node.get()); | 1480 m_startOfInsertedContent = firstPositionInNode(node.get()); |
| 1481 } | 1481 } |
| 1482 } | 1482 } |
| 1483 } | 1483 } |
| 1484 | 1484 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1518 if (m_selectReplacement) | 1518 if (m_selectReplacement) |
| 1519 setEndingSelection(VisibleSelection(start, end, SelDefaultAffinity, endi
ngSelection().isDirectional())); | 1519 setEndingSelection(VisibleSelection(start, end, SelDefaultAffinity, endi
ngSelection().isDirectional())); |
| 1520 else | 1520 else |
| 1521 setEndingSelection(VisibleSelection(end, SelDefaultAffinity, endingSelec
tion().isDirectional())); | 1521 setEndingSelection(VisibleSelection(end, SelDefaultAffinity, endingSelec
tion().isDirectional())); |
| 1522 } | 1522 } |
| 1523 | 1523 |
| 1524 void ReplaceSelectionCommand::mergeTextNodesAroundPosition(Position& position, P
osition& positionOnlyToBeUpdated, EditingState* editingState) | 1524 void ReplaceSelectionCommand::mergeTextNodesAroundPosition(Position& position, P
osition& positionOnlyToBeUpdated, EditingState* editingState) |
| 1525 { | 1525 { |
| 1526 bool positionIsOffsetInAnchor = position.isOffsetInAnchor(); | 1526 bool positionIsOffsetInAnchor = position.isOffsetInAnchor(); |
| 1527 bool positionOnlyToBeUpdatedIsOffsetInAnchor = positionOnlyToBeUpdated.isOff
setInAnchor(); | 1527 bool positionOnlyToBeUpdatedIsOffsetInAnchor = positionOnlyToBeUpdated.isOff
setInAnchor(); |
| 1528 RefPtrWillBeRawPtr<Text> text = nullptr; | 1528 RawPtr<Text> text = nullptr; |
| 1529 if (positionIsOffsetInAnchor && position.computeContainerNode() && position.
computeContainerNode()->isTextNode()) { | 1529 if (positionIsOffsetInAnchor && position.computeContainerNode() && position.
computeContainerNode()->isTextNode()) { |
| 1530 text = toText(position.computeContainerNode()); | 1530 text = toText(position.computeContainerNode()); |
| 1531 } else { | 1531 } else { |
| 1532 Node* before = position.computeNodeBeforePosition(); | 1532 Node* before = position.computeNodeBeforePosition(); |
| 1533 if (before && before->isTextNode()) { | 1533 if (before && before->isTextNode()) { |
| 1534 text = toText(before); | 1534 text = toText(before); |
| 1535 } else { | 1535 } else { |
| 1536 Node* after = position.computeNodeAfterPosition(); | 1536 Node* after = position.computeNodeAfterPosition(); |
| 1537 if (after && after->isTextNode()) | 1537 if (after && after->isTextNode()) |
| 1538 text = toText(after); | 1538 text = toText(after); |
| 1539 } | 1539 } |
| 1540 } | 1540 } |
| 1541 if (!text) | 1541 if (!text) |
| 1542 return; | 1542 return; |
| 1543 | 1543 |
| 1544 if (text->previousSibling() && text->previousSibling()->isTextNode()) { | 1544 if (text->previousSibling() && text->previousSibling()->isTextNode()) { |
| 1545 RefPtrWillBeRawPtr<Text> previous = toText(text->previousSibling()); | 1545 RawPtr<Text> previous = toText(text->previousSibling()); |
| 1546 insertTextIntoNode(text, 0, previous->data()); | 1546 insertTextIntoNode(text, 0, previous->data()); |
| 1547 | 1547 |
| 1548 if (positionIsOffsetInAnchor) | 1548 if (positionIsOffsetInAnchor) |
| 1549 position = Position(position.computeContainerNode(), previous->lengt
h() + position.offsetInContainerNode()); | 1549 position = Position(position.computeContainerNode(), previous->lengt
h() + position.offsetInContainerNode()); |
| 1550 else | 1550 else |
| 1551 updatePositionForNodeRemoval(position, *previous); | 1551 updatePositionForNodeRemoval(position, *previous); |
| 1552 | 1552 |
| 1553 if (positionOnlyToBeUpdatedIsOffsetInAnchor) { | 1553 if (positionOnlyToBeUpdatedIsOffsetInAnchor) { |
| 1554 if (positionOnlyToBeUpdated.computeContainerNode() == text) | 1554 if (positionOnlyToBeUpdated.computeContainerNode() == text) |
| 1555 positionOnlyToBeUpdated = Position(text, previous->length() + po
sitionOnlyToBeUpdated.offsetInContainerNode()); | 1555 positionOnlyToBeUpdated = Position(text, previous->length() + po
sitionOnlyToBeUpdated.offsetInContainerNode()); |
| 1556 else if (positionOnlyToBeUpdated.computeContainerNode() == previous) | 1556 else if (positionOnlyToBeUpdated.computeContainerNode() == previous) |
| 1557 positionOnlyToBeUpdated = Position(text, positionOnlyToBeUpdated
.offsetInContainerNode()); | 1557 positionOnlyToBeUpdated = Position(text, positionOnlyToBeUpdated
.offsetInContainerNode()); |
| 1558 } else { | 1558 } else { |
| 1559 updatePositionForNodeRemoval(positionOnlyToBeUpdated, *previous); | 1559 updatePositionForNodeRemoval(positionOnlyToBeUpdated, *previous); |
| 1560 } | 1560 } |
| 1561 | 1561 |
| 1562 removeNode(previous, editingState); | 1562 removeNode(previous, editingState); |
| 1563 if (editingState->isAborted()) | 1563 if (editingState->isAborted()) |
| 1564 return; | 1564 return; |
| 1565 } | 1565 } |
| 1566 if (text->nextSibling() && text->nextSibling()->isTextNode()) { | 1566 if (text->nextSibling() && text->nextSibling()->isTextNode()) { |
| 1567 RefPtrWillBeRawPtr<Text> next = toText(text->nextSibling()); | 1567 RawPtr<Text> next = toText(text->nextSibling()); |
| 1568 unsigned originalLength = text->length(); | 1568 unsigned originalLength = text->length(); |
| 1569 insertTextIntoNode(text, originalLength, next->data()); | 1569 insertTextIntoNode(text, originalLength, next->data()); |
| 1570 | 1570 |
| 1571 if (!positionIsOffsetInAnchor) | 1571 if (!positionIsOffsetInAnchor) |
| 1572 updatePositionForNodeRemoval(position, *next); | 1572 updatePositionForNodeRemoval(position, *next); |
| 1573 | 1573 |
| 1574 if (positionOnlyToBeUpdatedIsOffsetInAnchor && positionOnlyToBeUpdated.c
omputeContainerNode() == next) | 1574 if (positionOnlyToBeUpdatedIsOffsetInAnchor && positionOnlyToBeUpdated.c
omputeContainerNode() == next) |
| 1575 positionOnlyToBeUpdated = Position(text, originalLength + positionOn
lyToBeUpdated.offsetInContainerNode()); | 1575 positionOnlyToBeUpdated = Position(text, originalLength + positionOn
lyToBeUpdated.offsetInContainerNode()); |
| 1576 else | 1576 else |
| 1577 updatePositionForNodeRemoval(positionOnlyToBeUpdated, *next); | 1577 updatePositionForNodeRemoval(positionOnlyToBeUpdated, *next); |
| 1578 | 1578 |
| 1579 removeNode(next, editingState); | 1579 removeNode(next, editingState); |
| 1580 if (editingState->isAborted()) | 1580 if (editingState->isAborted()) |
| 1581 return; | 1581 return; |
| 1582 } | 1582 } |
| 1583 } | 1583 } |
| 1584 | 1584 |
| 1585 EditAction ReplaceSelectionCommand::editingAction() const | 1585 EditAction ReplaceSelectionCommand::editingAction() const |
| 1586 { | 1586 { |
| 1587 return m_editAction; | 1587 return m_editAction; |
| 1588 } | 1588 } |
| 1589 | 1589 |
| 1590 // If the user is inserting a list into an existing list, instead of nesting the
list, | 1590 // If the user is inserting a list into an existing list, instead of nesting the
list, |
| 1591 // we put the list items into the existing list. | 1591 // we put the list items into the existing list. |
| 1592 Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtrWillBeRawPtr<HTMLElem
ent> prpListElement, Element* insertionBlock, const Position& insertPos, Inserte
dNodes& insertedNodes, EditingState* editingState) | 1592 Node* ReplaceSelectionCommand::insertAsListItems(RawPtr<HTMLElement> prpListElem
ent, Element* insertionBlock, const Position& insertPos, InsertedNodes& inserted
Nodes, EditingState* editingState) |
| 1593 { | 1593 { |
| 1594 RefPtrWillBeRawPtr<HTMLElement> listElement = prpListElement; | 1594 RawPtr<HTMLElement> listElement = prpListElement; |
| 1595 | 1595 |
| 1596 while (listElement->hasOneChild() && isHTMLListElement(listElement->firstChi
ld())) | 1596 while (listElement->hasOneChild() && isHTMLListElement(listElement->firstChi
ld())) |
| 1597 listElement = toHTMLElement(listElement->firstChild()); | 1597 listElement = toHTMLElement(listElement->firstChild()); |
| 1598 | 1598 |
| 1599 bool isStart = isStartOfParagraph(createVisiblePosition(insertPos)); | 1599 bool isStart = isStartOfParagraph(createVisiblePosition(insertPos)); |
| 1600 bool isEnd = isEndOfParagraph(createVisiblePosition(insertPos)); | 1600 bool isEnd = isEndOfParagraph(createVisiblePosition(insertPos)); |
| 1601 bool isMiddle = !isStart && !isEnd; | 1601 bool isMiddle = !isStart && !isEnd; |
| 1602 Node* lastNode = insertionBlock; | 1602 Node* lastNode = insertionBlock; |
| 1603 | 1603 |
| 1604 // If we're in the middle of a list item, we should split it into two separa
te | 1604 // If we're in the middle of a list item, we should split it into two separa
te |
| 1605 // list items and insert these nodes between them. | 1605 // list items and insert these nodes between them. |
| 1606 if (isMiddle) { | 1606 if (isMiddle) { |
| 1607 int textNodeOffset = insertPos.offsetInContainerNode(); | 1607 int textNodeOffset = insertPos.offsetInContainerNode(); |
| 1608 if (insertPos.anchorNode()->isTextNode() && textNodeOffset > 0) | 1608 if (insertPos.anchorNode()->isTextNode() && textNodeOffset > 0) |
| 1609 splitTextNode(toText(insertPos.anchorNode()), textNodeOffset); | 1609 splitTextNode(toText(insertPos.anchorNode()), textNodeOffset); |
| 1610 splitTreeToNode(insertPos.anchorNode(), lastNode, true); | 1610 splitTreeToNode(insertPos.anchorNode(), lastNode, true); |
| 1611 } | 1611 } |
| 1612 | 1612 |
| 1613 while (RefPtrWillBeRawPtr<Node> listItem = listElement->firstChild()) { | 1613 while (RawPtr<Node> listItem = listElement->firstChild()) { |
| 1614 listElement->removeChild(listItem.get(), ASSERT_NO_EXCEPTION); | 1614 listElement->removeChild(listItem.get(), ASSERT_NO_EXCEPTION); |
| 1615 if (isStart || isMiddle) { | 1615 if (isStart || isMiddle) { |
| 1616 insertNodeBefore(listItem, lastNode, editingState); | 1616 insertNodeBefore(listItem, lastNode, editingState); |
| 1617 if (editingState->isAborted()) | 1617 if (editingState->isAborted()) |
| 1618 return nullptr; | 1618 return nullptr; |
| 1619 insertedNodes.respondToNodeInsertion(*listItem); | 1619 insertedNodes.respondToNodeInsertion(*listItem); |
| 1620 } else if (isEnd) { | 1620 } else if (isEnd) { |
| 1621 insertNodeAfter(listItem, lastNode, editingState); | 1621 insertNodeAfter(listItem, lastNode, editingState); |
| 1622 if (editingState->isAborted()) | 1622 if (editingState->isAborted()) |
| 1623 return nullptr; | 1623 return nullptr; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 return false; | 1655 return false; |
| 1656 | 1656 |
| 1657 // FIXME: Would be nice to handle smart replace in the fast path. | 1657 // FIXME: Would be nice to handle smart replace in the fast path. |
| 1658 if (m_smartReplace || fragment.hasInterchangeNewlineAtStart() || fragment.ha
sInterchangeNewlineAtEnd()) | 1658 if (m_smartReplace || fragment.hasInterchangeNewlineAtStart() || fragment.ha
sInterchangeNewlineAtEnd()) |
| 1659 return false; | 1659 return false; |
| 1660 | 1660 |
| 1661 // e.g. when "bar" is inserted after "foo" in <div><u>foo</u></div>, "bar" s
hould not be underlined. | 1661 // e.g. when "bar" is inserted after "foo" in <div><u>foo</u></div>, "bar" s
hould not be underlined. |
| 1662 if (elementToSplitToAvoidPastingIntoInlineElementsWithStyle(endingSelection(
).start())) | 1662 if (elementToSplitToAvoidPastingIntoInlineElementsWithStyle(endingSelection(
).start())) |
| 1663 return false; | 1663 return false; |
| 1664 | 1664 |
| 1665 RefPtrWillBeRawPtr<Node> nodeAfterInsertionPos = mostForwardCaretPosition(en
dingSelection().end()).anchorNode(); | 1665 RawPtr<Node> nodeAfterInsertionPos = mostForwardCaretPosition(endingSelectio
n().end()).anchorNode(); |
| 1666 Text* textNode = toText(fragment.firstChild()); | 1666 Text* textNode = toText(fragment.firstChild()); |
| 1667 // Our fragment creation code handles tabs, spaces, and newlines, so we don'
t have to worry about those here. | 1667 // Our fragment creation code handles tabs, spaces, and newlines, so we don'
t have to worry about those here. |
| 1668 | 1668 |
| 1669 Position start = endingSelection().start(); | 1669 Position start = endingSelection().start(); |
| 1670 Position end = replaceSelectedTextInNode(textNode->data()); | 1670 Position end = replaceSelectedTextInNode(textNode->data()); |
| 1671 if (end.isNull()) | 1671 if (end.isNull()) |
| 1672 return false; | 1672 return false; |
| 1673 | 1673 |
| 1674 if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBR
Element(*nodeAfterInsertionPos) | 1674 if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBR
Element(*nodeAfterInsertionPos) |
| 1675 && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), creat
eVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) { | 1675 && shouldRemoveEndBR(toHTMLBRElement(nodeAfterInsertionPos.get()), creat
eVisiblePosition(positionBeforeNode(nodeAfterInsertionPos.get())))) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1703 visitor->trace(m_startOfInsertedContent); | 1703 visitor->trace(m_startOfInsertedContent); |
| 1704 visitor->trace(m_endOfInsertedContent); | 1704 visitor->trace(m_endOfInsertedContent); |
| 1705 visitor->trace(m_insertionStyle); | 1705 visitor->trace(m_insertionStyle); |
| 1706 visitor->trace(m_documentFragment); | 1706 visitor->trace(m_documentFragment); |
| 1707 visitor->trace(m_startOfInsertedRange); | 1707 visitor->trace(m_startOfInsertedRange); |
| 1708 visitor->trace(m_endOfInsertedRange); | 1708 visitor->trace(m_endOfInsertedRange); |
| 1709 CompositeEditCommand::trace(visitor); | 1709 CompositeEditCommand::trace(visitor); |
| 1710 } | 1710 } |
| 1711 | 1711 |
| 1712 } // namespace blink | 1712 } // namespace blink |
| OLD | NEW |