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 |