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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 | 109 |
110 size_t numChanges = changes.size(); | 110 size_t numChanges = changes.size(); |
111 for (size_t i = 0; i < numChanges; ++i) | 111 for (size_t i = 0; i < numChanges; ++i) |
112 changes[i].apply(); | 112 changes[i].apply(); |
113 } | 113 } |
114 | 114 |
115 class StyledMarkupAccumulator FINAL : public MarkupAccumulator { | 115 class StyledMarkupAccumulator FINAL : public MarkupAccumulator { |
116 public: | 116 public: |
117 enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode }; | 117 enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode }; |
118 | 118 |
119 StyledMarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs, EAnnotateForInt erchange, const Range*, Node* highestNodeToBeSerialized = 0); | 119 StyledMarkupAccumulator(Vector<const Node*>* nodes, EAbsoluteURLs, EAnnotate ForInterchange, const Range*, Node* highestNodeToBeSerialized = 0); |
120 Node* serializeNodes(Node* startNode, Node* pastEnd); | 120 Node* serializeNodes(Node* startNode, Node* pastEnd); |
121 void appendString(const String& s) { return MarkupAccumulator::appendString( s); } | 121 void appendString(const String& s) { return MarkupAccumulator::appendString( s); } |
122 void wrapWithNode(Node*, bool convertBlocksToInlines = false, RangeFullySele ctsNode = DoesFullySelectNode); | 122 void wrapWithNode(const Node&, bool convertBlocksToInlines = false, RangeFul lySelectsNode = DoesFullySelectNode); |
123 void wrapWithStyleNode(StylePropertySet*, Document*, bool isBlock = false); | 123 void wrapWithStyleNode(StylePropertySet*, const Document&, bool isBlock = fa lse); |
124 String takeResults(); | 124 String takeResults(); |
125 | 125 |
126 private: | 126 private: |
127 void appendStyleNodeOpenTag(StringBuilder&, StylePropertySet*, Document*, bo ol isBlock = false); | 127 void appendStyleNodeOpenTag(StringBuilder&, StylePropertySet*, const Documen t&, bool isBlock = false); |
128 const String& styleNodeCloseTag(bool isBlock = false); | 128 const String& styleNodeCloseTag(bool isBlock = false); |
129 virtual void appendText(StringBuilder& out, Text*) OVERRIDE; | 129 virtual void appendText(StringBuilder& out, const Text&) OVERRIDE; |
130 String renderedText(const Node*, const Range*); | 130 String renderedText(const Node&, const Range*); |
131 String stringValueForRange(const Node*, const Range*); | 131 String stringValueForRange(const Node&, const Range*); |
132 void appendElement(StringBuilder& out, Element*, bool addDisplayInline, Rang eFullySelectsNode); | 132 void appendElement(StringBuilder& out, const Element&, bool addDisplayInline , RangeFullySelectsNode); |
133 virtual void appendElement(StringBuilder& out, Element* element, Namespaces* ) OVERRIDE { appendElement(out, element, false, DoesFullySelectNode); } | 133 virtual void appendElement(StringBuilder& out, const Element& element, Names paces*) OVERRIDE { appendElement(out, element, false, DoesFullySelectNode); } |
134 | 134 |
135 enum NodeTraversalMode { EmitString, DoNotEmitString }; | 135 enum NodeTraversalMode { EmitString, DoNotEmitString }; |
136 Node* traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTrav ersalMode); | 136 Node* traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTrav ersalMode); |
137 | 137 |
138 bool shouldAnnotate() { return m_shouldAnnotate == AnnotateForInterchange; } | 138 bool shouldAnnotate() { return m_shouldAnnotate == AnnotateForInterchange; } |
139 bool shouldApplyWrappingStyle(Node* node) const | 139 bool shouldApplyWrappingStyle(const Node& node) const |
140 { | 140 { |
141 return m_highestNodeToBeSerialized && m_highestNodeToBeSerialized->paren tNode() == node->parentNode() | 141 return m_highestNodeToBeSerialized && m_highestNodeToBeSerialized->paren tNode() == node.parentNode() |
142 && m_wrappingStyle && m_wrappingStyle->style(); | 142 && m_wrappingStyle && m_wrappingStyle->style(); |
143 } | 143 } |
144 | 144 |
145 Vector<String> m_reversedPrecedingMarkup; | 145 Vector<String> m_reversedPrecedingMarkup; |
146 const EAnnotateForInterchange m_shouldAnnotate; | 146 const EAnnotateForInterchange m_shouldAnnotate; |
147 Node* m_highestNodeToBeSerialized; | 147 Node* m_highestNodeToBeSerialized; |
148 RefPtr<EditingStyle> m_wrappingStyle; | 148 RefPtr<EditingStyle> m_wrappingStyle; |
149 }; | 149 }; |
150 | 150 |
151 inline StyledMarkupAccumulator::StyledMarkupAccumulator(Vector<Node*>* nodes, EA bsoluteURLs shouldResolveURLs, EAnnotateForInterchange shouldAnnotate, | 151 inline StyledMarkupAccumulator::StyledMarkupAccumulator(Vector<const Node*>* nod es, EAbsoluteURLs shouldResolveURLs, EAnnotateForInterchange shouldAnnotate, |
152 const Range* range, Node* highestNodeToBeSerialized) | 152 const Range* range, Node* highestNodeToBeSerialized) |
153 : MarkupAccumulator(nodes, shouldResolveURLs, range) | 153 : MarkupAccumulator(nodes, shouldResolveURLs, range) |
154 , m_shouldAnnotate(shouldAnnotate) | 154 , m_shouldAnnotate(shouldAnnotate) |
155 , m_highestNodeToBeSerialized(highestNodeToBeSerialized) | 155 , m_highestNodeToBeSerialized(highestNodeToBeSerialized) |
156 { | 156 { |
157 } | 157 } |
158 | 158 |
159 void StyledMarkupAccumulator::wrapWithNode(Node* node, bool convertBlocksToInlin es, RangeFullySelectsNode rangeFullySelectsNode) | 159 void StyledMarkupAccumulator::wrapWithNode(const Node& node, bool convertBlocksT oInlines, RangeFullySelectsNode rangeFullySelectsNode) |
160 { | 160 { |
161 StringBuilder markup; | 161 StringBuilder markup; |
162 if (node->isElementNode()) | 162 if (node.isElementNode()) |
163 appendElement(markup, toElement(node), convertBlocksToInlines && isBlock (const_cast<Node*>(node)), rangeFullySelectsNode); | 163 appendElement(markup, toElement(node), convertBlocksToInlines && isBlock (&node), rangeFullySelectsNode); |
164 else | 164 else |
165 appendStartMarkup(markup, node, 0); | 165 appendStartMarkup(markup, node, 0); |
166 m_reversedPrecedingMarkup.append(markup.toString()); | 166 m_reversedPrecedingMarkup.append(markup.toString()); |
167 appendEndTag(node); | 167 appendEndTag(node); |
168 if (m_nodes) | 168 if (m_nodes) |
169 m_nodes->append(node); | 169 m_nodes->append(&node); |
170 } | 170 } |
171 | 171 |
172 void StyledMarkupAccumulator::wrapWithStyleNode(StylePropertySet* style, Documen t* document, bool isBlock) | 172 void StyledMarkupAccumulator::wrapWithStyleNode(StylePropertySet* style, const D ocument& document, bool isBlock) |
173 { | 173 { |
174 StringBuilder openTag; | 174 StringBuilder openTag; |
175 appendStyleNodeOpenTag(openTag, style, document, isBlock); | 175 appendStyleNodeOpenTag(openTag, style, document, isBlock); |
176 m_reversedPrecedingMarkup.append(openTag.toString()); | 176 m_reversedPrecedingMarkup.append(openTag.toString()); |
177 appendString(styleNodeCloseTag(isBlock)); | 177 appendString(styleNodeCloseTag(isBlock)); |
178 } | 178 } |
179 | 179 |
180 void StyledMarkupAccumulator::appendStyleNodeOpenTag(StringBuilder& out, StylePr opertySet* style, Document* document, bool isBlock) | 180 void StyledMarkupAccumulator::appendStyleNodeOpenTag(StringBuilder& out, StylePr opertySet* style, const Document& document, bool isBlock) |
181 { | 181 { |
182 // wrappingStyleForSerialization should have removed -webkit-text-decoration s-in-effect | 182 // wrappingStyleForSerialization should have removed -webkit-text-decoration s-in-effect |
183 ASSERT(propertyMissingOrEqualToNone(style, CSSPropertyWebkitTextDecorationsI nEffect)); | 183 ASSERT(propertyMissingOrEqualToNone(style, CSSPropertyWebkitTextDecorationsI nEffect)); |
184 if (isBlock) | 184 if (isBlock) |
185 out.appendLiteral("<div style=\""); | 185 out.appendLiteral("<div style=\""); |
186 else | 186 else |
187 out.appendLiteral("<span style=\""); | 187 out.appendLiteral("<span style=\""); |
188 appendAttributeValue(out, style->asText(), document->isHTMLDocument()); | 188 appendAttributeValue(out, style->asText(), document.isHTMLDocument()); |
189 out.appendLiteral("\">"); | 189 out.appendLiteral("\">"); |
190 } | 190 } |
191 | 191 |
192 const String& StyledMarkupAccumulator::styleNodeCloseTag(bool isBlock) | 192 const String& StyledMarkupAccumulator::styleNodeCloseTag(bool isBlock) |
193 { | 193 { |
194 DEFINE_STATIC_LOCAL(const String, divClose, ("</div>")); | 194 DEFINE_STATIC_LOCAL(const String, divClose, ("</div>")); |
195 DEFINE_STATIC_LOCAL(const String, styleSpanClose, ("</span>")); | 195 DEFINE_STATIC_LOCAL(const String, styleSpanClose, ("</span>")); |
196 return isBlock ? divClose : styleSpanClose; | 196 return isBlock ? divClose : styleSpanClose; |
197 } | 197 } |
198 | 198 |
199 String StyledMarkupAccumulator::takeResults() | 199 String StyledMarkupAccumulator::takeResults() |
200 { | 200 { |
201 StringBuilder result; | 201 StringBuilder result; |
202 result.reserveCapacity(totalLength(m_reversedPrecedingMarkup) + length()); | 202 result.reserveCapacity(totalLength(m_reversedPrecedingMarkup) + length()); |
203 | 203 |
204 for (size_t i = m_reversedPrecedingMarkup.size(); i > 0; --i) | 204 for (size_t i = m_reversedPrecedingMarkup.size(); i > 0; --i) |
205 result.append(m_reversedPrecedingMarkup[i - 1]); | 205 result.append(m_reversedPrecedingMarkup[i - 1]); |
206 | 206 |
207 concatenateMarkup(result); | 207 concatenateMarkup(result); |
208 | 208 |
209 // We remove '\0' characters because they are not visibly rendered to the us er. | 209 // We remove '\0' characters because they are not visibly rendered to the us er. |
210 return result.toString().replace(0, ""); | 210 return result.toString().replace(0, ""); |
211 } | 211 } |
212 | 212 |
213 void StyledMarkupAccumulator::appendText(StringBuilder& out, Text* text) | 213 void StyledMarkupAccumulator::appendText(StringBuilder& out, const Text& text) |
214 { | 214 { |
215 const bool parentIsTextarea = text->parentElement() && text->parentElement() ->tagQName() == textareaTag; | 215 const bool parentIsTextarea = text.parentElement() && text.parentElement()-> tagQName() == textareaTag; |
216 const bool wrappingSpan = shouldApplyWrappingStyle(text) && !parentIsTextare a; | 216 const bool wrappingSpan = shouldApplyWrappingStyle(text) && !parentIsTextare a; |
217 if (wrappingSpan) { | 217 if (wrappingSpan) { |
218 RefPtr<EditingStyle> wrappingStyle = m_wrappingStyle->copy(); | 218 RefPtr<EditingStyle> wrappingStyle = m_wrappingStyle->copy(); |
219 // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance | 219 // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance |
220 // Make sure spans are inline style in paste side e.g. span { display: b lock }. | 220 // Make sure spans are inline style in paste side e.g. span { display: b lock }. |
221 wrappingStyle->forceInline(); | 221 wrappingStyle->forceInline(); |
222 // FIXME: Should this be included in forceInline? | 222 // FIXME: Should this be included in forceInline? |
223 wrappingStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone); | 223 wrappingStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone); |
224 | 224 |
225 appendStyleNodeOpenTag(out, wrappingStyle->style(), &text->document()); | 225 appendStyleNodeOpenTag(out, wrappingStyle->style(), text.document()); |
226 } | 226 } |
227 | 227 |
228 if (!shouldAnnotate() || parentIsTextarea) | 228 if (!shouldAnnotate() || parentIsTextarea) |
229 MarkupAccumulator::appendText(out, text); | 229 MarkupAccumulator::appendText(out, text); |
230 else { | 230 else { |
231 const bool useRenderedText = !enclosingNodeWithTag(firstPositionInNode(t ext), selectTag); | 231 const bool useRenderedText = !enclosingNodeWithTag(firstPositionInNode(c onst_cast<Text*>(&text)), selectTag); |
adamk
2014/01/28 22:12:35
This and the various const_casts below make me a b
Inactive
2014/01/29 17:13:21
Yes, this is unfortunate. I will be less agressive
| |
232 String content = useRenderedText ? renderedText(text, m_range) : stringV alueForRange(text, m_range); | 232 String content = useRenderedText ? renderedText(text, m_range) : stringV alueForRange(text, m_range); |
233 StringBuilder buffer; | 233 StringBuilder buffer; |
234 appendCharactersReplacingEntities(buffer, content, 0, content.length(), EntityMaskInPCDATA); | 234 appendCharactersReplacingEntities(buffer, content, 0, content.length(), EntityMaskInPCDATA); |
235 out.append(convertHTMLTextToInterchangeFormat(buffer.toString(), text)); | 235 out.append(convertHTMLTextToInterchangeFormat(buffer.toString(), text)); |
236 } | 236 } |
237 | 237 |
238 if (wrappingSpan) | 238 if (wrappingSpan) |
239 out.append(styleNodeCloseTag()); | 239 out.append(styleNodeCloseTag()); |
240 } | 240 } |
241 | 241 |
242 String StyledMarkupAccumulator::renderedText(const Node* node, const Range* rang e) | 242 String StyledMarkupAccumulator::renderedText(const Node& node, const Range* rang e) |
243 { | 243 { |
244 if (!node->isTextNode()) | 244 if (!node.isTextNode()) |
245 return String(); | 245 return String(); |
246 | 246 |
247 const Text* textNode = toText(node); | 247 const Text& textNode = toText(node); |
248 unsigned startOffset = 0; | 248 unsigned startOffset = 0; |
249 unsigned endOffset = textNode->length(); | 249 unsigned endOffset = textNode.length(); |
250 | 250 |
251 if (range && node == range->startContainer()) | 251 if (range && node == range->startContainer()) |
252 startOffset = range->startOffset(); | 252 startOffset = range->startOffset(); |
253 if (range && node == range->endContainer()) | 253 if (range && node == range->endContainer()) |
254 endOffset = range->endOffset(); | 254 endOffset = range->endOffset(); |
255 | 255 |
256 Position start = createLegacyEditingPosition(const_cast<Node*>(node), startO ffset); | 256 Position start = createLegacyEditingPosition(const_cast<Node*>(&node), start Offset); |
257 Position end = createLegacyEditingPosition(const_cast<Node*>(node), endOffse t); | 257 Position end = createLegacyEditingPosition(const_cast<Node*>(&node), endOffs et); |
258 return plainText(Range::create(node->document(), start, end).get()); | 258 return plainText(Range::create(node.document(), start, end).get()); |
259 } | 259 } |
260 | 260 |
261 String StyledMarkupAccumulator::stringValueForRange(const Node* node, const Rang e* range) | 261 String StyledMarkupAccumulator::stringValueForRange(const Node& node, const Rang e* range) |
262 { | 262 { |
263 if (!range) | 263 if (!range) |
264 return node->nodeValue(); | 264 return node.nodeValue(); |
265 | 265 |
266 String str = node->nodeValue(); | 266 String str = node.nodeValue(); |
267 if (node == range->endContainer()) | 267 if (node == range->endContainer()) |
268 str.truncate(range->endOffset()); | 268 str.truncate(range->endOffset()); |
269 if (node == range->startContainer()) | 269 if (node == range->startContainer()) |
270 str.remove(0, range->startOffset()); | 270 str.remove(0, range->startOffset()); |
271 return str; | 271 return str; |
272 } | 272 } |
273 | 273 |
274 void StyledMarkupAccumulator::appendElement(StringBuilder& out, Element* element , bool addDisplayInline, RangeFullySelectsNode rangeFullySelectsNode) | 274 void StyledMarkupAccumulator::appendElement(StringBuilder& out, const Element& e lement, bool addDisplayInline, RangeFullySelectsNode rangeFullySelectsNode) |
275 { | 275 { |
276 const bool documentIsHTML = element->document().isHTMLDocument(); | 276 const bool documentIsHTML = element.document().isHTMLDocument(); |
277 appendOpenTag(out, element, 0); | 277 appendOpenTag(out, element, 0); |
278 | 278 |
279 const unsigned length = element->hasAttributes() ? element->attributeCount() : 0; | 279 const unsigned length = element.hasAttributes() ? element.attributeCount() : 0; |
280 const bool shouldAnnotateOrForceInline = element->isHTMLElement() && (should Annotate() || addDisplayInline); | 280 const bool shouldAnnotateOrForceInline = element.isHTMLElement() && (shouldA nnotate() || addDisplayInline); |
281 const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldAp plyWrappingStyle(element); | 281 const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldAp plyWrappingStyle(element); |
282 for (unsigned i = 0; i < length; ++i) { | 282 for (unsigned i = 0; i < length; ++i) { |
283 const Attribute* attribute = element->attributeItem(i); | 283 const Attribute* attribute = element.attributeItem(i); |
284 // We'll handle the style attribute separately, below. | 284 // We'll handle the style attribute separately, below. |
285 if (attribute->name() == styleAttr && shouldOverrideStyleAttr) | 285 if (attribute->name() == styleAttr && shouldOverrideStyleAttr) |
286 continue; | 286 continue; |
287 appendAttribute(out, element, *attribute, 0); | 287 appendAttribute(out, element, *attribute, 0); |
288 } | 288 } |
289 | 289 |
290 if (shouldOverrideStyleAttr) { | 290 if (shouldOverrideStyleAttr) { |
291 RefPtr<EditingStyle> newInlineStyle; | 291 RefPtr<EditingStyle> newInlineStyle; |
292 | 292 |
293 if (shouldApplyWrappingStyle(element)) { | 293 if (shouldApplyWrappingStyle(element)) { |
294 newInlineStyle = m_wrappingStyle->copy(); | 294 newInlineStyle = m_wrappingStyle->copy(); |
295 newInlineStyle->removePropertiesInElementDefaultStyle(element); | 295 newInlineStyle->removePropertiesInElementDefaultStyle(const_cast<Ele ment*>(&element)); |
296 newInlineStyle->removeStyleConflictingWithStyleOfNode(element); | 296 newInlineStyle->removeStyleConflictingWithStyleOfNode(const_cast<Ele ment*>(&element)); |
297 } else | 297 } else |
298 newInlineStyle = EditingStyle::create(); | 298 newInlineStyle = EditingStyle::create(); |
299 | 299 |
300 if (element->isStyledElement() && element->inlineStyle()) | 300 if (element.isStyledElement() && element.inlineStyle()) |
301 newInlineStyle->overrideWithStyle(element->inlineStyle()); | 301 newInlineStyle->overrideWithStyle(element.inlineStyle()); |
302 | 302 |
303 if (shouldAnnotateOrForceInline) { | 303 if (shouldAnnotateOrForceInline) { |
304 if (shouldAnnotate()) | 304 if (shouldAnnotate()) |
305 newInlineStyle->mergeStyleFromRulesForSerialization(toHTMLElemen t(element)); | 305 newInlineStyle->mergeStyleFromRulesForSerialization(const_cast<H TMLElement*>(&toHTMLElement(element))); |
306 | 306 |
307 if (addDisplayInline) | 307 if (addDisplayInline) |
308 newInlineStyle->forceInline(); | 308 newInlineStyle->forceInline(); |
309 | 309 |
310 // If the node is not fully selected by the range, then we don't wan t to keep styles that affect its relationship to the nodes around it | 310 // If the node is not fully selected by the range, then we don't wan t to keep styles that affect its relationship to the nodes around it |
311 // only the ones that affect it and the nodes within it. | 311 // only the ones that affect it and the nodes within it. |
312 if (rangeFullySelectsNode == DoesNotFullySelectNode && newInlineStyl e->style()) | 312 if (rangeFullySelectsNode == DoesNotFullySelectNode && newInlineStyl e->style()) |
313 newInlineStyle->style()->removeProperty(CSSPropertyFloat); | 313 newInlineStyle->style()->removeProperty(CSSPropertyFloat); |
314 } | 314 } |
315 | 315 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 continue; | 359 continue; |
360 | 360 |
361 if (!n->renderer() && !enclosingNodeWithTag(firstPositionInOrBeforeNode( n), selectTag)) { | 361 if (!n->renderer() && !enclosingNodeWithTag(firstPositionInOrBeforeNode( n), selectTag)) { |
362 next = NodeTraversal::nextSkippingChildren(*n); | 362 next = NodeTraversal::nextSkippingChildren(*n); |
363 // Don't skip over pastEnd. | 363 // Don't skip over pastEnd. |
364 if (pastEnd && pastEnd->isDescendantOf(n)) | 364 if (pastEnd && pastEnd->isDescendantOf(n)) |
365 next = pastEnd; | 365 next = pastEnd; |
366 } else { | 366 } else { |
367 // Add the node to the markup if we're not skipping the descendants | 367 // Add the node to the markup if we're not skipping the descendants |
368 if (shouldEmit) | 368 if (shouldEmit) |
369 appendStartTag(n); | 369 appendStartTag(*n); |
370 | 370 |
371 // If node has no children, close the tag now. | 371 // If node has no children, close the tag now. |
372 if (!n->childNodeCount()) { | 372 if (!n->childNodeCount()) { |
373 if (shouldEmit) | 373 if (shouldEmit) |
374 appendEndTag(n); | 374 appendEndTag(*n); |
375 lastClosed = n; | 375 lastClosed = n; |
376 } else { | 376 } else { |
377 openedTag = true; | 377 openedTag = true; |
378 ancestorsToClose.append(n); | 378 ancestorsToClose.append(n); |
379 } | 379 } |
380 } | 380 } |
381 | 381 |
382 // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors. | 382 // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors. |
383 // FIXME: What happens if we just inserted open tag and reached the end? | 383 // FIXME: What happens if we just inserted open tag and reached the end? |
384 if (!openedTag && (!n->nextSibling() || next == pastEnd)) { | 384 if (!openedTag && (!n->nextSibling() || next == pastEnd)) { |
385 // Close up the ancestors. | 385 // Close up the ancestors. |
386 while (!ancestorsToClose.isEmpty()) { | 386 while (!ancestorsToClose.isEmpty()) { |
387 Node* ancestor = ancestorsToClose.last(); | 387 Node* ancestor = ancestorsToClose.last(); |
388 ASSERT(ancestor); | |
388 if (next != pastEnd && next->isDescendantOf(ancestor)) | 389 if (next != pastEnd && next->isDescendantOf(ancestor)) |
389 break; | 390 break; |
390 // Not at the end of the range, close ancestors up to sibling of next node. | 391 // Not at the end of the range, close ancestors up to sibling of next node. |
391 if (shouldEmit) | 392 if (shouldEmit) |
392 appendEndTag(ancestor); | 393 appendEndTag(*ancestor); |
393 lastClosed = ancestor; | 394 lastClosed = ancestor; |
394 ancestorsToClose.removeLast(); | 395 ancestorsToClose.removeLast(); |
395 } | 396 } |
396 | 397 |
397 // Surround the currently accumulated markup with markup for ancesto rs we never opened as we leave the subtree(s) rooted at those ancestors. | 398 // Surround the currently accumulated markup with markup for ancesto rs we never opened as we leave the subtree(s) rooted at those ancestors. |
398 ContainerNode* nextParent = next ? next->parentNode() : 0; | 399 ContainerNode* nextParent = next ? next->parentNode() : 0; |
399 if (next != pastEnd && n != nextParent) { | 400 if (next != pastEnd && n != nextParent) { |
400 Node* lastAncestorClosedOrSelf = n->isDescendantOf(lastClosed) ? lastClosed : n; | 401 Node* lastAncestorClosedOrSelf = n->isDescendantOf(lastClosed) ? lastClosed : n; |
401 for (ContainerNode* parent = lastAncestorClosedOrSelf->parentNod e(); parent && parent != nextParent; parent = parent->parentNode()) { | 402 for (ContainerNode* parent = lastAncestorClosedOrSelf->parentNod e(); parent && parent != nextParent; parent = parent->parentNode()) { |
402 // All ancestors that aren't in the ancestorsToClose list sh ould either be a) unrendered: | 403 // All ancestors that aren't in the ancestorsToClose list sh ould either be a) unrendered: |
403 if (!parent->renderer()) | 404 if (!parent->renderer()) |
404 continue; | 405 continue; |
405 // or b) ancestors that we never encountered during a pre-or der traversal starting at startNode: | 406 // or b) ancestors that we never encountered during a pre-or der traversal starting at startNode: |
406 ASSERT(startNode->isDescendantOf(parent)); | 407 ASSERT(startNode->isDescendantOf(parent)); |
407 if (shouldEmit) | 408 if (shouldEmit) |
408 wrapWithNode(parent); | 409 wrapWithNode(*parent); |
409 lastClosed = parent; | 410 lastClosed = parent; |
410 } | 411 } |
411 } | 412 } |
412 } | 413 } |
413 } | 414 } |
414 | 415 |
415 return lastClosed; | 416 return lastClosed; |
416 } | 417 } |
417 | 418 |
418 static bool isHTMLBlockElement(const Node* node) | 419 static bool isHTMLBlockElement(const Node* node) |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
532 specialCommonAncestor = commonAncestor; | 533 specialCommonAncestor = commonAncestor; |
533 | 534 |
534 if (Node *enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(special CommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) | 535 if (Node *enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(special CommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) |
535 specialCommonAncestor = enclosingAnchor; | 536 specialCommonAncestor = enclosingAnchor; |
536 | 537 |
537 return specialCommonAncestor; | 538 return specialCommonAncestor; |
538 } | 539 } |
539 | 540 |
540 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha nge? | 541 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha nge? |
541 // FIXME: At least, annotation and style info should probably not be included in range.markupString() | 542 // FIXME: At least, annotation and style info should probably not be included in range.markupString() |
542 static String createMarkupInternal(Document& document, const Range* range, const Range* updatedRange, Vector<Node*>* nodes, | 543 static String createMarkupInternal(Document& document, const Range* range, const Range* updatedRange, Vector<const Node*>* nodes, |
543 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu teURLs shouldResolveURLs, Node* constrainingAncestor) | 544 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu teURLs shouldResolveURLs, Node* constrainingAncestor) |
544 { | 545 { |
545 ASSERT(range); | 546 ASSERT(range); |
546 ASSERT(updatedRange); | 547 ASSERT(updatedRange); |
547 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); | 548 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); |
548 | 549 |
549 bool collapsed = updatedRange->collapsed(ASSERT_NO_EXCEPTION); | 550 bool collapsed = updatedRange->collapsed(ASSERT_NO_EXCEPTION); |
550 if (collapsed) | 551 if (collapsed) |
551 return emptyString(); | 552 return emptyString(); |
552 Node* commonAncestor = updatedRange->commonAncestorContainer(ASSERT_NO_EXCEP TION); | 553 Node* commonAncestor = updatedRange->commonAncestorContainer(ASSERT_NO_EXCEP TION); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr ) + "')"); | 594 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr ) + "')"); |
594 | 595 |
595 if (fullySelectedRootStyle->style()) { | 596 if (fullySelectedRootStyle->style()) { |
596 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). | 597 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). |
597 // This assertion is caused at least when we select all text of a <body> element whose | 598 // This assertion is caused at least when we select all text of a <body> element whose |
598 // 'text-decoration' property is "inherit", and copy it. | 599 // 'text-decoration' property is "inherit", and copy it. |
599 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) | 600 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) |
600 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); | 601 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); |
601 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) | 602 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) |
602 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); | 603 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); |
603 accumulator.wrapWithStyleNode(fullySelectedRootStyle->style( ), &document, true); | 604 accumulator.wrapWithStyleNode(fullySelectedRootStyle->style( ), document, true); |
604 } | 605 } |
605 } else { | 606 } else { |
606 // Since this node and all the other ancestors are not in the se lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode | 607 // Since this node and all the other ancestors are not in the se lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode |
607 // so that styles that affect the exterior of the node are not i ncluded. | 608 // so that styles that affect the exterior of the node are not i ncluded. |
608 accumulator.wrapWithNode(ancestor, convertBlocksToInlines, Style dMarkupAccumulator::DoesNotFullySelectNode); | 609 accumulator.wrapWithNode(*ancestor, convertBlocksToInlines, Styl edMarkupAccumulator::DoesNotFullySelectNode); |
609 } | 610 } |
610 if (nodes) | 611 if (nodes) |
611 nodes->append(ancestor); | 612 nodes->append(ancestor); |
612 | 613 |
613 if (ancestor == specialCommonAncestor) | 614 if (ancestor == specialCommonAncestor) |
614 break; | 615 break; |
615 } | 616 } |
616 } | 617 } |
617 | 618 |
618 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. | 619 // FIXME: The interchange newline should be placed in the block that it's in , not after all of the content, unconditionally. |
619 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter( visibleEnd.previous())) | 620 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter( visibleEnd.previous())) |
620 accumulator.appendString(interchangeNewlineString); | 621 accumulator.appendString(interchangeNewlineString); |
621 | 622 |
622 return accumulator.takeResults(); | 623 return accumulator.takeResults(); |
623 } | 624 } |
624 | 625 |
625 String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc hange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveUR Ls, Node* constrainingAncestor) | 626 String createMarkup(const Range* range, Vector<const Node*>* nodes, EAnnotateFor Interchange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldRes olveURLs, Node* constrainingAncestor) |
626 { | 627 { |
627 if (!range) | 628 if (!range) |
628 return emptyString(); | 629 return emptyString(); |
629 | 630 |
630 Document& document = range->ownerDocument(); | 631 Document& document = range->ownerDocument(); |
631 const Range* updatedRange = range; | 632 const Range* updatedRange = range; |
632 | 633 |
633 return createMarkupInternal(document, range, updatedRange, nodes, shouldAnno tate, convertBlocksToInlines, shouldResolveURLs, constrainingAncestor); | 634 return createMarkupInternal(document, range, updatedRange, nodes, shouldAnno tate, convertBlocksToInlines, shouldResolveURLs, constrainingAncestor); |
634 } | 635 } |
635 | 636 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
725 if (specialCommonAncestor) | 726 if (specialCommonAncestor) |
726 fragment->appendChild(specialCommonAncestor); | 727 fragment->appendChild(specialCommonAncestor); |
727 else | 728 else |
728 fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); | 729 fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); |
729 | 730 |
730 trimFragment(fragment.get(), nodeBeforeContext.get(), nodeAfterContext.get() ); | 731 trimFragment(fragment.get(), nodeBeforeContext.get(), nodeAfterContext.get() ); |
731 | 732 |
732 return fragment; | 733 return fragment; |
733 } | 734 } |
734 | 735 |
735 String createMarkup(const Node* node, EChildrenOnly childrenOnly, Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, Vector<QualifiedName>* tagNamesToSkip) | 736 String createMarkup(const Node* node, EChildrenOnly childrenOnly, Vector<const N ode*>* nodes, EAbsoluteURLs shouldResolveURLs, Vector<QualifiedName>* tagNamesTo Skip) |
736 { | 737 { |
737 if (!node) | 738 if (!node) |
738 return ""; | 739 return ""; |
739 | 740 |
740 MarkupAccumulator accumulator(nodes, shouldResolveURLs); | 741 MarkupAccumulator accumulator(nodes, shouldResolveURLs); |
741 return accumulator.serializeNodes(const_cast<Node*>(node), childrenOnly, tag NamesToSkip); | 742 return accumulator.serializeNodes(*node, childrenOnly, tagNamesToSkip); |
742 } | 743 } |
743 | 744 |
744 static void fillContainerFromString(ContainerNode* paragraph, const String& stri ng) | 745 static void fillContainerFromString(ContainerNode* paragraph, const String& stri ng) |
745 { | 746 { |
746 Document& document = paragraph->document(); | 747 Document& document = paragraph->document(); |
747 | 748 |
748 if (string.isEmpty()) { | 749 if (string.isEmpty()) { |
749 paragraph->appendChild(createBlockPlaceholderElement(document)); | 750 paragraph->appendChild(createBlockPlaceholderElement(document)); |
750 return; | 751 return; |
751 } | 752 } |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1043 return; | 1044 return; |
1044 | 1045 |
1045 RefPtr<Text> textNode = toText(node.get()); | 1046 RefPtr<Text> textNode = toText(node.get()); |
1046 RefPtr<Text> textNext = toText(next); | 1047 RefPtr<Text> textNext = toText(next); |
1047 textNode->appendData(textNext->data()); | 1048 textNode->appendData(textNext->data()); |
1048 if (textNext->parentNode()) // Might have been removed by mutation event. | 1049 if (textNext->parentNode()) // Might have been removed by mutation event. |
1049 textNext->remove(exceptionState); | 1050 textNext->remove(exceptionState); |
1050 } | 1051 } |
1051 | 1052 |
1052 } | 1053 } |
OLD | NEW |