Chromium Code Reviews| 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 |