Chromium Code Reviews| 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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 ReplacementFragment(Document*, DocumentFragment*, const VisibleSelection&); | 70 ReplacementFragment(Document*, DocumentFragment*, const VisibleSelection&); |
| 71 | 71 |
| 72 Node* firstChild() const; | 72 Node* firstChild() const; |
| 73 Node* lastChild() const; | 73 Node* lastChild() const; |
| 74 | 74 |
| 75 bool isEmpty() const; | 75 bool isEmpty() const; |
| 76 | 76 |
| 77 bool hasInterchangeNewlineAtStart() const { return m_hasInterchangeNewlineAt Start; } | 77 bool hasInterchangeNewlineAtStart() const { return m_hasInterchangeNewlineAt Start; } |
| 78 bool hasInterchangeNewlineAtEnd() const { return m_hasInterchangeNewlineAtEn d; } | 78 bool hasInterchangeNewlineAtEnd() const { return m_hasInterchangeNewlineAtEn d; } |
| 79 | 79 |
| 80 void removeNode(PassRefPtr<Node>); | 80 void removeNode(PassRefPtrWillBeRawPtr<Node>); |
| 81 void removeNodePreservingChildren(PassRefPtr<Node>); | 81 void removeNodePreservingChildren(PassRefPtrWillBeRawPtr<Node>); |
| 82 | 82 |
| 83 private: | 83 private: |
| 84 PassRefPtr<Element> insertFragmentForTestRendering(Node* rootEditableNode); | 84 PassRefPtrWillBeRawPtr<Element> insertFragmentForTestRendering(Node* rootEdi tableNode); |
| 85 void removeUnrenderedNodes(Node*); | 85 void removeUnrenderedNodes(Node*); |
| 86 void restoreAndRemoveTestRenderingNodesToFragment(Element*); | 86 void restoreAndRemoveTestRenderingNodesToFragment(Element*); |
| 87 void removeInterchangeNodes(Node*); | 87 void removeInterchangeNodes(Node*); |
| 88 | 88 |
| 89 void insertNodeBefore(PassRefPtr<Node> node, Node* refNode); | 89 void insertNodeBefore(PassRefPtrWillBeRawPtr<Node>, Node* refNode); |
| 90 | 90 |
| 91 RefPtrWillBeMember<Document> m_document; | 91 RefPtrWillBeMember<Document> m_document; |
| 92 RefPtrWillBeMember<DocumentFragment> m_fragment; | 92 RefPtrWillBeMember<DocumentFragment> m_fragment; |
| 93 bool m_hasInterchangeNewlineAtStart; | 93 bool m_hasInterchangeNewlineAtStart; |
| 94 bool m_hasInterchangeNewlineAtEnd; | 94 bool m_hasInterchangeNewlineAtEnd; |
| 95 }; | 95 }; |
| 96 | 96 |
| 97 static bool isInterchangeNewlineNode(const Node *node) | 97 static bool isInterchangeNewlineNode(const Node *node) |
| 98 { | 98 { |
| 99 DEFINE_STATIC_LOCAL(String, interchangeNewlineClassString, (AppleInterchange Newline)); | 99 DEFINE_STATIC_LOCAL(String, interchangeNewlineClassString, (AppleInterchange Newline)); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 m_hasInterchangeNewlineAtStart(false), | 138 m_hasInterchangeNewlineAtStart(false), |
| 139 m_hasInterchangeNewlineAtEnd(false) | 139 m_hasInterchangeNewlineAtEnd(false) |
| 140 { | 140 { |
| 141 if (!m_document) | 141 if (!m_document) |
| 142 return; | 142 return; |
| 143 if (!m_fragment) | 143 if (!m_fragment) |
| 144 return; | 144 return; |
| 145 if (!m_fragment->firstChild()) | 145 if (!m_fragment->firstChild()) |
| 146 return; | 146 return; |
| 147 | 147 |
| 148 RefPtr<Element> editableRoot = selection.rootEditableElement(); | 148 RefPtrWillBeRawPtr<Element> editableRoot = selection.rootEditableElement(); |
| 149 ASSERT(editableRoot); | 149 ASSERT(editableRoot); |
| 150 if (!editableRoot) | 150 if (!editableRoot) |
| 151 return; | 151 return; |
| 152 | 152 |
| 153 Node* shadowAncestorNode = editableRoot->deprecatedShadowAncestorNode(); | 153 Node* shadowAncestorNode = editableRoot->deprecatedShadowAncestorNode(); |
| 154 | 154 |
| 155 if (!editableRoot->getAttributeEventListener(EventTypeNames::webkitBeforeTex tInserted) && | 155 if (!editableRoot->getAttributeEventListener(EventTypeNames::webkitBeforeTex tInserted) && |
| 156 // FIXME: Remove these checks once textareas and textfields actually reg ister an event handler. | 156 // FIXME: Remove these checks once textareas and textfields actually reg ister an event handler. |
| 157 !(shadowAncestorNode && shadowAncestorNode->renderer() && shadowAncestor Node->renderer()->isTextControl()) && | 157 !(shadowAncestorNode && shadowAncestorNode->renderer() && shadowAncestor Node->renderer()->isTextControl()) && |
| 158 editableRoot->rendererIsRichlyEditable()) { | 158 editableRoot->rendererIsRichlyEditable()) { |
| 159 removeInterchangeNodes(m_fragment.get()); | 159 removeInterchangeNodes(m_fragment.get()); |
| 160 return; | 160 return; |
| 161 } | 161 } |
| 162 | 162 |
| 163 RefPtr<Element> holder = insertFragmentForTestRendering(editableRoot.get()); | 163 RefPtrWillBeRawPtr<Element> holder = insertFragmentForTestRendering(editable Root.get()); |
| 164 if (!holder) { | 164 if (!holder) { |
| 165 removeInterchangeNodes(m_fragment.get()); | 165 removeInterchangeNodes(m_fragment.get()); |
| 166 return; | 166 return; |
| 167 } | 167 } |
| 168 | 168 |
| 169 RefPtrWillBeRawPtr<Range> range = VisibleSelection::selectionFromContentsOfN ode(holder.get()).toNormalizedRange(); | 169 RefPtrWillBeRawPtr<Range> range = VisibleSelection::selectionFromContentsOfN ode(holder.get()).toNormalizedRange(); |
| 170 String text = plainText(range.get(), static_cast<TextIteratorBehavior>(TextI teratorEmitsOriginalText | TextIteratorIgnoresStyleVisibility)); | 170 String text = plainText(range.get(), static_cast<TextIteratorBehavior>(TextI teratorEmitsOriginalText | TextIteratorIgnoresStyleVisibility)); |
| 171 | 171 |
| 172 removeInterchangeNodes(holder.get()); | 172 removeInterchangeNodes(holder.get()); |
| 173 removeUnrenderedNodes(holder.get()); | 173 removeUnrenderedNodes(holder.get()); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 198 Node *ReplacementFragment::firstChild() const | 198 Node *ReplacementFragment::firstChild() const |
| 199 { | 199 { |
| 200 return m_fragment ? m_fragment->firstChild() : 0; | 200 return m_fragment ? m_fragment->firstChild() : 0; |
| 201 } | 201 } |
| 202 | 202 |
| 203 Node *ReplacementFragment::lastChild() const | 203 Node *ReplacementFragment::lastChild() const |
| 204 { | 204 { |
| 205 return m_fragment ? m_fragment->lastChild() : 0; | 205 return m_fragment ? m_fragment->lastChild() : 0; |
| 206 } | 206 } |
| 207 | 207 |
| 208 void ReplacementFragment::removeNodePreservingChildren(PassRefPtr<Node> node) | 208 void ReplacementFragment::removeNodePreservingChildren(PassRefPtrWillBeRawPtr<No de> node) |
| 209 { | 209 { |
| 210 if (!node) | 210 if (!node) |
| 211 return; | 211 return; |
| 212 | 212 |
| 213 while (RefPtr<Node> n = node->firstChild()) { | 213 while (RefPtrWillBeRawPtr<Node> n = node->firstChild()) { |
| 214 removeNode(n); | 214 removeNode(n); |
| 215 insertNodeBefore(n.release(), node.get()); | 215 insertNodeBefore(n.release(), node.get()); |
| 216 } | 216 } |
| 217 removeNode(node); | 217 removeNode(node); |
| 218 } | 218 } |
| 219 | 219 |
| 220 void ReplacementFragment::removeNode(PassRefPtr<Node> node) | 220 void ReplacementFragment::removeNode(PassRefPtrWillBeRawPtr<Node> node) |
| 221 { | 221 { |
| 222 if (!node) | 222 if (!node) |
| 223 return; | 223 return; |
| 224 | 224 |
| 225 ContainerNode* parent = node->nonShadowBoundaryParentNode(); | 225 ContainerNode* parent = node->nonShadowBoundaryParentNode(); |
| 226 if (!parent) | 226 if (!parent) |
| 227 return; | 227 return; |
| 228 | 228 |
| 229 parent->removeChild(node.get()); | 229 parent->removeChild(node.get()); |
| 230 } | 230 } |
| 231 | 231 |
| 232 void ReplacementFragment::insertNodeBefore(PassRefPtr<Node> node, Node* refNode) | 232 void ReplacementFragment::insertNodeBefore(PassRefPtrWillBeRawPtr<Node> node, No de* refNode) |
| 233 { | 233 { |
| 234 if (!node || !refNode) | 234 if (!node || !refNode) |
| 235 return; | 235 return; |
| 236 | 236 |
| 237 ContainerNode* parent = refNode->nonShadowBoundaryParentNode(); | 237 ContainerNode* parent = refNode->nonShadowBoundaryParentNode(); |
| 238 if (!parent) | 238 if (!parent) |
| 239 return; | 239 return; |
| 240 | 240 |
| 241 parent->insertBefore(node, refNode); | 241 parent->insertBefore(node, refNode); |
| 242 } | 242 } |
| 243 | 243 |
| 244 PassRefPtr<Element> ReplacementFragment::insertFragmentForTestRendering(Node* ro otEditableElement) | 244 PassRefPtrWillBeRawPtr<Element> ReplacementFragment::insertFragmentForTestRender ing(Node* rootEditableElement) |
| 245 { | 245 { |
| 246 ASSERT(m_document); | 246 ASSERT(m_document); |
| 247 RefPtr<Element> holder = createDefaultParagraphElement(*m_document.get()); | 247 RefPtrWillBeRawPtr<Element> holder = createDefaultParagraphElement(*m_docume nt.get()); |
| 248 | 248 |
| 249 holder->appendChild(m_fragment); | 249 holder->appendChild(m_fragment); |
| 250 rootEditableElement->appendChild(holder.get()); | 250 rootEditableElement->appendChild(holder.get()); |
| 251 m_document->updateLayoutIgnorePendingStylesheets(); | 251 m_document->updateLayoutIgnorePendingStylesheets(); |
| 252 | 252 |
| 253 return holder.release(); | 253 return holder.release(); |
| 254 } | 254 } |
| 255 | 255 |
| 256 void ReplacementFragment::restoreAndRemoveTestRenderingNodesToFragment(Element* holder) | 256 void ReplacementFragment::restoreAndRemoveTestRenderingNodesToFragment(Element* holder) |
| 257 { | 257 { |
| 258 if (!holder) | 258 if (!holder) |
| 259 return; | 259 return; |
| 260 | 260 |
| 261 while (RefPtr<Node> node = holder->firstChild()) { | 261 while (RefPtrWillBeRawPtr<Node> node = holder->firstChild()) { |
| 262 holder->removeChild(node.get()); | 262 holder->removeChild(node.get()); |
| 263 m_fragment->appendChild(node.get()); | 263 m_fragment->appendChild(node.get()); |
| 264 } | 264 } |
| 265 | 265 |
| 266 removeNode(holder); | 266 removeNode(holder); |
| 267 } | 267 } |
| 268 | 268 |
| 269 void ReplacementFragment::removeUnrenderedNodes(Node* holder) | 269 void ReplacementFragment::removeUnrenderedNodes(Node* holder) |
| 270 { | 270 { |
| 271 Vector<RefPtr<Node> > unrendered; | 271 WillBeHeapVector<RefPtrWillBeMember<Node> > unrendered; |
| 272 | 272 |
| 273 for (Node* node = holder->firstChild(); node; node = NodeTraversal::next(*no de, holder)) | 273 for (Node* node = holder->firstChild(); node; node = NodeTraversal::next(*no de, holder)) |
| 274 if (!isNodeRendered(node) && !isTableStructureNode(node)) | 274 if (!isNodeRendered(node) && !isTableStructureNode(node)) |
| 275 unrendered.append(node); | 275 unrendered.append(node); |
| 276 | 276 |
| 277 size_t n = unrendered.size(); | 277 size_t n = unrendered.size(); |
| 278 for (size_t i = 0; i < n; ++i) | 278 for (size_t i = 0; i < n; ++i) |
| 279 removeNode(unrendered[i]); | 279 removeNode(unrendered[i]); |
| 280 } | 280 } |
| 281 | 281 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 304 if (isInterchangeNewlineNode(node)) { | 304 if (isInterchangeNewlineNode(node)) { |
| 305 m_hasInterchangeNewlineAtEnd = true; | 305 m_hasInterchangeNewlineAtEnd = true; |
| 306 removeNode(node); | 306 removeNode(node); |
| 307 break; | 307 break; |
| 308 } | 308 } |
| 309 node = node->lastChild(); | 309 node = node->lastChild(); |
| 310 } | 310 } |
| 311 | 311 |
| 312 node = container->firstChild(); | 312 node = container->firstChild(); |
| 313 while (node) { | 313 while (node) { |
| 314 RefPtr<Node> next = NodeTraversal::next(*node); | 314 RefPtrWillBeRawPtr<Node> next = NodeTraversal::next(*node); |
| 315 if (isInterchangeConvertedSpaceSpan(node)) { | 315 if (isInterchangeConvertedSpaceSpan(node)) { |
| 316 next = NodeTraversal::nextSkippingChildren(*node); | 316 next = NodeTraversal::nextSkippingChildren(*node); |
| 317 removeNodePreservingChildren(node); | 317 removeNodePreservingChildren(node); |
| 318 } | 318 } |
| 319 node = next.get(); | 319 node = next.get(); |
| 320 } | 320 } |
| 321 } | 321 } |
| 322 | 322 |
| 323 inline void ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion(Node& node) | 323 inline void ReplaceSelectionCommand::InsertedNodes::respondToNodeInsertion(Node& node) |
| 324 { | 324 { |
| 325 if (!m_firstNodeInserted) | 325 if (!m_firstNodeInserted) |
| 326 m_firstNodeInserted = &node; | 326 m_firstNodeInserted = &node; |
| 327 | 327 |
| 328 m_lastNodeInserted = &node; | 328 m_lastNodeInserted = &node; |
| 329 } | 329 } |
| 330 | 330 |
| 331 inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNodePreservingChil dren(Node& node) | 331 inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNodePreservingChil dren(Node& node) |
| 332 { | 332 { |
| 333 if (m_firstNodeInserted == node) | 333 if (m_firstNodeInserted.get() == node) |
| 334 m_firstNodeInserted = NodeTraversal::next(node); | 334 m_firstNodeInserted = NodeTraversal::next(node); |
| 335 if (m_lastNodeInserted == node) | 335 if (m_lastNodeInserted.get() == node) |
| 336 m_lastNodeInserted = node.lastChild() ? node.lastChild() : NodeTraversal ::nextSkippingChildren(node); | 336 m_lastNodeInserted = node.lastChild() ? node.lastChild() : NodeTraversal ::nextSkippingChildren(node); |
| 337 } | 337 } |
| 338 | 338 |
| 339 inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNode(Node& node) | 339 inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNode(Node& node) |
| 340 { | 340 { |
| 341 if (m_firstNodeInserted == node && m_lastNodeInserted == node) { | 341 if (m_firstNodeInserted.get() == node && m_lastNodeInserted.get() == node) { |
| 342 m_firstNodeInserted = nullptr; | 342 m_firstNodeInserted = nullptr; |
| 343 m_lastNodeInserted = nullptr; | 343 m_lastNodeInserted = nullptr; |
| 344 } else if (m_firstNodeInserted == node) { | 344 } else if (m_firstNodeInserted.get() == node) { |
| 345 m_firstNodeInserted = NodeTraversal::nextSkippingChildren(*m_firstNodeIn serted); | 345 m_firstNodeInserted = NodeTraversal::nextSkippingChildren(*m_firstNodeIn serted); |
| 346 } else if (m_lastNodeInserted == node) { | 346 } else if (m_lastNodeInserted.get() == node) { |
| 347 m_lastNodeInserted = NodeTraversal::previousSkippingChildren(*m_lastNode Inserted); | 347 m_lastNodeInserted = NodeTraversal::previousSkippingChildren(*m_lastNode Inserted); |
| 348 } | 348 } |
| 349 } | 349 } |
| 350 | 350 |
| 351 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(Node& node, N ode& newNode) | 351 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode(Node& node, N ode& newNode) |
| 352 { | 352 { |
| 353 if (m_firstNodeInserted == node) | 353 if (m_firstNodeInserted.get() == node) |
| 354 m_firstNodeInserted = &newNode; | 354 m_firstNodeInserted = &newNode; |
| 355 if (m_lastNodeInserted == node) | 355 if (m_lastNodeInserted.get() == node) |
| 356 m_lastNodeInserted = &newNode; | 356 m_lastNodeInserted = &newNode; |
| 357 } | 357 } |
| 358 | 358 |
| 359 ReplaceSelectionCommand::ReplaceSelectionCommand(Document& document, PassRefPtrW illBeRawPtr<DocumentFragment> fragment, CommandOptions options, EditAction editA ction) | 359 ReplaceSelectionCommand::ReplaceSelectionCommand(Document& document, PassRefPtrW illBeRawPtr<DocumentFragment> fragment, CommandOptions options, EditAction editA ction) |
| 360 : CompositeEditCommand(document) | 360 : CompositeEditCommand(document) |
| 361 , m_selectReplacement(options & SelectReplacement) | 361 , m_selectReplacement(options & SelectReplacement) |
| 362 , m_smartReplace(options & SmartReplace) | 362 , m_smartReplace(options & SmartReplace) |
| 363 , m_matchStyle(options & MatchStyle) | 363 , m_matchStyle(options & MatchStyle) |
| 364 , m_documentFragment(fragment) | 364 , m_documentFragment(fragment) |
| 365 , m_preventNesting(options & PreventNesting) | 365 , m_preventNesting(options & PreventNesting) |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 455 (!isHeaderElement(sourceBlock) || haveSameTagName(sourceBlock, destin ationBlock)) && | 455 (!isHeaderElement(sourceBlock) || haveSameTagName(sourceBlock, destin ationBlock)) && |
| 456 // Don't merge to or from a position before or after a block because it would | 456 // Don't merge to or from a position before or after a block because it would |
| 457 // be a no-op and cause infinite recursion. | 457 // be a no-op and cause infinite recursion. |
| 458 !isBlock(sourceNode) && !isBlock(destinationNode); | 458 !isBlock(sourceNode) && !isBlock(destinationNode); |
| 459 } | 459 } |
| 460 | 460 |
| 461 // Style rules that match just inserted elements could change their appearance, like | 461 // Style rules that match just inserted elements could change their appearance, like |
| 462 // a div inserted into a document with div { display:inline; }. | 462 // a div inserted into a document with div { display:inline; }. |
| 463 void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert edNodes& insertedNodes) | 463 void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert edNodes& insertedNodes) |
| 464 { | 464 { |
| 465 RefPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); | 465 RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); |
| 466 RefPtr<Node> next; | 466 RefPtrWillBeRawPtr<Node> next; |
|
haraken
2014/05/26 02:36:12
= nullptr;
sof
2014/05/28 08:31:35
Complied.
| |
| 467 for (RefPtr<Node> node = insertedNodes.firstNodeInserted(); node && node != pastEndNode; node = next) { | 467 for (RefPtrWillBeRawPtr<Node> node = insertedNodes.firstNodeInserted(); node && node != pastEndNode; node = next) { |
| 468 // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance | 468 // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance |
| 469 | 469 |
| 470 next = NodeTraversal::next(*node); | 470 next = NodeTraversal::next(*node); |
| 471 if (!node->isStyledElement()) | 471 if (!node->isStyledElement()) |
| 472 continue; | 472 continue; |
| 473 | 473 |
| 474 Element* element = toElement(node); | 474 Element* element = toElement(node); |
| 475 | 475 |
| 476 const StylePropertySet* inlineStyle = element->inlineStyle(); | 476 const StylePropertySet* inlineStyle = element->inlineStyle(); |
| 477 RefPtr<EditingStyle> newInlineStyle = EditingStyle::create(inlineStyle); | 477 RefPtrWillBeRawPtr<EditingStyle> newInlineStyle = EditingStyle::create(i nlineStyle); |
| 478 if (inlineStyle) { | 478 if (inlineStyle) { |
| 479 if (element->isHTMLElement()) { | 479 if (element->isHTMLElement()) { |
| 480 Vector<QualifiedName> attributes; | 480 Vector<QualifiedName> attributes; |
| 481 HTMLElement* htmlElement = toHTMLElement(element); | 481 HTMLElement* htmlElement = toHTMLElement(element); |
| 482 ASSERT(htmlElement); | 482 ASSERT(htmlElement); |
| 483 | 483 |
| 484 if (newInlineStyle->conflictsWithImplicitStyleOfElement(htmlElem ent)) { | 484 if (newInlineStyle->conflictsWithImplicitStyleOfElement(htmlElem ent)) { |
| 485 // e.g. <b style="font-weight: normal;"> is converted to <sp an style="font-weight: normal;"> | 485 // e.g. <b style="font-weight: normal;"> is converted to <sp an style="font-weight: normal;"> |
| 486 node = replaceElementWithSpanPreservingChildrenAndAttributes (htmlElement); | 486 node = replaceElementWithSpanPreservingChildrenAndAttributes (htmlElement); |
| 487 element = toElement(node); | 487 element = toElement(node); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 605 elements.add(theadTag.localName()); | 605 elements.add(theadTag.localName()); |
| 606 elements.add(trTag.localName()); | 606 elements.add(trTag.localName()); |
| 607 elements.add(ulTag.localName()); | 607 elements.add(ulTag.localName()); |
| 608 elements.add(xmpTag.localName()); | 608 elements.add(xmpTag.localName()); |
| 609 } | 609 } |
| 610 return elements.contains(name); | 610 return elements.contains(name); |
| 611 } | 611 } |
| 612 | 612 |
| 613 void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuild er(const InsertedNodes& insertedNodes) | 613 void ReplaceSelectionCommand::makeInsertedContentRoundTrippableWithHTMLTreeBuild er(const InsertedNodes& insertedNodes) |
| 614 { | 614 { |
| 615 RefPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); | 615 RefPtrWillBeRawPtr<Node> pastEndNode = insertedNodes.pastLastLeaf(); |
| 616 RefPtr<Node> next; | 616 RefPtrWillBeRawPtr<Node> next; |
|
haraken
2014/05/26 02:36:12
= nullptr;
sof
2014/05/28 08:31:35
Complied.
| |
| 617 for (RefPtr<Node> node = insertedNodes.firstNodeInserted(); node && node != pastEndNode; node = next) { | 617 for (RefPtrWillBeRawPtr<Node> node = insertedNodes.firstNodeInserted(); node && node != pastEndNode; node = next) { |
| 618 next = NodeTraversal::next(*node); | 618 next = NodeTraversal::next(*node); |
| 619 | 619 |
| 620 if (!node->isHTMLElement()) | 620 if (!node->isHTMLElement()) |
| 621 continue; | 621 continue; |
| 622 | 622 |
| 623 if (isProhibitedParagraphChild(toHTMLElement(node)->localName())) { | 623 if (isProhibitedParagraphChild(toHTMLElement(node)->localName())) { |
| 624 if (HTMLElement* paragraphElement = toHTMLElement(enclosingNodeWithT ag(positionInParentBeforeNode(*node), pTag))) | 624 if (HTMLElement* paragraphElement = toHTMLElement(enclosingNodeWithT ag(positionInParentBeforeNode(*node), pTag))) |
| 625 moveNodeOutOfAncestor(node, paragraphElement); | 625 moveNodeOutOfAncestor(node, paragraphElement); |
| 626 } | 626 } |
| 627 | 627 |
| 628 if (isHeaderElement(node.get())) { | 628 if (isHeaderElement(node.get())) { |
| 629 if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeO fType(positionInParentBeforeNode(*node), isHeaderElement))) | 629 if (HTMLElement* headerElement = toHTMLElement(highestEnclosingNodeO fType(positionInParentBeforeNode(*node), isHeaderElement))) |
| 630 moveNodeOutOfAncestor(node, headerElement); | 630 moveNodeOutOfAncestor(node, headerElement); |
| 631 } | 631 } |
| 632 } | 632 } |
| 633 } | 633 } |
| 634 | 634 |
| 635 void ReplaceSelectionCommand::moveNodeOutOfAncestor(PassRefPtr<Node> prpNode, Pa ssRefPtr<Node> prpAncestor) | 635 void ReplaceSelectionCommand::moveNodeOutOfAncestor(PassRefPtrWillBeRawPtr<Node> prpNode, PassRefPtrWillBeRawPtr<Node> prpAncestor) |
| 636 { | 636 { |
| 637 RefPtr<Node> node = prpNode; | 637 RefPtrWillBeRawPtr<Node> node = prpNode; |
| 638 RefPtr<Node> ancestor = prpAncestor; | 638 RefPtrWillBeRawPtr<Node> ancestor = prpAncestor; |
| 639 | 639 |
| 640 if (!ancestor->parentNode()->rendererIsEditable()) | 640 if (!ancestor->parentNode()->rendererIsEditable()) |
| 641 return; | 641 return; |
| 642 | 642 |
| 643 VisiblePosition positionAtEndOfNode(lastPositionInOrAfterNode(node.get())); | 643 VisiblePosition positionAtEndOfNode(lastPositionInOrAfterNode(node.get())); |
| 644 VisiblePosition lastPositionInParagraph(lastPositionInNode(ancestor.get())); | 644 VisiblePosition lastPositionInParagraph(lastPositionInNode(ancestor.get())); |
| 645 if (positionAtEndOfNode == lastPositionInParagraph) { | 645 if (positionAtEndOfNode == lastPositionInParagraph) { |
| 646 removeNode(node); | 646 removeNode(node); |
| 647 if (ancestor->nextSibling()) | 647 if (ancestor->nextSibling()) |
| 648 insertNodeBefore(node, ancestor->nextSibling()); | 648 insertNodeBefore(node, ancestor->nextSibling()); |
| 649 else | 649 else |
| 650 appendNode(node, ancestor->parentNode()); | 650 appendNode(node, ancestor->parentNode()); |
| 651 } else { | 651 } else { |
| 652 RefPtr<Node> nodeToSplitTo = splitTreeToNode(node.get(), ancestor.get(), true); | 652 RefPtrWillBeRawPtr<Node> nodeToSplitTo = splitTreeToNode(node.get(), anc estor.get(), true); |
| 653 removeNode(node); | 653 removeNode(node); |
| 654 insertNodeBefore(node, nodeToSplitTo); | 654 insertNodeBefore(node, nodeToSplitTo); |
| 655 } | 655 } |
| 656 if (!ancestor->firstChild()) | 656 if (!ancestor->firstChild()) |
| 657 removeNode(ancestor.release()); | 657 removeNode(ancestor.release()); |
| 658 } | 658 } |
| 659 | 659 |
| 660 static inline bool nodeHasVisibleRenderText(Text& text) | 660 static inline bool nodeHasVisibleRenderText(Text& text) |
| 661 { | 661 { |
| 662 return text.renderer() && toRenderText(text.renderer())->renderedTextLength( ) > 0; | 662 return text.renderer() && toRenderText(text.renderer())->renderedTextLength( ) > 0; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 722 // and doesn't receive the optimization. | 722 // and doesn't receive the optimization. |
| 723 if (isMailPasteAsQuotationNode(topNode) || enclosingNodeOfType(firstPosition InOrBeforeNode(topNode), isMailBlockquote, CanCrossEditingBoundary)) | 723 if (isMailPasteAsQuotationNode(topNode) || enclosingNodeOfType(firstPosition InOrBeforeNode(topNode), isMailBlockquote, CanCrossEditingBoundary)) |
| 724 return false; | 724 return false; |
| 725 | 725 |
| 726 // Either there are no style spans in the fragment or a WebKit client has ad ded content to the fragment | 726 // Either there are no style spans in the fragment or a WebKit client has ad ded content to the fragment |
| 727 // before inserting it. Look for and handle style spans after insertion. | 727 // before inserting it. Look for and handle style spans after insertion. |
| 728 if (!isLegacyAppleStyleSpan(topNode)) | 728 if (!isLegacyAppleStyleSpan(topNode)) |
| 729 return false; | 729 return false; |
| 730 | 730 |
| 731 Node* wrappingStyleSpan = topNode; | 731 Node* wrappingStyleSpan = topNode; |
| 732 RefPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(insertionPos .parentAnchoredEquivalent()); | 732 RefPtrWillBeRawPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create( insertionPos.parentAnchoredEquivalent()); |
| 733 String styleText = styleAtInsertionPos->style()->asText(); | 733 String styleText = styleAtInsertionPos->style()->asText(); |
| 734 | 734 |
| 735 // FIXME: This string comparison is a naive way of comparing two styles. | 735 // FIXME: This string comparison is a naive way of comparing two styles. |
| 736 // We should be taking the diff and check that the diff is empty. | 736 // We should be taking the diff and check that the diff is empty. |
| 737 if (styleText != toElement(wrappingStyleSpan)->getAttribute(styleAttr)) | 737 if (styleText != toElement(wrappingStyleSpan)->getAttribute(styleAttr)) |
| 738 return false; | 738 return false; |
| 739 | 739 |
| 740 fragment.removeNodePreservingChildren(wrappingStyleSpan); | 740 fragment.removeNodePreservingChildren(wrappingStyleSpan); |
| 741 return true; | 741 return true; |
| 742 } | 742 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 760 wrappingStyleSpan = toHTMLElement(node); | 760 wrappingStyleSpan = toHTMLElement(node); |
| 761 break; | 761 break; |
| 762 } | 762 } |
| 763 } | 763 } |
| 764 | 764 |
| 765 // There might not be any style spans if we're pasting from another applicat ion or if | 765 // There might not be any style spans if we're pasting from another applicat ion or if |
| 766 // we are here because of a document.execCommand("InsertHTML", ...) call. | 766 // we are here because of a document.execCommand("InsertHTML", ...) call. |
| 767 if (!wrappingStyleSpan) | 767 if (!wrappingStyleSpan) |
| 768 return; | 768 return; |
| 769 | 769 |
| 770 RefPtr<EditingStyle> style = EditingStyle::create(wrappingStyleSpan->inlineS tyle()); | 770 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(wrappingStyleS pan->inlineStyle()); |
| 771 ContainerNode* context = wrappingStyleSpan->parentNode(); | 771 ContainerNode* context = wrappingStyleSpan->parentNode(); |
| 772 | 772 |
| 773 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if yo u're pasting into a quoted region, | 773 // If Mail wraps the fragment with a Paste as Quotation blockquote, or if yo u're pasting into a quoted region, |
| 774 // styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>. | 774 // styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>. |
| 775 Node* blockquoteNode = isMailPasteAsQuotationNode(context) ? context : enclo singNodeOfType(firstPositionInNode(context), isMailBlockquote, CanCrossEditingBo undary); | 775 Node* blockquoteNode = isMailPasteAsQuotationNode(context) ? context : enclo singNodeOfType(firstPositionInNode(context), isMailBlockquote, CanCrossEditingBo undary); |
| 776 if (blockquoteNode) | 776 if (blockquoteNode) |
| 777 context = document().documentElement(); | 777 context = document().documentElement(); |
| 778 | 778 |
| 779 // This operation requires that only editing styles to be removed from sourc eDocumentStyle. | 779 // This operation requires that only editing styles to be removed from sourc eDocumentStyle. |
| 780 style->prepareToApplyAt(firstPositionInNode(context)); | 780 style->prepareToApplyAt(firstPositionInNode(context)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 // include the what was the start of the selection that was pasted into, so that we preserve that paragraph's | 813 // include the what was the start of the selection that was pasted into, so that we preserve that paragraph's |
| 814 // block styles. | 814 // block styles. |
| 815 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC ontent) && !isStartOfParagraph(startOfInsertedContent)); | 815 bool mergeForward = !(inSameParagraph(startOfInsertedContent, endOfInsertedC ontent) && !isStartOfParagraph(startOfInsertedContent)); |
| 816 | 816 |
| 817 VisiblePosition destination = mergeForward ? endOfInsertedContent.next() : e ndOfInsertedContent; | 817 VisiblePosition destination = mergeForward ? endOfInsertedContent.next() : e ndOfInsertedContent; |
| 818 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end OfInsertedContent) : endOfInsertedContent.next(); | 818 VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(end OfInsertedContent) : endOfInsertedContent.next(); |
| 819 | 819 |
| 820 // Merging forward could result in deleting the destination anchor node. | 820 // Merging forward could result in deleting the destination anchor node. |
| 821 // To avoid this, we add a placeholder node before the start of the paragrap h. | 821 // To avoid this, we add a placeholder node before the start of the paragrap h. |
| 822 if (endOfParagraph(startOfParagraphToMove) == destination) { | 822 if (endOfParagraph(startOfParagraphToMove) == destination) { |
| 823 RefPtr<Node> placeholder = createBreakElement(document()); | 823 RefPtrWillBeRawPtr<Node> placeholder = createBreakElement(document()); |
| 824 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().de precatedNode()); | 824 insertNodeBefore(placeholder, startOfParagraphToMove.deepEquivalent().de precatedNode()); |
| 825 destination = VisiblePosition(positionBeforeNode(placeholder.get())); | 825 destination = VisiblePosition(positionBeforeNode(placeholder.get())); |
| 826 } | 826 } |
| 827 | 827 |
| 828 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove) , destination); | 828 moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove) , destination); |
| 829 | 829 |
| 830 // Merging forward will remove m_endOfInsertedContent from the document. | 830 // Merging forward will remove m_endOfInsertedContent from the document. |
| 831 if (mergeForward) { | 831 if (mergeForward) { |
| 832 if (m_startOfInsertedContent.isOrphan()) | 832 if (m_startOfInsertedContent.isOrphan()) |
| 833 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui valent(); | 833 m_startOfInsertedContent = endingSelection().visibleStart().deepEqui valent(); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 986 return; | 986 return; |
| 987 | 987 |
| 988 // NOTE: This would be an incorrect usage of downstream() if downstream() we re changed to mean the last position after | 988 // NOTE: This would be an incorrect usage of downstream() if downstream() we re changed to mean the last position after |
| 989 // 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 | 989 // 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 |
| 990 // away, there are positions after the br which map to the same visible posi tion as [br, 0]). | 990 // away, there are positions after the br which map to the same visible posi tion as [br, 0]). |
| 991 Node* endBR = isHTMLBRElement(*insertionPos.downstream().deprecatedNode()) ? insertionPos.downstream().deprecatedNode() : 0; | 991 Node* endBR = isHTMLBRElement(*insertionPos.downstream().deprecatedNode()) ? insertionPos.downstream().deprecatedNode() : 0; |
| 992 VisiblePosition originalVisPosBeforeEndBR; | 992 VisiblePosition originalVisPosBeforeEndBR; |
| 993 if (endBR) | 993 if (endBR) |
| 994 originalVisPosBeforeEndBR = VisiblePosition(positionBeforeNode(endBR), D OWNSTREAM).previous(); | 994 originalVisPosBeforeEndBR = VisiblePosition(positionBeforeNode(endBR), D OWNSTREAM).previous(); |
| 995 | 995 |
| 996 RefPtr<Node> insertionBlock = enclosingBlock(insertionPos.deprecatedNode()); | 996 RefPtrWillBeRawPtr<Node> insertionBlock = enclosingBlock(insertionPos.deprec atedNode()); |
| 997 | 997 |
| 998 // Adjust insertionPos to prevent nesting. | 998 // Adjust insertionPos to prevent nesting. |
| 999 // If the start was in a Mail blockquote, we will have already handled adjus ting insertionPos above. | 999 // If the start was in a Mail blockquote, we will have already handled adjus ting insertionPos above. |
| 1000 if (m_preventNesting && insertionBlock && !isTableCell(insertionBlock.get()) && !startIsInsideMailBlockquote) { | 1000 if (m_preventNesting && insertionBlock && !isTableCell(insertionBlock.get()) && !startIsInsideMailBlockquote) { |
| 1001 ASSERT(insertionBlock != currentRoot); | 1001 ASSERT(insertionBlock != currentRoot); |
| 1002 VisiblePosition visibleInsertionPos(insertionPos); | 1002 VisiblePosition visibleInsertionPos(insertionPos); |
| 1003 if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInserti onPos) && fragment.hasInterchangeNewlineAtEnd())) | 1003 if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInserti onPos) && fragment.hasInterchangeNewlineAtEnd())) |
| 1004 insertionPos = positionInParentAfterNode(*insertionBlock); | 1004 insertionPos = positionInParentAfterNode(*insertionBlock); |
| 1005 else if (isStartOfBlock(visibleInsertionPos)) | 1005 else if (isStartOfBlock(visibleInsertionPos)) |
| 1006 insertionPos = positionInParentBeforeNode(*insertionBlock); | 1006 insertionPos = positionInParentBeforeNode(*insertionBlock); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1035 // This way we can produce a less verbose markup. | 1035 // This way we can produce a less verbose markup. |
| 1036 // We can skip this optimization for fragments not wrapped in one of | 1036 // We can skip this optimization for fragments not wrapped in one of |
| 1037 // our style spans and for positions inside list items | 1037 // our style spans and for positions inside list items |
| 1038 // since insertAsListItems already does the right thing. | 1038 // since insertAsListItems already does the right thing. |
| 1039 if (!m_matchStyle && !enclosingList(insertionPos.containerNode())) { | 1039 if (!m_matchStyle && !enclosingList(insertionPos.containerNode())) { |
| 1040 if (insertionPos.containerNode()->isTextNode() && insertionPos.offsetInC ontainerNode() && !insertionPos.atLastEditingPositionForNode()) { | 1040 if (insertionPos.containerNode()->isTextNode() && insertionPos.offsetInC ontainerNode() && !insertionPos.atLastEditingPositionForNode()) { |
| 1041 splitTextNode(insertionPos.containerText(), insertionPos.offsetInCon tainerNode()); | 1041 splitTextNode(insertionPos.containerText(), insertionPos.offsetInCon tainerNode()); |
| 1042 insertionPos = firstPositionInNode(insertionPos.containerNode()); | 1042 insertionPos = firstPositionInNode(insertionPos.containerNode()); |
| 1043 } | 1043 } |
| 1044 | 1044 |
| 1045 if (RefPtr<Node> nodeToSplitTo = nodeToSplitToAvoidPastingIntoInlineNode sWithStyle(insertionPos)) { | 1045 if (RefPtrWillBeRawPtr<Node> nodeToSplitTo = nodeToSplitToAvoidPastingIn toInlineNodesWithStyle(insertionPos)) { |
| 1046 if (insertionPos.containerNode() != nodeToSplitTo->parentNode()) { | 1046 if (insertionPos.containerNode() != nodeToSplitTo->parentNode()) { |
| 1047 Node* splitStart = insertionPos.computeNodeAfterPosition(); | 1047 Node* splitStart = insertionPos.computeNodeAfterPosition(); |
| 1048 if (!splitStart) | 1048 if (!splitStart) |
| 1049 splitStart = insertionPos.containerNode(); | 1049 splitStart = insertionPos.containerNode(); |
| 1050 nodeToSplitTo = splitTreeToNode(splitStart, nodeToSplitTo->paren tNode()).get(); | 1050 nodeToSplitTo = splitTreeToNode(splitStart, nodeToSplitTo->paren tNode()).get(); |
| 1051 insertionPos = positionInParentBeforeNode(*nodeToSplitTo); | 1051 insertionPos = positionInParentBeforeNode(*nodeToSplitTo); |
| 1052 } | 1052 } |
| 1053 } | 1053 } |
| 1054 } | 1054 } |
| 1055 | 1055 |
| 1056 // FIXME: When pasting rich content we're often prevented from heading down the fast path by style spans. Try | 1056 // FIXME: When pasting rich content we're often prevented from heading down the fast path by style spans. Try |
| 1057 // again here if they've been removed. | 1057 // again here if they've been removed. |
| 1058 | 1058 |
| 1059 // 1) Insert the content. | 1059 // 1) Insert the content. |
| 1060 // 2) Remove redundant styles and style tags, this inner <b> for example: <b >foo <b>bar</b> baz</b>. | 1060 // 2) Remove redundant styles and style tags, this inner <b> for example: <b >foo <b>bar</b> baz</b>. |
| 1061 // 3) Merge the start of the added content with the content before the posit ion being pasted into. | 1061 // 3) Merge the start of the added content with the content before the posit ion being pasted into. |
| 1062 // 4) Do one of the following: a) expand the last br if the fragment ends wi th one and it collapsed, | 1062 // 4) Do one of the following: a) expand the last br if the fragment ends wi th one and it collapsed, |
| 1063 // b) merge the last paragraph of the incoming fragment with the paragraph t hat contained the | 1063 // b) merge the last paragraph of the incoming fragment with the paragraph t hat contained the |
| 1064 // end of the selection that was pasted into, or c) handle an interchange ne wline at the end of the | 1064 // end of the selection that was pasted into, or c) handle an interchange ne wline at the end of the |
| 1065 // incoming fragment. | 1065 // incoming fragment. |
| 1066 // 5) Add spaces for smart replace. | 1066 // 5) Add spaces for smart replace. |
| 1067 // 6) Select the replacement if requested, and match style if requested. | 1067 // 6) Select the replacement if requested, and match style if requested. |
| 1068 | 1068 |
| 1069 InsertedNodes insertedNodes; | 1069 InsertedNodes insertedNodes; |
| 1070 RefPtr<Node> refNode = fragment.firstChild(); | 1070 RefPtrWillBeRawPtr<Node> refNode = fragment.firstChild(); |
| 1071 ASSERT(refNode); | 1071 ASSERT(refNode); |
| 1072 RefPtr<Node> node = refNode->nextSibling(); | 1072 RefPtrWillBeRawPtr<Node> node = refNode->nextSibling(); |
| 1073 | 1073 |
| 1074 fragment.removeNode(refNode); | 1074 fragment.removeNode(refNode); |
| 1075 | 1075 |
| 1076 Node* blockStart = enclosingBlock(insertionPos.deprecatedNode()); | 1076 Node* blockStart = enclosingBlock(insertionPos.deprecatedNode()); |
| 1077 if ((isListElement(refNode.get()) || (isLegacyAppleStyleSpan(refNode.get()) && isListElement(refNode->firstChild()))) | 1077 if ((isListElement(refNode.get()) || (isLegacyAppleStyleSpan(refNode.get()) && isListElement(refNode->firstChild()))) |
| 1078 && blockStart && blockStart->renderer()->isListItem()) | 1078 && blockStart && blockStart->renderer()->isListItem()) |
| 1079 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio nPos, insertedNodes); | 1079 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, insertio nPos, insertedNodes); |
| 1080 else { | 1080 else { |
| 1081 insertNodeAt(refNode, insertionPos); | 1081 insertNodeAt(refNode, insertionPos); |
| 1082 insertedNodes.respondToNodeInsertion(*refNode); | 1082 insertedNodes.respondToNodeInsertion(*refNode); |
| 1083 } | 1083 } |
| 1084 | 1084 |
| 1085 // Mutation events (bug 22634) may have already removed the inserted content | 1085 // Mutation events (bug 22634) may have already removed the inserted content |
| 1086 if (!refNode->inDocument()) | 1086 if (!refNode->inDocument()) |
| 1087 return; | 1087 return; |
| 1088 | 1088 |
| 1089 bool plainTextFragment = isPlainTextMarkup(refNode.get()); | 1089 bool plainTextFragment = isPlainTextMarkup(refNode.get()); |
| 1090 | 1090 |
| 1091 while (node) { | 1091 while (node) { |
| 1092 RefPtr<Node> next = node->nextSibling(); | 1092 RefPtrWillBeRawPtr<Node> next = node->nextSibling(); |
| 1093 fragment.removeNode(node.get()); | 1093 fragment.removeNode(node.get()); |
| 1094 insertNodeAfter(node, refNode); | 1094 insertNodeAfter(node, refNode); |
| 1095 insertedNodes.respondToNodeInsertion(*node); | 1095 insertedNodes.respondToNodeInsertion(*node); |
| 1096 | 1096 |
| 1097 // Mutation events (bug 22634) may have already removed the inserted con tent | 1097 // Mutation events (bug 22634) may have already removed the inserted con tent |
| 1098 if (!node->inDocument()) | 1098 if (!node->inDocument()) |
| 1099 return; | 1099 return; |
| 1100 | 1100 |
| 1101 refNode = node; | 1101 refNode = node; |
| 1102 if (node && plainTextFragment) | 1102 if (node && plainTextFragment) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1119 insertionBlock = nullptr; | 1119 insertionBlock = nullptr; |
| 1120 | 1120 |
| 1121 VisiblePosition startOfInsertedContent(firstPositionInOrBeforeNode(insertedN odes.firstNodeInserted())); | 1121 VisiblePosition startOfInsertedContent(firstPositionInOrBeforeNode(insertedN odes.firstNodeInserted())); |
| 1122 | 1122 |
| 1123 // We inserted before the insertionBlock to prevent nesting, and the content before the insertionBlock wasn't in its own block and | 1123 // We inserted before the insertionBlock to prevent nesting, and the content before the insertionBlock wasn't in its own block and |
| 1124 // didn't have a br after it, so the inserted content ended up in the same p aragraph. | 1124 // didn't have a br after it, so the inserted content ended up in the same p aragraph. |
| 1125 if (!startOfInsertedContent.isNull() && insertionBlock && insertionPos.depre catedNode() == insertionBlock->parentNode() && (unsigned)insertionPos.deprecated EditingOffset() < insertionBlock->nodeIndex() && !isStartOfParagraph(startOfInse rtedContent)) | 1125 if (!startOfInsertedContent.isNull() && insertionBlock && insertionPos.depre catedNode() == insertionBlock->parentNode() && (unsigned)insertionPos.deprecated EditingOffset() < insertionBlock->nodeIndex() && !isStartOfParagraph(startOfInse rtedContent)) |
| 1126 insertNodeAt(createBreakElement(document()).get(), startOfInsertedConten t.deepEquivalent()); | 1126 insertNodeAt(createBreakElement(document()).get(), startOfInsertedConten t.deepEquivalent()); |
| 1127 | 1127 |
| 1128 if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosB eforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText)) )) { | 1128 if (endBR && (plainTextFragment || (shouldRemoveEndBR(endBR, originalVisPosB eforeEndBR) && !(fragment.hasInterchangeNewlineAtEnd() && selectionIsPlainText)) )) { |
| 1129 RefPtr<Node> parent = endBR->parentNode(); | 1129 RefPtrWillBeRawPtr<Node> parent = endBR->parentNode(); |
| 1130 insertedNodes.willRemoveNode(*endBR); | 1130 insertedNodes.willRemoveNode(*endBR); |
| 1131 removeNode(endBR); | 1131 removeNode(endBR); |
| 1132 if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) { | 1132 if (Node* nodeToRemove = highestNodeToRemoveInPruning(parent.get())) { |
| 1133 insertedNodes.willRemoveNode(*nodeToRemove); | 1133 insertedNodes.willRemoveNode(*nodeToRemove); |
| 1134 removeNode(nodeToRemove); | 1134 removeNode(nodeToRemove); |
| 1135 } | 1135 } |
| 1136 } | 1136 } |
| 1137 | 1137 |
| 1138 makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes); | 1138 makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes); |
| 1139 | 1139 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1186 Position lastPositionToSelect; | 1186 Position lastPositionToSelect; |
| 1187 if (fragment.hasInterchangeNewlineAtEnd()) { | 1187 if (fragment.hasInterchangeNewlineAtEnd()) { |
| 1188 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); | 1188 VisiblePosition endOfInsertedContent = positionAtEndOfInsertedContent(); |
| 1189 VisiblePosition next = endOfInsertedContent.next(CannotCrossEditingBound ary); | 1189 VisiblePosition next = endOfInsertedContent.next(CannotCrossEditingBound ary); |
| 1190 | 1190 |
| 1191 if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedCont ent) || next.isNull()) { | 1191 if (selectionEndWasEndOfParagraph || !isEndOfParagraph(endOfInsertedCont ent) || next.isNull()) { |
| 1192 if (!isStartOfParagraph(endOfInsertedContent)) { | 1192 if (!isStartOfParagraph(endOfInsertedContent)) { |
| 1193 setEndingSelection(endOfInsertedContent); | 1193 setEndingSelection(endOfInsertedContent); |
| 1194 Node* enclosingNode = enclosingBlock(endOfInsertedContent.deepEq uivalent().deprecatedNode()); | 1194 Node* enclosingNode = enclosingBlock(endOfInsertedContent.deepEq uivalent().deprecatedNode()); |
| 1195 if (isListItem(enclosingNode)) { | 1195 if (isListItem(enclosingNode)) { |
| 1196 RefPtr<Node> newListItem = createListItemElement(document()) ; | 1196 RefPtrWillBeRawPtr<Node> newListItem = createListItemElement (document()); |
| 1197 insertNodeAfter(newListItem, enclosingNode); | 1197 insertNodeAfter(newListItem, enclosingNode); |
| 1198 setEndingSelection(VisiblePosition(firstPositionInNode(newLi stItem.get()))); | 1198 setEndingSelection(VisiblePosition(firstPositionInNode(newLi stItem.get()))); |
| 1199 } else { | 1199 } else { |
| 1200 // Use a default paragraph element (a plain div) for the emp ty paragraph, using the last paragraph | 1200 // Use a default paragraph element (a plain div) for the emp ty paragraph, using the last paragraph |
| 1201 // block's style seems to annoy users. | 1201 // block's style seems to annoy users. |
| 1202 insertParagraphSeparator(true, !startIsInsideMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(), | 1202 insertParagraphSeparator(true, !startIsInsideMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(), |
| 1203 isMailBlockquote, CannotCrossEditingBoundary, insertedNo des.firstNodeInserted()->parentNode())); | 1203 isMailBlockquote, CannotCrossEditingBoundary, insertedNo des.firstNodeInserted()->parentNode())); |
| 1204 } | 1204 } |
| 1205 | 1205 |
| 1206 // Select up to the paragraph separator that was added. | 1206 // Select up to the paragraph separator that was added. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1280 } | 1280 } |
| 1281 | 1281 |
| 1282 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar acterSmartReplaceExemptConsideringNonBreakingSpace(endOfInsertedContent.characte rAfter(), false); | 1282 bool needsTrailingSpace = !isEndOfParagraph(endOfInsertedContent) && !isChar acterSmartReplaceExemptConsideringNonBreakingSpace(endOfInsertedContent.characte rAfter(), false); |
| 1283 if (needsTrailingSpace && endNode) { | 1283 if (needsTrailingSpace && endNode) { |
| 1284 bool collapseWhiteSpace = !endNode->renderer() || endNode->renderer()->s tyle()->collapseWhiteSpace(); | 1284 bool collapseWhiteSpace = !endNode->renderer() || endNode->renderer()->s tyle()->collapseWhiteSpace(); |
| 1285 if (endNode->isTextNode()) { | 1285 if (endNode->isTextNode()) { |
| 1286 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ? nonBreakingSpaceString() : " "); | 1286 insertTextIntoNode(toText(endNode), endOffset, collapseWhiteSpace ? nonBreakingSpaceString() : " "); |
| 1287 if (m_endOfInsertedContent.containerNode() == endNode) | 1287 if (m_endOfInsertedContent.containerNode() == endNode) |
| 1288 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse tInContainerNode() + 1); | 1288 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse tInContainerNode() + 1); |
| 1289 } else { | 1289 } else { |
| 1290 RefPtr<Node> node = document().createEditingTextNode(collapseWhiteSp ace ? nonBreakingSpaceString() : " "); | 1290 RefPtrWillBeRawPtr<Node> node = document().createEditingTextNode(col lapseWhiteSpace ? nonBreakingSpaceString() : " "); |
| 1291 insertNodeAfter(node, endNode); | 1291 insertNodeAfter(node, endNode); |
| 1292 updateNodesInserted(node.get()); | 1292 updateNodesInserted(node.get()); |
| 1293 } | 1293 } |
| 1294 } | 1294 } |
| 1295 | 1295 |
| 1296 document().updateLayout(); | 1296 document().updateLayout(); |
| 1297 | 1297 |
| 1298 Position startDownstream = startOfInsertedContent.deepEquivalent().downstrea m(); | 1298 Position startDownstream = startOfInsertedContent.deepEquivalent().downstrea m(); |
| 1299 Node* startNode = startDownstream.computeNodeAfterPosition(); | 1299 Node* startNode = startDownstream.computeNodeAfterPosition(); |
| 1300 unsigned startOffset = 0; | 1300 unsigned startOffset = 0; |
| 1301 if (startDownstream.anchorType() == Position::PositionIsOffsetInAnchor) { | 1301 if (startDownstream.anchorType() == Position::PositionIsOffsetInAnchor) { |
| 1302 startNode = startDownstream.containerNode(); | 1302 startNode = startDownstream.containerNode(); |
| 1303 startOffset = startDownstream.offsetInContainerNode(); | 1303 startOffset = startDownstream.offsetInContainerNode(); |
| 1304 } | 1304 } |
| 1305 | 1305 |
| 1306 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC haracterSmartReplaceExemptConsideringNonBreakingSpace(startOfInsertedContent.pre vious().characterAfter(), true); | 1306 bool needsLeadingSpace = !isStartOfParagraph(startOfInsertedContent) && !isC haracterSmartReplaceExemptConsideringNonBreakingSpace(startOfInsertedContent.pre vious().characterAfter(), true); |
| 1307 if (needsLeadingSpace && startNode) { | 1307 if (needsLeadingSpace && startNode) { |
| 1308 bool collapseWhiteSpace = !startNode->renderer() || startNode->renderer( )->style()->collapseWhiteSpace(); | 1308 bool collapseWhiteSpace = !startNode->renderer() || startNode->renderer( )->style()->collapseWhiteSpace(); |
| 1309 if (startNode->isTextNode()) { | 1309 if (startNode->isTextNode()) { |
| 1310 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac e ? nonBreakingSpaceString() : " "); | 1310 insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpac e ? nonBreakingSpaceString() : " "); |
| 1311 if (m_endOfInsertedContent.containerNode() == startNode && m_endOfIn sertedContent.offsetInContainerNode()) | 1311 if (m_endOfInsertedContent.containerNode() == startNode && m_endOfIn sertedContent.offsetInContainerNode()) |
| 1312 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse tInContainerNode() + 1); | 1312 m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offse tInContainerNode() + 1); |
| 1313 } else { | 1313 } else { |
| 1314 RefPtr<Node> node = document().createEditingTextNode(collapseWhiteSp ace ? nonBreakingSpaceString() : " "); | 1314 RefPtrWillBeRawPtr<Node> node = document().createEditingTextNode(col lapseWhiteSpace ? nonBreakingSpaceString() : " "); |
| 1315 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont ent to be the node containing the leading space, | 1315 // Don't updateNodesInserted. Doing so would set m_endOfInsertedCont ent to be the node containing the leading space, |
| 1316 // but m_endOfInsertedContent is supposed to mark the end of pasted content. | 1316 // but m_endOfInsertedContent is supposed to mark the end of pasted content. |
| 1317 insertNodeBefore(node, startNode); | 1317 insertNodeBefore(node, startNode); |
| 1318 m_startOfInsertedContent = firstPositionInNode(node.get()); | 1318 m_startOfInsertedContent = firstPositionInNode(node.get()); |
| 1319 } | 1319 } |
| 1320 } | 1320 } |
| 1321 } | 1321 } |
| 1322 | 1322 |
| 1323 void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositi onToSelect) | 1323 void ReplaceSelectionCommand::completeHTMLReplacement(const Position &lastPositi onToSelect) |
| 1324 { | 1324 { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1429 | 1429 |
| 1430 // If we're in the middle of a list item, we should split it into two separa te | 1430 // If we're in the middle of a list item, we should split it into two separa te |
| 1431 // list items and insert these nodes between them. | 1431 // list items and insert these nodes between them. |
| 1432 if (isMiddle) { | 1432 if (isMiddle) { |
| 1433 int textNodeOffset = insertPos.offsetInContainerNode(); | 1433 int textNodeOffset = insertPos.offsetInContainerNode(); |
| 1434 if (insertPos.deprecatedNode()->isTextNode() && textNodeOffset > 0) | 1434 if (insertPos.deprecatedNode()->isTextNode() && textNodeOffset > 0) |
| 1435 splitTextNode(toText(insertPos.deprecatedNode()), textNodeOffset); | 1435 splitTextNode(toText(insertPos.deprecatedNode()), textNodeOffset); |
| 1436 splitTreeToNode(insertPos.deprecatedNode(), lastNode, true); | 1436 splitTreeToNode(insertPos.deprecatedNode(), lastNode, true); |
| 1437 } | 1437 } |
| 1438 | 1438 |
| 1439 while (RefPtr<Node> listItem = listElement->firstChild()) { | 1439 while (RefPtrWillBeRawPtr<Node> listItem = listElement->firstChild()) { |
| 1440 listElement->removeChild(listItem.get(), ASSERT_NO_EXCEPTION); | 1440 listElement->removeChild(listItem.get(), ASSERT_NO_EXCEPTION); |
| 1441 if (isStart || isMiddle) { | 1441 if (isStart || isMiddle) { |
| 1442 insertNodeBefore(listItem, lastNode); | 1442 insertNodeBefore(listItem, lastNode); |
| 1443 insertedNodes.respondToNodeInsertion(*listItem); | 1443 insertedNodes.respondToNodeInsertion(*listItem); |
| 1444 } else if (isEnd) { | 1444 } else if (isEnd) { |
| 1445 insertNodeAfter(listItem, lastNode); | 1445 insertNodeAfter(listItem, lastNode); |
| 1446 insertedNodes.respondToNodeInsertion(*listItem); | 1446 insertedNodes.respondToNodeInsertion(*listItem); |
| 1447 lastNode = listItem.get(); | 1447 lastNode = listItem.get(); |
| 1448 } else | 1448 } else |
| 1449 ASSERT_NOT_REACHED(); | 1449 ASSERT_NOT_REACHED(); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1476 return false; | 1476 return false; |
| 1477 | 1477 |
| 1478 // FIXME: Would be nice to handle smart replace in the fast path. | 1478 // FIXME: Would be nice to handle smart replace in the fast path. |
| 1479 if (m_smartReplace || fragment.hasInterchangeNewlineAtStart() || fragment.ha sInterchangeNewlineAtEnd()) | 1479 if (m_smartReplace || fragment.hasInterchangeNewlineAtStart() || fragment.ha sInterchangeNewlineAtEnd()) |
| 1480 return false; | 1480 return false; |
| 1481 | 1481 |
| 1482 // e.g. when "bar" is inserted after "foo" in <div><u>foo</u></div>, "bar" s hould not be underlined. | 1482 // e.g. when "bar" is inserted after "foo" in <div><u>foo</u></div>, "bar" s hould not be underlined. |
| 1483 if (nodeToSplitToAvoidPastingIntoInlineNodesWithStyle(endingSelection().star t())) | 1483 if (nodeToSplitToAvoidPastingIntoInlineNodesWithStyle(endingSelection().star t())) |
| 1484 return false; | 1484 return false; |
| 1485 | 1485 |
| 1486 RefPtr<Node> nodeAfterInsertionPos = endingSelection().end().downstream().an chorNode(); | 1486 RefPtrWillBeRawPtr<Node> nodeAfterInsertionPos = endingSelection().end().dow nstream().anchorNode(); |
| 1487 Text* textNode = toText(fragment.firstChild()); | 1487 Text* textNode = toText(fragment.firstChild()); |
| 1488 // Our fragment creation code handles tabs, spaces, and newlines, so we don' t have to worry about those here. | 1488 // Our fragment creation code handles tabs, spaces, and newlines, so we don' t have to worry about those here. |
| 1489 | 1489 |
| 1490 Position start = endingSelection().start(); | 1490 Position start = endingSelection().start(); |
| 1491 Position end = replaceSelectedTextInNode(textNode->data()); | 1491 Position end = replaceSelectedTextInNode(textNode->data()); |
| 1492 if (end.isNull()) | 1492 if (end.isNull()) |
| 1493 return false; | 1493 return false; |
| 1494 | 1494 |
| 1495 if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBR Element(*nodeAfterInsertionPos) | 1495 if (nodeAfterInsertionPos && nodeAfterInsertionPos->parentNode() && isHTMLBR Element(*nodeAfterInsertionPos) |
| 1496 && shouldRemoveEndBR(nodeAfterInsertionPos.get(), VisiblePosition(positi onBeforeNode(nodeAfterInsertionPos.get())))) | 1496 && shouldRemoveEndBR(nodeAfterInsertionPos.get(), VisiblePosition(positi onBeforeNode(nodeAfterInsertionPos.get())))) |
| 1497 removeNodeAndPruneAncestors(nodeAfterInsertionPos.get()); | 1497 removeNodeAndPruneAncestors(nodeAfterInsertionPos.get()); |
| 1498 | 1498 |
| 1499 VisibleSelection selectionAfterReplace(m_selectReplacement ? start : end, en d); | 1499 VisibleSelection selectionAfterReplace(m_selectReplacement ? start : end, en d); |
| 1500 | 1500 |
| 1501 setEndingSelection(selectionAfterReplace); | 1501 setEndingSelection(selectionAfterReplace); |
| 1502 | 1502 |
| 1503 return true; | 1503 return true; |
| 1504 } | 1504 } |
| 1505 | 1505 |
| 1506 void ReplaceSelectionCommand::trace(Visitor* visitor) | |
| 1507 { | |
| 1508 visitor->trace(m_insertionStyle); | |
| 1509 visitor->trace(m_documentFragment); | |
| 1510 CompositeEditCommand::trace(visitor); | |
| 1511 } | |
| 1512 | |
| 1506 } // namespace WebCore | 1513 } // namespace WebCore |
| OLD | NEW |