OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. |
3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. | 3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. |
4 * Copyright (C) 2011 Igalia S.L. | 4 * Copyright (C) 2011 Igalia S.L. |
5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
6 * | 6 * |
7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
9 * are met: | 9 * are met: |
10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
61 #include "wtf/text/StringBuilder.h" | 61 #include "wtf/text/StringBuilder.h" |
62 | 62 |
63 using namespace std; | 63 using namespace std; |
64 | 64 |
65 namespace WebCore { | 65 namespace WebCore { |
66 | 66 |
67 using namespace HTMLNames; | 67 using namespace HTMLNames; |
68 | 68 |
69 static bool propertyMissingOrEqualToNone(StylePropertySet*, CSSPropertyID); | 69 static bool propertyMissingOrEqualToNone(StylePropertySet*, CSSPropertyID); |
70 | 70 |
71 class AttributeChange { | 71 class AttributeChange : public NoBaseWillBeGarbageCollectedFinalized<AttributeCh ange> { |
72 public: | 72 public: |
73 AttributeChange() | 73 static PassOwnPtrWillBeRawPtr<AttributeChange> create(PassRefPtrWillBeRawPtr <Element> element, const QualifiedName& name, const String& value) |
74 : m_name(nullAtom, nullAtom, nullAtom) | |
75 { | 74 { |
75 return adoptPtrWillBeNoop(new AttributeChange(element, name, value)); | |
76 } | 76 } |
77 | 77 |
78 AttributeChange(PassRefPtr<Element> element, const QualifiedName& name, cons t String& value) | 78 AttributeChange(PassRefPtrWillBeRawPtr<Element> element, const QualifiedName & name, const String& value) |
79 : m_element(element), m_name(name), m_value(value) | 79 : m_element(element), m_name(name), m_value(value) |
80 { | 80 { |
81 } | 81 } |
82 | 82 |
83 void apply() | 83 void apply() |
84 { | 84 { |
85 m_element->setAttribute(m_name, AtomicString(m_value)); | 85 m_element->setAttribute(m_name, AtomicString(m_value)); |
86 } | 86 } |
87 | 87 |
88 void trace(Visitor* visitor) | |
89 { | |
90 visitor->trace(m_element); | |
91 } | |
92 | |
88 private: | 93 private: |
89 RefPtr<Element> m_element; | 94 RefPtrWillBeMember<Element> m_element; |
90 QualifiedName m_name; | 95 QualifiedName m_name; |
91 String m_value; | 96 String m_value; |
92 }; | 97 }; |
93 | 98 |
94 static void completeURLs(DocumentFragment& fragment, const String& baseURL) | 99 static void completeURLs(DocumentFragment& fragment, const String& baseURL) |
95 { | 100 { |
96 Vector<AttributeChange> changes; | 101 WillBeHeapVector<OwnPtrWillBeMember<AttributeChange> > changes; |
97 | 102 |
98 KURL parsedBaseURL(ParsedURLString, baseURL); | 103 KURL parsedBaseURL(ParsedURLString, baseURL); |
99 | 104 |
100 for (Element* element = ElementTraversal::firstWithin(fragment); element; el ement = ElementTraversal::next(*element, &fragment)) { | 105 for (Element* element = ElementTraversal::firstWithin(fragment); element; el ement = ElementTraversal::next(*element, &fragment)) { |
101 if (!element->hasAttributes()) | 106 if (!element->hasAttributes()) |
102 continue; | 107 continue; |
103 unsigned length = element->attributeCount(); | 108 unsigned length = element->attributeCount(); |
104 for (unsigned i = 0; i < length; i++) { | 109 for (unsigned i = 0; i < length; i++) { |
105 const Attribute& attribute = element->attributeItem(i); | 110 const Attribute& attribute = element->attributeItem(i); |
106 if (element->isURLAttribute(attribute) && !attribute.value().isEmpty ()) | 111 if (element->isURLAttribute(attribute) && !attribute.value().isEmpty ()) |
107 changes.append(AttributeChange(element, attribute.name(), KURL(p arsedBaseURL, attribute.value()).string())); | 112 changes.append(AttributeChange::create(element, attribute.name() , KURL(parsedBaseURL, attribute.value()).string())); |
108 } | 113 } |
109 } | 114 } |
110 | 115 |
111 size_t numChanges = changes.size(); | 116 size_t numChanges = changes.size(); |
112 for (size_t i = 0; i < numChanges; ++i) | 117 for (size_t i = 0; i < numChanges; ++i) |
113 changes[i].apply(); | 118 changes[i]->apply(); |
114 } | 119 } |
115 | 120 |
116 class StyledMarkupAccumulator FINAL : public MarkupAccumulator { | 121 class StyledMarkupAccumulator FINAL : public MarkupAccumulator { |
117 public: | 122 public: |
118 enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode }; | 123 enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode }; |
119 | 124 |
120 StyledMarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs, EAnnotateForInt erchange, const Range*, Node* highestNodeToBeSerialized = 0); | 125 StyledMarkupAccumulator(WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, EAbsoluteURLs, EAnnotateForInterchange, RawPtr<const Range>, Node* highestNodeTo BeSerialized = 0); |
121 Node* serializeNodes(Node* startNode, Node* pastEnd); | 126 Node* serializeNodes(Node* startNode, Node* pastEnd); |
122 void appendString(const String& s) { return MarkupAccumulator::appendString( s); } | 127 void appendString(const String& s) { return MarkupAccumulator::appendString( s); } |
123 void wrapWithNode(Node&, bool convertBlocksToInlines = false, RangeFullySele ctsNode = DoesFullySelectNode); | 128 void wrapWithNode(Node&, bool convertBlocksToInlines = false, RangeFullySele ctsNode = DoesFullySelectNode); |
124 void wrapWithStyleNode(StylePropertySet*, const Document&, bool isBlock = fa lse); | 129 void wrapWithStyleNode(StylePropertySet*, const Document&, bool isBlock = fa lse); |
125 String takeResults(); | 130 String takeResults(); |
126 | 131 |
127 private: | 132 private: |
128 void appendStyleNodeOpenTag(StringBuilder&, StylePropertySet*, const Documen t&, bool isBlock = false); | 133 void appendStyleNodeOpenTag(StringBuilder&, StylePropertySet*, const Documen t&, bool isBlock = false); |
129 const String& styleNodeCloseTag(bool isBlock = false); | 134 const String& styleNodeCloseTag(bool isBlock = false); |
130 virtual void appendText(StringBuilder& out, Text&) OVERRIDE; | 135 virtual void appendText(StringBuilder& out, Text&) OVERRIDE; |
131 String renderedText(Node&, const Range*); | 136 String renderedText(Node&, const Range*); |
132 String stringValueForRange(const Node&, const Range*); | 137 String stringValueForRange(const Node&, const Range*); |
133 void appendElement(StringBuilder& out, Element&, bool addDisplayInline, Rang eFullySelectsNode); | 138 void appendElement(StringBuilder& out, Element&, bool addDisplayInline, Rang eFullySelectsNode); |
134 virtual void appendElement(StringBuilder& out, Element& element, Namespaces* ) OVERRIDE { appendElement(out, element, false, DoesFullySelectNode); } | 139 virtual void appendElement(StringBuilder& out, Element& element, Namespaces* ) OVERRIDE { appendElement(out, element, false, DoesFullySelectNode); } |
135 | 140 |
136 enum NodeTraversalMode { EmitString, DoNotEmitString }; | 141 enum NodeTraversalMode { EmitString, DoNotEmitString }; |
137 Node* traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTrav ersalMode); | 142 Node* traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTrav ersalMode); |
138 | 143 |
139 bool shouldAnnotate() { return m_shouldAnnotate == AnnotateForInterchange; } | 144 bool shouldAnnotate() { return m_shouldAnnotate == AnnotateForInterchange; } |
140 bool shouldApplyWrappingStyle(const Node& node) const | 145 bool shouldApplyWrappingStyle(const Node& node) const |
141 { | 146 { |
142 return m_highestNodeToBeSerialized && m_highestNodeToBeSerialized->paren tNode() == node.parentNode() | 147 return m_highestNodeToBeSerialized && m_highestNodeToBeSerialized->paren tNode() == node.parentNode() |
143 && m_wrappingStyle && m_wrappingStyle->style(); | 148 && m_wrappingStyle && m_wrappingStyle->style(); |
144 } | 149 } |
145 | 150 |
146 Vector<String> m_reversedPrecedingMarkup; | 151 Vector<String> m_reversedPrecedingMarkup; |
147 const EAnnotateForInterchange m_shouldAnnotate; | 152 const EAnnotateForInterchange m_shouldAnnotate; |
148 Node* m_highestNodeToBeSerialized; | 153 RawPtrWillBeMember<Node> m_highestNodeToBeSerialized; |
149 RefPtr<EditingStyle> m_wrappingStyle; | 154 RefPtrWillBeMember<EditingStyle> m_wrappingStyle; |
haraken
2014/05/28 15:35:25
Who traces these Members?
Ian: It'd be great if t
haraken
2014/05/29 01:14:15
Ignore this comment :) I found that this object is
| |
150 }; | 155 }; |
151 | 156 |
152 inline StyledMarkupAccumulator::StyledMarkupAccumulator(Vector<Node*>* nodes, EA bsoluteURLs shouldResolveURLs, EAnnotateForInterchange shouldAnnotate, | 157 inline StyledMarkupAccumulator::StyledMarkupAccumulator(WillBeHeapVector<RawPtrW illBeMember<Node> >* nodes, EAbsoluteURLs shouldResolveURLs, EAnnotateForInterch ange shouldAnnotate, RawPtr<const Range> range, Node* highestNodeToBeSerialized) |
153 const Range* range, Node* highestNodeToBeSerialized) | |
154 : MarkupAccumulator(nodes, shouldResolveURLs, range) | 158 : MarkupAccumulator(nodes, shouldResolveURLs, range) |
155 , m_shouldAnnotate(shouldAnnotate) | 159 , m_shouldAnnotate(shouldAnnotate) |
156 , m_highestNodeToBeSerialized(highestNodeToBeSerialized) | 160 , m_highestNodeToBeSerialized(highestNodeToBeSerialized) |
157 { | 161 { |
158 } | 162 } |
159 | 163 |
160 void StyledMarkupAccumulator::wrapWithNode(Node& node, bool convertBlocksToInlin es, RangeFullySelectsNode rangeFullySelectsNode) | 164 void StyledMarkupAccumulator::wrapWithNode(Node& node, bool convertBlocksToInlin es, RangeFullySelectsNode rangeFullySelectsNode) |
161 { | 165 { |
162 StringBuilder markup; | 166 StringBuilder markup; |
163 if (node.isElementNode()) | 167 if (node.isElementNode()) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 | 213 |
210 // We remove '\0' characters because they are not visibly rendered to the us er. | 214 // We remove '\0' characters because they are not visibly rendered to the us er. |
211 return result.toString().replace(0, ""); | 215 return result.toString().replace(0, ""); |
212 } | 216 } |
213 | 217 |
214 void StyledMarkupAccumulator::appendText(StringBuilder& out, Text& text) | 218 void StyledMarkupAccumulator::appendText(StringBuilder& out, Text& text) |
215 { | 219 { |
216 const bool parentIsTextarea = text.parentElement() && text.parentElement()-> tagQName() == textareaTag; | 220 const bool parentIsTextarea = text.parentElement() && text.parentElement()-> tagQName() == textareaTag; |
217 const bool wrappingSpan = shouldApplyWrappingStyle(text) && !parentIsTextare a; | 221 const bool wrappingSpan = shouldApplyWrappingStyle(text) && !parentIsTextare a; |
218 if (wrappingSpan) { | 222 if (wrappingSpan) { |
219 RefPtr<EditingStyle> wrappingStyle = m_wrappingStyle->copy(); | 223 RefPtrWillBeRawPtr<EditingStyle> wrappingStyle = m_wrappingStyle->copy() ; |
220 // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance | 224 // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance |
221 // Make sure spans are inline style in paste side e.g. span { display: b lock }. | 225 // Make sure spans are inline style in paste side e.g. span { display: b lock }. |
222 wrappingStyle->forceInline(); | 226 wrappingStyle->forceInline(); |
223 // FIXME: Should this be included in forceInline? | 227 // FIXME: Should this be included in forceInline? |
224 wrappingStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone); | 228 wrappingStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone); |
225 | 229 |
226 appendStyleNodeOpenTag(out, wrappingStyle->style(), text.document()); | 230 appendStyleNodeOpenTag(out, wrappingStyle->style(), text.document()); |
227 } | 231 } |
228 | 232 |
229 if (!shouldAnnotate() || parentIsTextarea) | 233 if (!shouldAnnotate() || parentIsTextarea) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
282 const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldAp plyWrappingStyle(element); | 286 const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldAp plyWrappingStyle(element); |
283 for (unsigned i = 0; i < length; ++i) { | 287 for (unsigned i = 0; i < length; ++i) { |
284 const Attribute& attribute = element.attributeItem(i); | 288 const Attribute& attribute = element.attributeItem(i); |
285 // We'll handle the style attribute separately, below. | 289 // We'll handle the style attribute separately, below. |
286 if (attribute.name() == styleAttr && shouldOverrideStyleAttr) | 290 if (attribute.name() == styleAttr && shouldOverrideStyleAttr) |
287 continue; | 291 continue; |
288 appendAttribute(out, element, attribute, 0); | 292 appendAttribute(out, element, attribute, 0); |
289 } | 293 } |
290 | 294 |
291 if (shouldOverrideStyleAttr) { | 295 if (shouldOverrideStyleAttr) { |
292 RefPtr<EditingStyle> newInlineStyle; | 296 RefPtrWillBeRawPtr<EditingStyle> newInlineStyle; |
haraken
2014/05/28 15:35:25
= nullptr;
Mads prefers always-initialization eve
Mads Ager (chromium)
2014/05/28 16:09:44
I do prefer that. :-)
On the other hand I don't h
sof
2014/05/28 22:06:06
Complied.
| |
293 | 297 |
294 if (shouldApplyWrappingStyle(element)) { | 298 if (shouldApplyWrappingStyle(element)) { |
295 newInlineStyle = m_wrappingStyle->copy(); | 299 newInlineStyle = m_wrappingStyle->copy(); |
296 newInlineStyle->removePropertiesInElementDefaultStyle(&element); | 300 newInlineStyle->removePropertiesInElementDefaultStyle(&element); |
297 newInlineStyle->removeStyleConflictingWithStyleOfNode(&element); | 301 newInlineStyle->removeStyleConflictingWithStyleOfNode(&element); |
298 } else | 302 } else |
299 newInlineStyle = EditingStyle::create(); | 303 newInlineStyle = EditingStyle::create(); |
300 | 304 |
301 if (element.isStyledElement() && element.inlineStyle()) | 305 if (element.isStyledElement() && element.inlineStyle()) |
302 newInlineStyle->overrideWithStyle(element.inlineStyle()); | 306 newInlineStyle->overrideWithStyle(element.inlineStyle()); |
(...skipping 30 matching lines...) Expand all Loading... | |
333 | 337 |
334 if (m_highestNodeToBeSerialized && m_highestNodeToBeSerialized->parentNode() ) | 338 if (m_highestNodeToBeSerialized && m_highestNodeToBeSerialized->parentNode() ) |
335 m_wrappingStyle = EditingStyle::wrappingStyleForSerialization(m_highestN odeToBeSerialized->parentNode(), shouldAnnotate()); | 339 m_wrappingStyle = EditingStyle::wrappingStyleForSerialization(m_highestN odeToBeSerialized->parentNode(), shouldAnnotate()); |
336 | 340 |
337 return traverseNodesForSerialization(startNode, pastEnd, EmitString); | 341 return traverseNodesForSerialization(startNode, pastEnd, EmitString); |
338 } | 342 } |
339 | 343 |
340 Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, No de* pastEnd, NodeTraversalMode traversalMode) | 344 Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, No de* pastEnd, NodeTraversalMode traversalMode) |
341 { | 345 { |
342 const bool shouldEmit = traversalMode == EmitString; | 346 const bool shouldEmit = traversalMode == EmitString; |
343 Vector<Node*> ancestorsToClose; | 347 WillBeHeapVector<RawPtrWillBeMember<Node> > ancestorsToClose; |
344 Node* next; | 348 Node* next; |
345 Node* lastClosed = 0; | 349 Node* lastClosed = 0; |
346 for (Node* n = startNode; n != pastEnd; n = next) { | 350 for (Node* n = startNode; n != pastEnd; n = next) { |
347 // According to <rdar://problem/5730668>, it is possible for n to blow | 351 // According to <rdar://problem/5730668>, it is possible for n to blow |
348 // past pastEnd and become null here. This shouldn't be possible. | 352 // past pastEnd and become null here. This shouldn't be possible. |
349 // This null check will prevent crashes (but create too much markup) | 353 // This null check will prevent crashes (but create too much markup) |
350 // and the ASSERT will hopefully lead us to understanding the problem. | 354 // and the ASSERT will hopefully lead us to understanding the problem. |
351 ASSERT(n); | 355 ASSERT(n); |
352 if (!n) | 356 if (!n) |
353 break; | 357 break; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 | 472 |
469 static bool needInterchangeNewlineAfter(const VisiblePosition& v) | 473 static bool needInterchangeNewlineAfter(const VisiblePosition& v) |
470 { | 474 { |
471 VisiblePosition next = v.next(); | 475 VisiblePosition next = v.next(); |
472 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); | 476 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); |
473 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); | 477 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); |
474 // Add an interchange newline if a paragraph break is selected and a br won' t already be added to the markup to represent it. | 478 // Add an interchange newline if a paragraph break is selected and a br won' t already be added to the markup to represent it. |
475 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement( *upstreamNode) && upstreamNode == downstreamNode); | 479 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement( *upstreamNode) && upstreamNode == downstreamNode); |
476 } | 480 } |
477 | 481 |
478 static PassRefPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(const Node* n ode) | 482 static PassRefPtrWillBeRawPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(c onst Node* node) |
479 { | 483 { |
480 if (!node->isHTMLElement()) | 484 if (!node->isHTMLElement()) |
481 return nullptr; | 485 return nullptr; |
482 | 486 |
483 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t o untangle | 487 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t o untangle |
484 // the non-const-ness of styleFromMatchedRulesForElement. | 488 // the non-const-ness of styleFromMatchedRulesForElement. |
485 HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); | 489 HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); |
486 RefPtr<EditingStyle> style = EditingStyle::create(element->inlineStyle()); | 490 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin eStyle()); |
487 style->mergeStyleFromRules(element); | 491 style->mergeStyleFromRules(element); |
488 return style.release(); | 492 return style.release(); |
489 } | 493 } |
490 | 494 |
491 static bool isElementPresentational(const Node* node) | 495 static bool isElementPresentational(const Node* node) |
492 { | 496 { |
493 return node->hasTagName(uTag) || node->hasTagName(sTag) || node->hasTagName( strikeTag) | 497 return node->hasTagName(uTag) || node->hasTagName(sTag) || node->hasTagName( strikeTag) |
494 || node->hasTagName(iTag) || node->hasTagName(emTag) || node->hasTagName (bTag) || node->hasTagName(strongTag); | 498 || node->hasTagName(iTag) || node->hasTagName(emTag) || node->hasTagName (bTag) || node->hasTagName(strongTag); |
495 } | 499 } |
496 | 500 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
534 specialCommonAncestor = commonAncestor; | 538 specialCommonAncestor = commonAncestor; |
535 | 539 |
536 if (Node *enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(special CommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) | 540 if (Node *enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(special CommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) |
537 specialCommonAncestor = enclosingAnchor; | 541 specialCommonAncestor = enclosingAnchor; |
538 | 542 |
539 return specialCommonAncestor; | 543 return specialCommonAncestor; |
540 } | 544 } |
541 | 545 |
542 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha nge? | 546 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha nge? |
543 // FIXME: At least, annotation and style info should probably not be included in range.markupString() | 547 // FIXME: At least, annotation and style info should probably not be included in range.markupString() |
544 static String createMarkupInternal(Document& document, const Range* range, const Range* updatedRange, Vector<Node*>* nodes, | 548 static String createMarkupInternal(Document& document, const Range* range, const Range* updatedRange, WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, |
545 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu teURLs shouldResolveURLs, Node* constrainingAncestor) | 549 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu teURLs shouldResolveURLs, Node* constrainingAncestor) |
546 { | 550 { |
547 ASSERT(range); | 551 ASSERT(range); |
548 ASSERT(updatedRange); | 552 ASSERT(updatedRange); |
549 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); | 553 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); |
550 | 554 |
551 bool collapsed = updatedRange->collapsed(); | 555 bool collapsed = updatedRange->collapsed(); |
552 if (collapsed) | 556 if (collapsed) |
553 return emptyString(); | 557 return emptyString(); |
554 Node* commonAncestor = updatedRange->commonAncestorContainer(); | 558 Node* commonAncestor = updatedRange->commonAncestorContainer(); |
(...skipping 24 matching lines...) Expand all Loading... | |
579 if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, AS SERT_NO_EXCEPTION) >= 0) | 583 if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, AS SERT_NO_EXCEPTION) >= 0) |
580 return interchangeNewlineString; | 584 return interchangeNewlineString; |
581 } | 585 } |
582 | 586 |
583 Node* lastClosed = accumulator.serializeNodes(startNode, pastEnd); | 587 Node* lastClosed = accumulator.serializeNodes(startNode, pastEnd); |
584 | 588 |
585 if (specialCommonAncestor && lastClosed) { | 589 if (specialCommonAncestor && lastClosed) { |
586 // Also include all of the ancestors of lastClosed up to this special an cestor. | 590 // Also include all of the ancestors of lastClosed up to this special an cestor. |
587 for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ances tor = ancestor->parentNode()) { | 591 for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ances tor = ancestor->parentNode()) { |
588 if (ancestor == fullySelectedRoot && !convertBlocksToInlines) { | 592 if (ancestor == fullySelectedRoot && !convertBlocksToInlines) { |
589 RefPtr<EditingStyle> fullySelectedRootStyle = styleFromMatchedRu lesAndInlineDecl(fullySelectedRoot); | 593 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); |
590 | 594 |
591 // Bring the background attribute over, but not as an attribute because a background attribute on a div | 595 // Bring the background attribute over, but not as an attribute because a background attribute on a div |
592 // appears to have no effect. | 596 // appears to have no effect. |
593 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) | 597 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) |
594 && toElement(fullySelectedRoot)->hasAttribute(backgroundAttr )) | 598 && toElement(fullySelectedRoot)->hasAttribute(backgroundAttr )) |
595 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr ) + "')"); | 599 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr ) + "')"); |
596 | 600 |
597 if (fullySelectedRootStyle->style()) { | 601 if (fullySelectedRootStyle->style()) { |
598 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). | 602 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). |
599 // This assertion is caused at least when we select all text of a <body> element whose | 603 // This assertion is caused at least when we select all text of a <body> element whose |
(...skipping 17 matching lines...) Expand all Loading... | |
617 } | 621 } |
618 } | 622 } |
619 | 623 |
620 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. | 624 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. |
621 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter( visibleEnd.previous())) | 625 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter( visibleEnd.previous())) |
622 accumulator.appendString(interchangeNewlineString); | 626 accumulator.appendString(interchangeNewlineString); |
623 | 627 |
624 return accumulator.takeResults(); | 628 return accumulator.takeResults(); |
625 } | 629 } |
626 | 630 |
627 String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc hange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveUR Ls, Node* constrainingAncestor) | 631 String createMarkup(const Range* range, WillBeHeapVector<RawPtrWillBeMember<Node > >* nodes, EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveURLs, Node* constrainingAncestor) |
628 { | 632 { |
629 if (!range) | 633 if (!range) |
630 return emptyString(); | 634 return emptyString(); |
631 | 635 |
632 Document& document = range->ownerDocument(); | 636 Document& document = range->ownerDocument(); |
633 const Range* updatedRange = range; | 637 const Range* updatedRange = range; |
634 | 638 |
635 return createMarkupInternal(document, range, updatedRange, nodes, shouldAnno tate, convertBlocksToInlines, shouldResolveURLs, constrainingAncestor); | 639 return createMarkupInternal(document, range, updatedRange, nodes, shouldAnno tate, convertBlocksToInlines, shouldResolveURLs, constrainingAncestor); |
636 } | 640 } |
637 | 641 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
727 if (specialCommonAncestor) | 731 if (specialCommonAncestor) |
728 fragment->appendChild(specialCommonAncestor); | 732 fragment->appendChild(specialCommonAncestor); |
729 else | 733 else |
730 fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); | 734 fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); |
731 | 735 |
732 trimFragment(fragment.get(), nodeBeforeContext.get(), nodeAfterContext.get() ); | 736 trimFragment(fragment.get(), nodeBeforeContext.get(), nodeAfterContext.get() ); |
733 | 737 |
734 return fragment; | 738 return fragment; |
735 } | 739 } |
736 | 740 |
737 String createMarkup(const Node* node, EChildrenOnly childrenOnly, Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, Vector<QualifiedName>* tagNamesToSkip) | 741 String createMarkup(const Node* node, EChildrenOnly childrenOnly, WillBeHeapVect or<RawPtrWillBeMember<Node> >* nodes, EAbsoluteURLs shouldResolveURLs, Vector<Qu alifiedName>* tagNamesToSkip) |
738 { | 742 { |
739 if (!node) | 743 if (!node) |
740 return ""; | 744 return ""; |
741 | 745 |
742 MarkupAccumulator accumulator(nodes, shouldResolveURLs); | 746 MarkupAccumulator accumulator(nodes, shouldResolveURLs); |
743 return accumulator.serializeNodes(const_cast<Node&>(*node), childrenOnly, ta gNamesToSkip); | 747 return accumulator.serializeNodes(const_cast<Node&>(*node), childrenOnly, ta gNamesToSkip); |
744 } | 748 } |
745 | 749 |
746 static void fillContainerFromString(ContainerNode* paragraph, const String& stri ng) | 750 static void fillContainerFromString(ContainerNode* paragraph, const String& stri ng) |
747 { | 751 { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 if (text.isEmpty()) | 829 if (text.isEmpty()) |
826 return fragment.release(); | 830 return fragment.release(); |
827 | 831 |
828 String string = text; | 832 String string = text; |
829 string.replace("\r\n", "\n"); | 833 string.replace("\r\n", "\n"); |
830 string.replace('\r', '\n'); | 834 string.replace('\r', '\n'); |
831 | 835 |
832 if (shouldPreserveNewline(*context)) { | 836 if (shouldPreserveNewline(*context)) { |
833 fragment->appendChild(document.createTextNode(string)); | 837 fragment->appendChild(document.createTextNode(string)); |
834 if (string.endsWith('\n')) { | 838 if (string.endsWith('\n')) { |
835 RefPtr<Element> element = createBreakElement(document); | 839 RefPtrWillBeRawPtr<Element> element = createBreakElement(document); |
836 element->setAttribute(classAttr, AppleInterchangeNewline); | 840 element->setAttribute(classAttr, AppleInterchangeNewline); |
837 fragment->appendChild(element.release()); | 841 fragment->appendChild(element.release()); |
838 } | 842 } |
839 return fragment.release(); | 843 return fragment.release(); |
840 } | 844 } |
841 | 845 |
842 // A string with no newlines gets added inline, rather than being put into a paragraph. | 846 // A string with no newlines gets added inline, rather than being put into a paragraph. |
843 if (string.find('\n') == kNotFound) { | 847 if (string.find('\n') == kNotFound) { |
844 fillContainerFromString(fragment.get(), string); | 848 fillContainerFromString(fragment.get(), string); |
845 return fragment.release(); | 849 return fragment.release(); |
846 } | 850 } |
847 | 851 |
848 // Break string into paragraphs. Extra line breaks turn into empty paragraph s. | 852 // Break string into paragraphs. Extra line breaks turn into empty paragraph s. |
849 Node* blockNode = enclosingBlock(context->firstNode()); | 853 Node* blockNode = enclosingBlock(context->firstNode()); |
850 Element* block = toElement(blockNode); | 854 Element* block = toElement(blockNode); |
851 bool useClonesOfEnclosingBlock = blockNode | 855 bool useClonesOfEnclosingBlock = blockNode |
852 && blockNode->isElementNode() | 856 && blockNode->isElementNode() |
853 && !isHTMLBodyElement(*block) | 857 && !isHTMLBodyElement(*block) |
854 && !isHTMLHtmlElement(*block) | 858 && !isHTMLHtmlElement(*block) |
855 && block != editableRootForPosition(context->startPosition()); | 859 && block != editableRootForPosition(context->startPosition()); |
856 bool useLineBreak = enclosingTextFormControl(context->startPosition()); | 860 bool useLineBreak = enclosingTextFormControl(context->startPosition()); |
857 | 861 |
858 Vector<String> list; | 862 Vector<String> list; |
859 string.split('\n', true, list); // true gets us empty strings in the list | 863 string.split('\n', true, list); // true gets us empty strings in the list |
860 size_t numLines = list.size(); | 864 size_t numLines = list.size(); |
861 for (size_t i = 0; i < numLines; ++i) { | 865 for (size_t i = 0; i < numLines; ++i) { |
862 const String& s = list[i]; | 866 const String& s = list[i]; |
863 | 867 |
864 RefPtr<Element> element; | 868 RefPtrWillBeRawPtr<Element> element = nullptr; |
865 if (s.isEmpty() && i + 1 == numLines) { | 869 if (s.isEmpty() && i + 1 == numLines) { |
866 // For last line, use the "magic BR" rather than a P. | 870 // For last line, use the "magic BR" rather than a P. |
867 element = createBreakElement(document); | 871 element = createBreakElement(document); |
868 element->setAttribute(classAttr, AppleInterchangeNewline); | 872 element->setAttribute(classAttr, AppleInterchangeNewline); |
869 } else if (useLineBreak) { | 873 } else if (useLineBreak) { |
870 element = createBreakElement(document); | 874 element = createBreakElement(document); |
871 fillContainerFromString(fragment.get(), s); | 875 fillContainerFromString(fragment.get(), s); |
872 } else { | 876 } else { |
873 if (useClonesOfEnclosingBlock) | 877 if (useClonesOfEnclosingBlock) |
874 element = block->cloneElementWithoutChildren(); | 878 element = block->cloneElementWithoutChildren(); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1065 return; | 1069 return; |
1066 | 1070 |
1067 RefPtrWillBeRawPtr<Text> textNode = toText(node.get()); | 1071 RefPtrWillBeRawPtr<Text> textNode = toText(node.get()); |
1068 RefPtrWillBeRawPtr<Text> textNext = toText(next); | 1072 RefPtrWillBeRawPtr<Text> textNext = toText(next); |
1069 textNode->appendData(textNext->data()); | 1073 textNode->appendData(textNext->data()); |
1070 if (textNext->parentNode()) // Might have been removed by mutation event. | 1074 if (textNext->parentNode()) // Might have been removed by mutation event. |
1071 textNext->remove(exceptionState); | 1075 textNext->remove(exceptionState); |
1072 } | 1076 } |
1073 | 1077 |
1074 } | 1078 } |
OLD | NEW |