Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: Source/core/editing/markup.cpp

Issue 428823002: Use tighter typing in editing: markup (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/editing/markup.h ('k') | Source/core/html/HTMLElement.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 20 matching lines...) Expand all
31 31
32 #include "bindings/core/v8/ExceptionState.h" 32 #include "bindings/core/v8/ExceptionState.h"
33 #include "core/CSSPropertyNames.h" 33 #include "core/CSSPropertyNames.h"
34 #include "core/CSSValueKeywords.h" 34 #include "core/CSSValueKeywords.h"
35 #include "core/HTMLNames.h" 35 #include "core/HTMLNames.h"
36 #include "core/css/CSSPrimitiveValue.h" 36 #include "core/css/CSSPrimitiveValue.h"
37 #include "core/css/CSSValue.h" 37 #include "core/css/CSSValue.h"
38 #include "core/css/StylePropertySet.h" 38 #include "core/css/StylePropertySet.h"
39 #include "core/dom/CDATASection.h" 39 #include "core/dom/CDATASection.h"
40 #include "core/dom/ChildListMutationScope.h" 40 #include "core/dom/ChildListMutationScope.h"
41 #include "core/dom/Comment.h"
41 #include "core/dom/ContextFeatures.h" 42 #include "core/dom/ContextFeatures.h"
42 #include "core/dom/DocumentFragment.h" 43 #include "core/dom/DocumentFragment.h"
43 #include "core/dom/ElementTraversal.h" 44 #include "core/dom/ElementTraversal.h"
44 #include "core/dom/ExceptionCode.h" 45 #include "core/dom/ExceptionCode.h"
45 #include "core/dom/NodeTraversal.h" 46 #include "core/dom/NodeTraversal.h"
46 #include "core/dom/Range.h" 47 #include "core/dom/Range.h"
47 #include "core/editing/Editor.h" 48 #include "core/editing/Editor.h"
48 #include "core/editing/MarkupAccumulator.h" 49 #include "core/editing/MarkupAccumulator.h"
49 #include "core/editing/TextIterator.h" 50 #include "core/editing/TextIterator.h"
50 #include "core/editing/VisibleSelection.h" 51 #include "core/editing/VisibleSelection.h"
51 #include "core/editing/VisibleUnits.h" 52 #include "core/editing/VisibleUnits.h"
52 #include "core/editing/htmlediting.h" 53 #include "core/editing/htmlediting.h"
53 #include "core/frame/LocalFrame.h" 54 #include "core/frame/LocalFrame.h"
55 #include "core/html/HTMLAnchorElement.h"
54 #include "core/html/HTMLBRElement.h" 56 #include "core/html/HTMLBRElement.h"
55 #include "core/html/HTMLBodyElement.h" 57 #include "core/html/HTMLBodyElement.h"
58 #include "core/html/HTMLDivElement.h"
56 #include "core/html/HTMLElement.h" 59 #include "core/html/HTMLElement.h"
57 #include "core/html/HTMLQuoteElement.h" 60 #include "core/html/HTMLQuoteElement.h"
58 #include "core/html/HTMLSpanElement.h" 61 #include "core/html/HTMLSpanElement.h"
59 #include "core/html/HTMLTableCellElement.h" 62 #include "core/html/HTMLTableCellElement.h"
63 #include "core/html/HTMLTableElement.h"
60 #include "core/html/HTMLTextFormControlElement.h" 64 #include "core/html/HTMLTextFormControlElement.h"
61 #include "core/rendering/RenderObject.h" 65 #include "core/rendering/RenderObject.h"
62 #include "platform/weborigin/KURL.h" 66 #include "platform/weborigin/KURL.h"
63 #include "wtf/StdLibExtras.h" 67 #include "wtf/StdLibExtras.h"
64 #include "wtf/text/StringBuilder.h" 68 #include "wtf/text/StringBuilder.h"
65 69
66 namespace blink { 70 namespace blink {
67 71
68 using namespace HTMLNames; 72 using namespace HTMLNames;
69 73
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 changes[i].apply(); 130 changes[i].apply();
127 } 131 }
128 132
129 class StyledMarkupAccumulator FINAL : public MarkupAccumulator { 133 class StyledMarkupAccumulator FINAL : public MarkupAccumulator {
130 public: 134 public:
131 enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode }; 135 enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode };
132 136
133 StyledMarkupAccumulator(WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, EAbsoluteURLs, EAnnotateForInterchange, RawPtr<const Range>, Node* highestNodeTo BeSerialized = 0); 137 StyledMarkupAccumulator(WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, EAbsoluteURLs, EAnnotateForInterchange, RawPtr<const Range>, Node* highestNodeTo BeSerialized = 0);
134 Node* serializeNodes(Node* startNode, Node* pastEnd); 138 Node* serializeNodes(Node* startNode, Node* pastEnd);
135 void appendString(const String& s) { return MarkupAccumulator::appendString( s); } 139 void appendString(const String& s) { return MarkupAccumulator::appendString( s); }
136 void wrapWithNode(Node&, bool convertBlocksToInlines = false, RangeFullySele ctsNode = DoesFullySelectNode); 140 void wrapWithNode(ContainerNode&, bool convertBlocksToInlines = false, Range FullySelectsNode = DoesFullySelectNode);
137 void wrapWithStyleNode(StylePropertySet*, const Document&, bool isBlock = fa lse); 141 void wrapWithStyleNode(StylePropertySet*, const Document&, bool isBlock = fa lse);
138 String takeResults(); 142 String takeResults();
139 143
140 private: 144 private:
141 void appendStyleNodeOpenTag(StringBuilder&, StylePropertySet*, const Documen t&, bool isBlock = false); 145 void appendStyleNodeOpenTag(StringBuilder&, StylePropertySet*, const Documen t&, bool isBlock = false);
142 const String& styleNodeCloseTag(bool isBlock = false); 146 const String& styleNodeCloseTag(bool isBlock = false);
143 virtual void appendText(StringBuilder& out, Text&) OVERRIDE; 147 virtual void appendText(StringBuilder& out, Text&) OVERRIDE;
144 String renderedText(Node&, const Range*); 148 String renderedText(Node&, const Range*);
145 String stringValueForRange(const Node&, const Range*); 149 String stringValueForRange(const Node&, const Range*);
146 void appendElement(StringBuilder& out, Element&, bool addDisplayInline, Rang eFullySelectsNode); 150 void appendElement(StringBuilder& out, Element&, bool addDisplayInline, Rang eFullySelectsNode);
(...skipping 15 matching lines...) Expand all
162 RefPtrWillBeMember<EditingStyle> m_wrappingStyle; 166 RefPtrWillBeMember<EditingStyle> m_wrappingStyle;
163 }; 167 };
164 168
165 inline StyledMarkupAccumulator::StyledMarkupAccumulator(WillBeHeapVector<RawPtrW illBeMember<Node> >* nodes, EAbsoluteURLs shouldResolveURLs, EAnnotateForInterch ange shouldAnnotate, RawPtr<const Range> range, Node* highestNodeToBeSerialized) 169 inline StyledMarkupAccumulator::StyledMarkupAccumulator(WillBeHeapVector<RawPtrW illBeMember<Node> >* nodes, EAbsoluteURLs shouldResolveURLs, EAnnotateForInterch ange shouldAnnotate, RawPtr<const Range> range, Node* highestNodeToBeSerialized)
166 : MarkupAccumulator(nodes, shouldResolveURLs, range) 170 : MarkupAccumulator(nodes, shouldResolveURLs, range)
167 , m_shouldAnnotate(shouldAnnotate) 171 , m_shouldAnnotate(shouldAnnotate)
168 , m_highestNodeToBeSerialized(highestNodeToBeSerialized) 172 , m_highestNodeToBeSerialized(highestNodeToBeSerialized)
169 { 173 {
170 } 174 }
171 175
172 void StyledMarkupAccumulator::wrapWithNode(Node& node, bool convertBlocksToInlin es, RangeFullySelectsNode rangeFullySelectsNode) 176 void StyledMarkupAccumulator::wrapWithNode(ContainerNode& node, bool convertBloc ksToInlines, RangeFullySelectsNode rangeFullySelectsNode)
173 { 177 {
174 StringBuilder markup; 178 StringBuilder markup;
175 if (node.isElementNode()) 179 if (node.isElementNode())
176 appendElement(markup, toElement(node), convertBlocksToInlines && isBlock (&node), rangeFullySelectsNode); 180 appendElement(markup, toElement(node), convertBlocksToInlines && isBlock (&node), rangeFullySelectsNode);
177 else 181 else
178 appendStartMarkup(markup, node, 0); 182 appendStartMarkup(markup, node, 0);
179 m_reversedPrecedingMarkup.append(markup.toString()); 183 m_reversedPrecedingMarkup.append(markup.toString());
180 appendEndTag(node); 184 appendEndTag(node);
181 if (m_nodes) 185 if (m_nodes)
182 m_nodes->append(&node); 186 m_nodes->append(&node);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 254
251 if (wrappingSpan) 255 if (wrappingSpan)
252 out.append(styleNodeCloseTag()); 256 out.append(styleNodeCloseTag());
253 } 257 }
254 258
255 String StyledMarkupAccumulator::renderedText(Node& node, const Range* range) 259 String StyledMarkupAccumulator::renderedText(Node& node, const Range* range)
256 { 260 {
257 if (!node.isTextNode()) 261 if (!node.isTextNode())
258 return String(); 262 return String();
259 263
260 const Text& textNode = toText(node); 264 Text& textNode = toText(node);
261 unsigned startOffset = 0; 265 unsigned startOffset = 0;
262 unsigned endOffset = textNode.length(); 266 unsigned endOffset = textNode.length();
263 267
264 if (range && node == range->startContainer()) 268 if (range && textNode == range->startContainer())
265 startOffset = range->startOffset(); 269 startOffset = range->startOffset();
266 if (range && node == range->endContainer()) 270 if (range && textNode == range->endContainer())
267 endOffset = range->endOffset(); 271 endOffset = range->endOffset();
268 272
269 Position start = createLegacyEditingPosition(&node, startOffset); 273 Position start = createLegacyEditingPosition(&textNode, startOffset);
270 Position end = createLegacyEditingPosition(&node, endOffset); 274 Position end = createLegacyEditingPosition(&textNode, endOffset);
271 return plainText(Range::create(node.document(), start, end).get()); 275 return plainText(Range::create(textNode.document(), start, end).get());
272 } 276 }
273 277
274 String StyledMarkupAccumulator::stringValueForRange(const Node& node, const Rang e* range) 278 String StyledMarkupAccumulator::stringValueForRange(const Node& node, const Rang e* range)
275 { 279 {
276 if (!range) 280 if (!range)
277 return node.nodeValue(); 281 return node.nodeValue();
278 282
279 String str = node.nodeValue(); 283 String str = node.nodeValue();
280 if (node == range->endContainer()) 284 if (node == range->endContainer())
281 str.truncate(range->endOffset()); 285 str.truncate(range->endOffset());
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 } 361 }
358 } 362 }
359 363
360 364
361 return traverseNodesForSerialization(startNode, pastEnd, EmitString); 365 return traverseNodesForSerialization(startNode, pastEnd, EmitString);
362 } 366 }
363 367
364 Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, No de* pastEnd, NodeTraversalMode traversalMode) 368 Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, No de* pastEnd, NodeTraversalMode traversalMode)
365 { 369 {
366 const bool shouldEmit = traversalMode == EmitString; 370 const bool shouldEmit = traversalMode == EmitString;
367 WillBeHeapVector<RawPtrWillBeMember<Node> > ancestorsToClose; 371 WillBeHeapVector<RawPtrWillBeMember<ContainerNode> > ancestorsToClose;
368 Node* next; 372 Node* next;
369 Node* lastClosed = 0; 373 Node* lastClosed = 0;
370 for (Node* n = startNode; n != pastEnd; n = next) { 374 for (Node* n = startNode; n != pastEnd; n = next) {
371 // According to <rdar://problem/5730668>, it is possible for n to blow 375 // According to <rdar://problem/5730668>, it is possible for n to blow
372 // past pastEnd and become null here. This shouldn't be possible. 376 // past pastEnd and become null here. This shouldn't be possible.
373 // This null check will prevent crashes (but create too much markup) 377 // This null check will prevent crashes (but create too much markup)
374 // and the ASSERT will hopefully lead us to understanding the problem. 378 // and the ASSERT will hopefully lead us to understanding the problem.
375 ASSERT(n); 379 ASSERT(n);
376 if (!n) 380 if (!n)
377 break; 381 break;
378 382
379 next = NodeTraversal::next(*n); 383 next = NodeTraversal::next(*n);
380 bool openedTag = false; 384 bool openedTag = false;
381 385
382 if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd) 386 if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd)
383 // Don't write out empty block containers that aren't fully selected . 387 // Don't write out empty block containers that aren't fully selected .
384 continue; 388 continue;
385 389
386 if (!n->renderer() && !enclosingElementWithTag(firstPositionInOrBeforeNo de(n), selectTag) && m_shouldAnnotate != AnnotateForNavigationTransition) { 390 if (!n->renderer() && !enclosingElementWithTag(firstPositionInOrBeforeNo de(n), selectTag) && m_shouldAnnotate != AnnotateForNavigationTransition) {
387 next = NodeTraversal::nextSkippingChildren(*n); 391 next = NodeTraversal::nextSkippingChildren(*n);
388 // Don't skip over pastEnd. 392 // Don't skip over pastEnd.
389 if (pastEnd && pastEnd->isDescendantOf(n)) 393 if (pastEnd && pastEnd->isDescendantOf(n))
390 next = pastEnd; 394 next = pastEnd;
391 } else { 395 } else {
392 // Add the node to the markup if we're not skipping the descendants 396 // Add the node to the markup if we're not skipping the descendants
393 if (shouldEmit) 397 if (shouldEmit)
394 appendStartTag(*n); 398 appendStartTag(*n);
395 399
396 // If node has no children, close the tag now. 400 // If node has no children, close the tag now.
397 if (!n->hasChildren()) { 401 if (n->isContainerNode() && toContainerNode(n)->hasChildren()) {
402 openedTag = true;
403 ancestorsToClose.append(toContainerNode(n));
404 } else {
398 if (shouldEmit) 405 if (shouldEmit)
399 appendEndTag(*n); 406 appendEndTag(*n);
400 lastClosed = n; 407 lastClosed = n;
401 } else {
402 openedTag = true;
403 ancestorsToClose.append(n);
404 } 408 }
405 } 409 }
406 410
407 // 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. 411 // 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.
408 // FIXME: What happens if we just inserted open tag and reached the end? 412 // FIXME: What happens if we just inserted open tag and reached the end?
409 if (!openedTag && (!n->nextSibling() || next == pastEnd)) { 413 if (!openedTag && (!n->nextSibling() || next == pastEnd)) {
410 // Close up the ancestors. 414 // Close up the ancestors.
411 while (!ancestorsToClose.isEmpty()) { 415 while (!ancestorsToClose.isEmpty()) {
412 Node* ancestor = ancestorsToClose.last(); 416 ContainerNode* ancestor = ancestorsToClose.last();
413 ASSERT(ancestor); 417 ASSERT(ancestor);
414 if (next != pastEnd && next->isDescendantOf(ancestor)) 418 if (next != pastEnd && next->isDescendantOf(ancestor))
415 break; 419 break;
416 // Not at the end of the range, close ancestors up to sibling of next node. 420 // Not at the end of the range, close ancestors up to sibling of next node.
417 if (shouldEmit) 421 if (shouldEmit)
418 appendEndTag(*ancestor); 422 appendEndTag(*ancestor);
419 lastClosed = ancestor; 423 lastClosed = ancestor;
420 ancestorsToClose.removeLast(); 424 ancestorsToClose.removeLast();
421 } 425 }
422 426
(...skipping 18 matching lines...) Expand all
441 return lastClosed; 445 return lastClosed;
442 } 446 }
443 447
444 static bool isHTMLBlockElement(const Node* node) 448 static bool isHTMLBlockElement(const Node* node)
445 { 449 {
446 ASSERT(node); 450 ASSERT(node);
447 return isHTMLTableCellElement(*node) 451 return isHTMLTableCellElement(*node)
448 || isNonTableCellHTMLBlockElement(node); 452 || isNonTableCellHTMLBlockElement(node);
449 } 453 }
450 454
451 static ContainerNode* ancestorToRetainStructureAndAppearanceForBlock(Node* commo nAncestorBlock) 455 static HTMLElement* ancestorToRetainStructureAndAppearanceForBlock(Element* comm onAncestorBlock)
452 { 456 {
453 if (!commonAncestorBlock) 457 if (!commonAncestorBlock)
454 return 0; 458 return 0;
455 459
456 if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*comm onAncestorBlock)) { 460 if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*comm onAncestorBlock))
457 ContainerNode* table = commonAncestorBlock->parentNode(); 461 return Traversal<HTMLTableElement>::firstAncestor(*commonAncestorBlock);
458 while (table && !isHTMLTableElement(*table))
459 table = table->parentNode();
460
461 return table;
462 }
463 462
464 if (isNonTableCellHTMLBlockElement(commonAncestorBlock)) 463 if (isNonTableCellHTMLBlockElement(commonAncestorBlock))
465 return toHTMLElement(commonAncestorBlock); 464 return toHTMLElement(commonAncestorBlock);
466 465
467 return 0; 466 return 0;
468 } 467 }
469 468
470 static inline ContainerNode* ancestorToRetainStructureAndAppearance(Node* common Ancestor) 469 static inline HTMLElement* ancestorToRetainStructureAndAppearance(Node* commonAn cestor)
471 { 470 {
472 return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonA ncestor)); 471 return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonA ncestor));
473 } 472 }
474 473
475 static inline ContainerNode* ancestorToRetainStructureAndAppearanceWithNoRendere r(Node* commonAncestor) 474 static inline HTMLElement* ancestorToRetainStructureAndAppearanceWithNoRenderer( Node* commonAncestor)
476 { 475 {
477 Node* commonAncestorBlock = enclosingNodeOfType(firstPositionInOrBeforeNode( commonAncestor), isHTMLBlockElement); 476 HTMLElement* commonAncestorBlock = toHTMLElement(enclosingNodeOfType(firstPo sitionInOrBeforeNode(commonAncestor), isHTMLBlockElement));
478 return ancestorToRetainStructureAndAppearanceForBlock(commonAncestorBlock); 477 return ancestorToRetainStructureAndAppearanceForBlock(commonAncestorBlock);
479 } 478 }
480 479
481 static bool propertyMissingOrEqualToNone(StylePropertySet* style, CSSPropertyID propertyID) 480 static bool propertyMissingOrEqualToNone(StylePropertySet* style, CSSPropertyID propertyID)
482 { 481 {
483 if (!style) 482 if (!style)
484 return false; 483 return false;
485 RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(propertyID); 484 RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(propertyID);
486 if (!value) 485 if (!value)
487 return true; 486 return true;
488 if (!value->isPrimitiveValue()) 487 if (!value->isPrimitiveValue())
489 return false; 488 return false;
490 return toCSSPrimitiveValue(value.get())->getValueID() == CSSValueNone; 489 return toCSSPrimitiveValue(value.get())->getValueID() == CSSValueNone;
491 } 490 }
492 491
493 static bool needInterchangeNewlineAfter(const VisiblePosition& v) 492 static bool needInterchangeNewlineAfter(const VisiblePosition& v)
494 { 493 {
495 VisiblePosition next = v.next(); 494 VisiblePosition next = v.next();
496 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); 495 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode();
497 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); 496 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode();
498 // Add an interchange newline if a paragraph break is selected and a br won' t already be added to the markup to represent it. 497 // Add an interchange newline if a paragraph break is selected and a br won' t already be added to the markup to represent it.
499 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement( *upstreamNode) && upstreamNode == downstreamNode); 498 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement( *upstreamNode) && upstreamNode == downstreamNode);
500 } 499 }
501 500
502 static PassRefPtrWillBeRawPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(c onst Node* node) 501 static PassRefPtrWillBeRawPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(c onst HTMLElement* element)
503 { 502 {
504 if (!node->isHTMLElement()) 503 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin eStyle());
505 return nullptr;
506
507 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t o untangle 504 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t o untangle
508 // the non-const-ness of styleFromMatchedRulesForElement. 505 // the non-const-ness of styleFromMatchedRulesForElement.
509 HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); 506 style->mergeStyleFromRules(const_cast<HTMLElement*>(element));
510 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin eStyle());
511 style->mergeStyleFromRules(element);
512 return style.release(); 507 return style.release();
513 } 508 }
514 509
515 static bool isPresentationalHTMLElement(const Node* node) 510 static bool isPresentationalHTMLElement(const Node* node)
516 { 511 {
517 if (!node->isHTMLElement()) 512 if (!node->isHTMLElement())
518 return false; 513 return false;
519 514
520 const HTMLElement& element = toHTMLElement(*node); 515 const HTMLElement& element = toHTMLElement(*node);
521 return element.hasTagName(uTag) || element.hasTagName(sTag) || element.hasTa gName(strikeTag) 516 return element.hasTagName(uTag) || element.hasTagName(sTag) || element.hasTa gName(strikeTag)
522 || element.hasTagName(iTag) || element.hasTagName(emTag) || element.hasT agName(bTag) || element.hasTagName(strongTag); 517 || element.hasTagName(iTag) || element.hasTagName(emTag) || element.hasT agName(bTag) || element.hasTagName(strongTag);
523 } 518 }
524 519
525 static ContainerNode* highestAncestorToWrapMarkup(const Range* range, EAnnotateF orInterchange shouldAnnotate, Node* constrainingAncestor) 520 static HTMLElement* highestAncestorToWrapMarkup(const Range* range, EAnnotateFor Interchange shouldAnnotate, Node* constrainingAncestor)
526 { 521 {
527 Node* commonAncestor = range->commonAncestorContainer(); 522 Node* commonAncestor = range->commonAncestorContainer();
528 ASSERT(commonAncestor); 523 ASSERT(commonAncestor);
529 ContainerNode* specialCommonAncestor = 0; 524 HTMLElement* specialCommonAncestor = 0;
530 if (shouldAnnotate == AnnotateForInterchange) { 525 if (shouldAnnotate == AnnotateForInterchange) {
531 // Include ancestors that aren't completely inside the range but are req uired to retain 526 // Include ancestors that aren't completely inside the range but are req uired to retain
532 // the structure and appearance of the copied markup. 527 // the structure and appearance of the copied markup.
533 specialCommonAncestor = ancestorToRetainStructureAndAppearance(commonAnc estor); 528 specialCommonAncestor = ancestorToRetainStructureAndAppearance(commonAnc estor);
534 529
535 if (Node* parentListNode = enclosingNodeOfType(firstPositionInOrBeforeNo de(range->firstNode()), isListItem)) { 530 if (Node* parentListNode = enclosingNodeOfType(firstPositionInOrBeforeNo de(range->firstNode()), isListItem)) {
536 if (blink::areRangesEqual(VisibleSelection::selectionFromContentsOfN ode(parentListNode).toNormalizedRange().get(), range)) { 531 if (blink::areRangesEqual(VisibleSelection::selectionFromContentsOfN ode(parentListNode).toNormalizedRange().get(), range)) {
537 specialCommonAncestor = parentListNode->parentNode(); 532 ContainerNode* ancestor = parentListNode->parentNode();
538 while (specialCommonAncestor && !isListElement(specialCommonAnce stor)) 533 while (ancestor && !isHTMLListElement(ancestor))
539 specialCommonAncestor = specialCommonAncestor->parentNode(); 534 ancestor = ancestor->parentNode();
535 specialCommonAncestor = toHTMLElement(ancestor);
540 } 536 }
541 } 537 }
542 538
543 // Retain the Mail quote level by including all ancestor mail block quot es. 539 // Retain the Mail quote level by including all ancestor mail block quot es.
544 if (HTMLQuoteElement* highestMailBlockquote = toHTMLQuoteElement(highest EnclosingNodeOfType(firstPositionInOrBeforeNode(range->firstNode()), isMailHTMLB lockquoteElement, CanCrossEditingBoundary))) 540 if (HTMLQuoteElement* highestMailBlockquote = toHTMLQuoteElement(highest EnclosingNodeOfType(firstPositionInOrBeforeNode(range->firstNode()), isMailHTMLB lockquoteElement, CanCrossEditingBoundary)))
545 specialCommonAncestor = highestMailBlockquote; 541 specialCommonAncestor = highestMailBlockquote;
546 } 542 }
547 543
548 Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : common Ancestor; 544 Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : common Ancestor;
549 if (checkAncestor->renderer()) { 545 if (checkAncestor->renderer()) {
550 HTMLElement* newSpecialCommonAncestor = toHTMLElement(highestEnclosingNo deOfType(firstPositionInNode(checkAncestor), &isPresentationalHTMLElement, CanCr ossEditingBoundary, constrainingAncestor)); 546 HTMLElement* newSpecialCommonAncestor = toHTMLElement(highestEnclosingNo deOfType(firstPositionInNode(checkAncestor), &isPresentationalHTMLElement, CanCr ossEditingBoundary, constrainingAncestor));
551 if (newSpecialCommonAncestor) 547 if (newSpecialCommonAncestor)
552 specialCommonAncestor = newSpecialCommonAncestor; 548 specialCommonAncestor = newSpecialCommonAncestor;
553 } 549 }
554 550
555 // If a single tab is selected, commonAncestor will be a text node inside a tab span. 551 // If a single tab is selected, commonAncestor will be a text node inside a tab span.
556 // If two or more tabs are selected, commonAncestor will be the tab span. 552 // If two or more tabs are selected, commonAncestor will be the tab span.
557 // In either case, if there is a specialCommonAncestor already, it will nece ssarily be above 553 // In either case, if there is a specialCommonAncestor already, it will nece ssarily be above
558 // any tab span that needs to be included. 554 // any tab span that needs to be included.
559 if (!specialCommonAncestor && isTabSpanTextNode(commonAncestor)) 555 if (!specialCommonAncestor && isTabHTMLSpanElementTextNode(commonAncestor))
560 specialCommonAncestor = commonAncestor->parentNode(); 556 specialCommonAncestor = toHTMLSpanElement(commonAncestor->parentNode());
561 if (!specialCommonAncestor && isTabSpanElement(commonAncestor)) 557 if (!specialCommonAncestor && isTabHTMLSpanElement(commonAncestor))
562 specialCommonAncestor = toElement(commonAncestor); 558 specialCommonAncestor = toHTMLSpanElement(commonAncestor);
563 559
564 if (Element* enclosingAnchor = enclosingElementWithTag(firstPositionInNode(s pecialCommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) 560 if (HTMLAnchorElement* enclosingAnchor = toHTMLAnchorElement(enclosingElemen tWithTag(firstPositionInNode(specialCommonAncestor ? specialCommonAncestor : com monAncestor), aTag)))
565 specialCommonAncestor = enclosingAnchor; 561 specialCommonAncestor = enclosingAnchor;
566 562
567 return specialCommonAncestor; 563 return specialCommonAncestor;
568 } 564 }
569 565
570 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha nge? 566 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha nge?
571 // FIXME: At least, annotation and style info should probably not be included in range.markupString() 567 // FIXME: At least, annotation and style info should probably not be included in range.markupString()
572 static String createMarkupInternal(Document& document, const Range* range, const Range* updatedRange, WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, 568 static String createMarkupInternal(Document& document, const Range* range, const Range* updatedRange, WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes,
573 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu teURLs shouldResolveURLs, Node* constrainingAncestor) 569 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu teURLs shouldResolveURLs, Node* constrainingAncestor)
574 { 570 {
575 ASSERT(range); 571 ASSERT(range);
576 ASSERT(updatedRange); 572 ASSERT(updatedRange);
577 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">")); 573 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\"" AppleInterchangeNewline "\">"));
578 574
579 bool collapsed = updatedRange->collapsed(); 575 bool collapsed = updatedRange->collapsed();
580 if (collapsed) 576 if (collapsed)
581 return emptyString(); 577 return emptyString();
582 Node* commonAncestor = updatedRange->commonAncestorContainer(); 578 Node* commonAncestor = updatedRange->commonAncestorContainer();
583 if (!commonAncestor) 579 if (!commonAncestor)
584 return emptyString(); 580 return emptyString();
585 581
586 document.updateLayoutIgnorePendingStylesheets(); 582 document.updateLayoutIgnorePendingStylesheets();
587 583
588 Element* body = enclosingElementWithTag(firstPositionInNode(commonAncestor), bodyTag); 584 HTMLBodyElement* body = toHTMLBodyElement(enclosingElementWithTag(firstPosit ionInNode(commonAncestor), bodyTag));
589 Node* fullySelectedRoot = 0; 585 HTMLBodyElement* fullySelectedRoot = 0;
590 // FIXME: Do this for all fully selected blocks, not just the body. 586 // FIXME: Do this for all fully selected blocks, not just the body.
591 if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(bod y).toNormalizedRange().get(), range)) 587 if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(bod y).toNormalizedRange().get(), range))
592 fullySelectedRoot = body; 588 fullySelectedRoot = body;
593 ContainerNode* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRa nge, shouldAnnotate, constrainingAncestor); 589 HTMLElement* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRang e, shouldAnnotate, constrainingAncestor);
594 StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate , updatedRange, specialCommonAncestor); 590 StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate , updatedRange, specialCommonAncestor);
595 Node* pastEnd = updatedRange->pastLastNode(); 591 Node* pastEnd = updatedRange->pastLastNode();
596 592
597 Node* startNode = updatedRange->firstNode(); 593 Node* startNode = updatedRange->firstNode();
598 VisiblePosition visibleStart(updatedRange->startPosition(), VP_DEFAULT_AFFIN ITY); 594 VisiblePosition visibleStart(updatedRange->startPosition(), VP_DEFAULT_AFFIN ITY);
599 VisiblePosition visibleEnd(updatedRange->endPosition(), VP_DEFAULT_AFFINITY) ; 595 VisiblePosition visibleEnd(updatedRange->endPosition(), VP_DEFAULT_AFFINITY) ;
600 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter( visibleStart)) { 596 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter( visibleStart)) {
601 if (visibleStart == visibleEnd.previous()) 597 if (visibleStart == visibleEnd.previous())
602 return interchangeNewlineString; 598 return interchangeNewlineString;
603 599
604 accumulator.appendString(interchangeNewlineString); 600 accumulator.appendString(interchangeNewlineString);
605 startNode = visibleStart.next().deepEquivalent().deprecatedNode(); 601 startNode = visibleStart.next().deepEquivalent().deprecatedNode();
606 602
607 if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, AS SERT_NO_EXCEPTION) >= 0) 603 if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, AS SERT_NO_EXCEPTION) >= 0)
608 return interchangeNewlineString; 604 return interchangeNewlineString;
609 } 605 }
610 606
611 Node* lastClosed = accumulator.serializeNodes(startNode, pastEnd); 607 Node* lastClosed = accumulator.serializeNodes(startNode, pastEnd);
612 608
613 if (specialCommonAncestor && lastClosed) { 609 if (specialCommonAncestor && lastClosed) {
614 // Also include all of the ancestors of lastClosed up to this special an cestor. 610 // Also include all of the ancestors of lastClosed up to this special an cestor.
615 for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ances tor = ancestor->parentNode()) { 611 for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ances tor = ancestor->parentNode()) {
616 if (ancestor == fullySelectedRoot && !convertBlocksToInlines) { 612 if (ancestor == fullySelectedRoot && !convertBlocksToInlines) {
617 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot); 613 RefPtrWillBeRawPtr<EditingStyle> fullySelectedRootStyle = styleF romMatchedRulesAndInlineDecl(fullySelectedRoot);
618 614
619 // Bring the background attribute over, but not as an attribute because a background attribute on a div 615 // Bring the background attribute over, but not as an attribute because a background attribute on a div
620 // appears to have no effect. 616 // appears to have no effect.
621 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage)) 617 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundI mage))
622 && toElement(fullySelectedRoot)->hasAttribute(backgroundAttr )) 618 && fullySelectedRoot->hasAttribute(backgroundAttr))
623 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr ) + "')"); 619 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack groundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')");
624 620
625 if (fullySelectedRootStyle->style()) { 621 if (fullySelectedRootStyle->style()) {
626 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup(). 622 // Reset the CSS properties to avoid an assertion error in a ddStyleMarkup().
627 // This assertion is caused at least when we select all text of a <body> element whose 623 // This assertion is caused at least when we select all text of a <body> element whose
628 // 'text-decoration' property is "inherit", and copy it. 624 // 'text-decoration' property is "inherit", and copy it.
629 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration)) 625 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyTextDecoration))
630 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone); 626 fullySelectedRootStyle->style()->setProperty(CSSProperty TextDecoration, CSSValueNone);
631 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect)) 627 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st yle(), CSSPropertyWebkitTextDecorationsInEffect))
632 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone); 628 fullySelectedRootStyle->style()->setProperty(CSSProperty WebkitTextDecorationsInEffect, CSSValueNone);
633 accumulator.wrapWithStyleNode(fullySelectedRootStyle->style( ), document, true); 629 accumulator.wrapWithStyleNode(fullySelectedRootStyle->style( ), document, true);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 fragment->parseHTML(markup, fakeBody.get(), parserContentPolicy); 668 fragment->parseHTML(markup, fakeBody.get(), parserContentPolicy);
673 669
674 if (!baseURL.isEmpty() && baseURL != blankURL() && baseURL != document.baseU RL()) 670 if (!baseURL.isEmpty() && baseURL != blankURL() && baseURL != document.baseU RL())
675 completeURLs(*fragment, baseURL); 671 completeURLs(*fragment, baseURL);
676 672
677 return fragment.release(); 673 return fragment.release();
678 } 674 }
679 675
680 static const char fragmentMarkerTag[] = "webkit-fragment-marker"; 676 static const char fragmentMarkerTag[] = "webkit-fragment-marker";
681 677
682 static bool findNodesSurroundingContext(Document* document, RefPtrWillBeRawPtr<N ode>& nodeBeforeContext, RefPtrWillBeRawPtr<Node>& nodeAfterContext) 678 static bool findNodesSurroundingContext(Document* document, RefPtrWillBeRawPtr<C omment>& nodeBeforeContext, RefPtrWillBeRawPtr<Comment>& nodeAfterContext)
683 { 679 {
684 for (Node* node = document->firstChild(); node; node = NodeTraversal::next(* node)) { 680 for (Node* node = document->firstChild(); node; node = NodeTraversal::next(* node)) {
685 if (node->nodeType() == Node::COMMENT_NODE && toCharacterData(node)->dat a() == fragmentMarkerTag) { 681 if (node->nodeType() == Node::COMMENT_NODE && toComment(node)->data() == fragmentMarkerTag) {
686 if (!nodeBeforeContext) 682 if (!nodeBeforeContext)
687 nodeBeforeContext = node; 683 nodeBeforeContext = toComment(node);
688 else { 684 else {
689 nodeAfterContext = node; 685 nodeAfterContext = toComment(node);
690 return true; 686 return true;
691 } 687 }
692 } 688 }
693 } 689 }
694 return false; 690 return false;
695 } 691 }
696 692
697 static void trimFragment(DocumentFragment* fragment, Node* nodeBeforeContext, No de* nodeAfterContext) 693 static void trimFragment(DocumentFragment* fragment, Comment* nodeBeforeContext, Comment* nodeAfterContext)
698 { 694 {
699 RefPtrWillBeRawPtr<Node> next = nullptr; 695 RefPtrWillBeRawPtr<Node> next = nullptr;
700 for (RefPtrWillBeRawPtr<Node> node = fragment->firstChild(); node; node = ne xt) { 696 for (RefPtrWillBeRawPtr<Node> node = fragment->firstChild(); node; node = ne xt) {
701 if (nodeBeforeContext->isDescendantOf(node.get())) { 697 if (nodeBeforeContext->isDescendantOf(node.get())) {
702 next = NodeTraversal::next(*node); 698 next = NodeTraversal::next(*node);
703 continue; 699 continue;
704 } 700 }
705 next = NodeTraversal::nextSkippingChildren(*node); 701 next = NodeTraversal::nextSkippingChildren(*node);
706 ASSERT(!node->contains(nodeAfterContext)); 702 ASSERT(!node->contains(nodeAfterContext));
707 node->parentNode()->removeChild(node.get(), ASSERT_NO_EXCEPTION); 703 node->parentNode()->removeChild(node.get(), ASSERT_NO_EXCEPTION);
(...skipping 21 matching lines...) Expand all
729 taggedMarkup.append(markup.substring(fragmentEnd)); 725 taggedMarkup.append(markup.substring(fragmentEnd));
730 726
731 RefPtrWillBeRawPtr<DocumentFragment> taggedFragment = createFragmentFromMark up(document, taggedMarkup.toString(), baseURL, parserContentPolicy); 727 RefPtrWillBeRawPtr<DocumentFragment> taggedFragment = createFragmentFromMark up(document, taggedMarkup.toString(), baseURL, parserContentPolicy);
732 RefPtrWillBeRawPtr<Document> taggedDocument = Document::create(); 728 RefPtrWillBeRawPtr<Document> taggedDocument = Document::create();
733 taggedDocument->setContextFeatures(document.contextFeatures()); 729 taggedDocument->setContextFeatures(document.contextFeatures());
734 730
735 // FIXME: It's not clear what this code is trying to do. It puts nodes as di rect children of a 731 // FIXME: It's not clear what this code is trying to do. It puts nodes as di rect children of a
736 // Document that are not normally allowed by using the parser machinery. 732 // Document that are not normally allowed by using the parser machinery.
737 taggedDocument->parserTakeAllChildrenFrom(*taggedFragment); 733 taggedDocument->parserTakeAllChildrenFrom(*taggedFragment);
738 734
739 RefPtrWillBeRawPtr<Node> nodeBeforeContext = nullptr; 735 RefPtrWillBeRawPtr<Comment> nodeBeforeContext = nullptr;
740 RefPtrWillBeRawPtr<Node> nodeAfterContext = nullptr; 736 RefPtrWillBeRawPtr<Comment> nodeAfterContext = nullptr;
741 if (!findNodesSurroundingContext(taggedDocument.get(), nodeBeforeContext, no deAfterContext)) 737 if (!findNodesSurroundingContext(taggedDocument.get(), nodeBeforeContext, no deAfterContext))
742 return nullptr; 738 return nullptr;
743 739
744 RefPtrWillBeRawPtr<Range> range = Range::create(*taggedDocument.get(), 740 RefPtrWillBeRawPtr<Range> range = Range::create(*taggedDocument.get(),
745 positionAfterNode(nodeBeforeContext.get()).parentAnchoredEquivalent(), 741 positionAfterNode(nodeBeforeContext.get()).parentAnchoredEquivalent(),
746 positionBeforeNode(nodeAfterContext.get()).parentAnchoredEquivalent()); 742 positionBeforeNode(nodeAfterContext.get()).parentAnchoredEquivalent());
747 743
748 Node* commonAncestor = range->commonAncestorContainer(); 744 Node* commonAncestor = range->commonAncestorContainer();
749 Node* specialCommonAncestor = ancestorToRetainStructureAndAppearanceWithNoRe nderer(commonAncestor); 745 HTMLElement* specialCommonAncestor = ancestorToRetainStructureAndAppearanceW ithNoRenderer(commonAncestor);
750 746
751 // When there's a special common ancestor outside of the fragment, we must i nclude it as well to 747 // When there's a special common ancestor outside of the fragment, we must i nclude it as well to
752 // preserve the structure and appearance of the fragment. For example, if th e fragment contains 748 // preserve the structure and appearance of the fragment. For example, if th e fragment contains
753 // TD, we need to include the enclosing TABLE tag as well. 749 // TD, we need to include the enclosing TABLE tag as well.
754 RefPtrWillBeRawPtr<DocumentFragment> fragment = DocumentFragment::create(doc ument); 750 RefPtrWillBeRawPtr<DocumentFragment> fragment = DocumentFragment::create(doc ument);
755 if (specialCommonAncestor) 751 if (specialCommonAncestor)
756 fragment->appendChild(specialCommonAncestor); 752 fragment->appendChild(specialCommonAncestor);
757 else 753 else
758 fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor)); 754 fragment->parserTakeAllChildrenFrom(toContainerNode(*commonAncestor));
759 755
(...skipping 29 matching lines...) Expand all
789 size_t numEntries = tabList.size(); 785 size_t numEntries = tabList.size();
790 for (size_t i = 0; i < numEntries; ++i) { 786 for (size_t i = 0; i < numEntries; ++i) {
791 const String& s = tabList[i]; 787 const String& s = tabList[i];
792 788
793 // append the non-tab textual part 789 // append the non-tab textual part
794 if (!s.isEmpty()) { 790 if (!s.isEmpty()) {
795 if (!tabText.isEmpty()) { 791 if (!tabText.isEmpty()) {
796 paragraph->appendChild(createTabSpanElement(document, tabText.to String())); 792 paragraph->appendChild(createTabSpanElement(document, tabText.to String()));
797 tabText.clear(); 793 tabText.clear();
798 } 794 }
799 RefPtrWillBeRawPtr<Node> textNode = document.createTextNode(stringWi thRebalancedWhitespace(s, first, i + 1 == numEntries)); 795 RefPtrWillBeRawPtr<Text> textNode = document.createTextNode(stringWi thRebalancedWhitespace(s, first, i + 1 == numEntries));
800 paragraph->appendChild(textNode.release()); 796 paragraph->appendChild(textNode.release());
801 } 797 }
802 798
803 // there is a tab after every entry, except the last entry 799 // there is a tab after every entry, except the last entry
804 // (if the last character is a tab, the list gets an extra empty entry) 800 // (if the last character is a tab, the list gets an extra empty entry)
805 if (i + 1 != numEntries) 801 if (i + 1 != numEntries)
806 tabText.append('\t'); 802 tabText.append('\t');
807 else if (!tabText.isEmpty()) 803 else if (!tabText.isEmpty())
808 paragraph->appendChild(createTabSpanElement(document, tabText.toStri ng())); 804 paragraph->appendChild(createTabSpanElement(document, tabText.toStri ng()));
809 805
810 first = false; 806 first = false;
811 } 807 }
812 } 808 }
813 809
814 bool isPlainTextMarkup(Node* node) 810 bool isPlainTextMarkup(Node* node)
815 { 811 {
816 ASSERT(node); 812 ASSERT(node);
817 if (!node->isElementNode()) 813 if (!isHTMLDivElement(*node))
818 return false; 814 return false;
819 815
820 Element* element = toElement(node); 816 HTMLDivElement& element = toHTMLDivElement(*node);
821 if (!isHTMLDivElement(*element) || !element->hasAttributes()) 817 if (!element.hasAttributes())
822 return false; 818 return false;
823 819
824 if (element->hasOneChild() && (element->firstChild()->isTextNode() || elemen t->firstChild()->hasChildren())) 820 if (element.hasOneChild())
825 return true; 821 return element.firstChild()->isTextNode() || element.firstChild()->hasCh ildren();
826 822
827 return element->hasChildCount(2) && isTabSpanTextNode(element->firstChild()- >firstChild()) && element->lastChild()->isTextNode(); 823 return element.hasChildCount(2) && isTabHTMLSpanElementTextNode(element.firs tChild()->firstChild()) && element.lastChild()->isTextNode();
828 } 824 }
829 825
830 static bool shouldPreserveNewline(const Range& range) 826 static bool shouldPreserveNewline(const Range& range)
831 { 827 {
832 if (Node* node = range.firstNode()) { 828 if (Node* node = range.firstNode()) {
833 if (RenderObject* renderer = node->renderer()) 829 if (RenderObject* renderer = node->renderer())
834 return renderer->style()->preserveNewline(); 830 return renderer->style()->preserveNewline();
835 } 831 }
836 832
837 if (Node* node = range.startPosition().anchorNode()) { 833 if (Node* node = range.startPosition().anchorNode()) {
(...skipping 29 matching lines...) Expand all
867 return fragment.release(); 863 return fragment.release();
868 } 864 }
869 865
870 // A string with no newlines gets added inline, rather than being put into a paragraph. 866 // A string with no newlines gets added inline, rather than being put into a paragraph.
871 if (string.find('\n') == kNotFound) { 867 if (string.find('\n') == kNotFound) {
872 fillContainerFromString(fragment.get(), string); 868 fillContainerFromString(fragment.get(), string);
873 return fragment.release(); 869 return fragment.release();
874 } 870 }
875 871
876 // Break string into paragraphs. Extra line breaks turn into empty paragraph s. 872 // Break string into paragraphs. Extra line breaks turn into empty paragraph s.
877 Node* blockNode = enclosingBlock(context->firstNode()); 873 Element* block = enclosingBlock(context->firstNode());
878 Element* block = toElement(blockNode); 874 bool useClonesOfEnclosingBlock = block
879 bool useClonesOfEnclosingBlock = blockNode
880 && blockNode->isElementNode()
881 && !isHTMLBodyElement(*block) 875 && !isHTMLBodyElement(*block)
882 && !isHTMLHtmlElement(*block) 876 && !isHTMLHtmlElement(*block)
883 && block != editableRootForPosition(context->startPosition()); 877 && block != editableRootForPosition(context->startPosition());
884 bool useLineBreak = enclosingTextFormControl(context->startPosition()); 878 bool useLineBreak = enclosingTextFormControl(context->startPosition());
885 879
886 Vector<String> list; 880 Vector<String> list;
887 string.split('\n', true, list); // true gets us empty strings in the list 881 string.split('\n', true, list); // true gets us empty strings in the list
888 size_t numLines = list.size(); 882 size_t numLines = list.size();
889 for (size_t i = 0; i < numLines; ++i) { 883 for (size_t i = 0; i < numLines; ++i) {
890 const String& s = list[i]; 884 const String& s = list[i];
(...skipping 22 matching lines...) Expand all
913 { 907 {
914 if (!node) 908 if (!node)
915 return String(); 909 return String();
916 910
917 LocalFrame* frame = node->document().frame(); 911 LocalFrame* frame = node->document().frame();
918 if (!frame) 912 if (!frame)
919 return String(); 913 return String();
920 914
921 // FIXME: This is never "for interchange". Is that right? 915 // FIXME: This is never "for interchange". Is that right?
922 String markupString = createMarkup(node, IncludeNode, 0); 916 String markupString = createMarkup(node, IncludeNode, 0);
923 Node::NodeType nodeType = node->nodeType(); 917 if (!node->isDocumentNode() && !node->isDocumentTypeNode())
924 if (nodeType != Node::DOCUMENT_NODE && !node->isDocumentTypeNode())
925 markupString = frame->documentTypeString() + markupString; 918 markupString = frame->documentTypeString() + markupString;
926 919
927 return markupString; 920 return markupString;
928 } 921 }
929 922
930 String urlToMarkup(const KURL& url, const String& title) 923 String urlToMarkup(const KURL& url, const String& title)
931 { 924 {
932 StringBuilder markup; 925 StringBuilder markup;
933 markup.appendLiteral("<a href=\""); 926 markup.appendLiteral("<a href=\"");
934 markup.append(url.string()); 927 markup.append(url.string());
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1091 // FIXME: No need to replace the child it is a text node and its contents ar e already == text. 1084 // FIXME: No need to replace the child it is a text node and its contents ar e already == text.
1092 if (containerNode->hasOneChild()) { 1085 if (containerNode->hasOneChild()) {
1093 containerNode->replaceChild(textNode.release(), containerNode->firstChil d(), exceptionState); 1086 containerNode->replaceChild(textNode.release(), containerNode->firstChil d(), exceptionState);
1094 return; 1087 return;
1095 } 1088 }
1096 1089
1097 containerNode->removeChildren(); 1090 containerNode->removeChildren();
1098 containerNode->appendChild(textNode.release(), exceptionState); 1091 containerNode->appendChild(textNode.release(), exceptionState);
1099 } 1092 }
1100 1093
1101 void mergeWithNextTextNode(PassRefPtrWillBeRawPtr<Node> node, ExceptionState& ex ceptionState) 1094 void mergeWithNextTextNode(Text* textNode, ExceptionState& exceptionState)
1102 { 1095 {
1103 ASSERT(node && node->isTextNode()); 1096 ASSERT(textNode);
1104 Node* next = node->nextSibling(); 1097 Node* next = textNode->nextSibling();
1105 if (!next || !next->isTextNode()) 1098 if (!next || !next->isTextNode())
1106 return; 1099 return;
1107 1100
1108 RefPtrWillBeRawPtr<Text> textNode = toText(node.get());
1109 RefPtrWillBeRawPtr<Text> textNext = toText(next); 1101 RefPtrWillBeRawPtr<Text> textNext = toText(next);
1110 textNode->appendData(textNext->data()); 1102 textNode->appendData(textNext->data());
1111 if (textNext->parentNode()) // Might have been removed by mutation event. 1103 if (textNext->parentNode()) // Might have been removed by mutation event.
1112 textNext->remove(exceptionState); 1104 textNext->remove(exceptionState);
1113 } 1105 }
1114 1106
1115 String createStyledMarkupForNavigationTransition(Node* node) 1107 String createStyledMarkupForNavigationTransition(Node* node)
1116 { 1108 {
1117 node->document().updateLayoutIgnorePendingStylesheets(); 1109 node->document().updateLayoutIgnorePendingStylesheets();
1118 1110
1119 StyledMarkupAccumulator accumulator(0, ResolveAllURLs, AnnotateForNavigation Transition, nullptr, 0); 1111 StyledMarkupAccumulator accumulator(0, ResolveAllURLs, AnnotateForNavigation Transition, nullptr, 0);
1120 accumulator.serializeNodes(node, NodeTraversal::nextSkippingChildren(*node)) ; 1112 accumulator.serializeNodes(node, NodeTraversal::nextSkippingChildren(*node)) ;
1121 1113
1122 static const char* documentMarkup = "<!DOCTYPE html><meta name=\"viewport\" content=\"width=device-width, user-scalable=0\">"; 1114 static const char* documentMarkup = "<!DOCTYPE html><meta name=\"viewport\" content=\"width=device-width, user-scalable=0\">";
1123 return documentMarkup + accumulator.takeResults(); 1115 return documentMarkup + accumulator.takeResults();
1124 } 1116 }
1125 1117
1126 } 1118 }
OLDNEW
« no previous file with comments | « Source/core/editing/markup.h ('k') | Source/core/html/HTMLElement.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698