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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 #include "core/editing/Editor.h" | 47 #include "core/editing/Editor.h" |
48 #include "core/editing/MarkupAccumulator.h" | 48 #include "core/editing/MarkupAccumulator.h" |
49 #include "core/editing/TextIterator.h" | 49 #include "core/editing/TextIterator.h" |
50 #include "core/editing/VisibleSelection.h" | 50 #include "core/editing/VisibleSelection.h" |
51 #include "core/editing/VisibleUnits.h" | 51 #include "core/editing/VisibleUnits.h" |
52 #include "core/editing/htmlediting.h" | 52 #include "core/editing/htmlediting.h" |
53 #include "core/frame/LocalFrame.h" | 53 #include "core/frame/LocalFrame.h" |
54 #include "core/html/HTMLBRElement.h" | 54 #include "core/html/HTMLBRElement.h" |
55 #include "core/html/HTMLBodyElement.h" | 55 #include "core/html/HTMLBodyElement.h" |
56 #include "core/html/HTMLElement.h" | 56 #include "core/html/HTMLElement.h" |
| 57 #include "core/html/HTMLQuoteElement.h" |
57 #include "core/html/HTMLSpanElement.h" | 58 #include "core/html/HTMLSpanElement.h" |
58 #include "core/html/HTMLTableCellElement.h" | 59 #include "core/html/HTMLTableCellElement.h" |
59 #include "core/html/HTMLTextFormControlElement.h" | 60 #include "core/html/HTMLTextFormControlElement.h" |
60 #include "core/rendering/RenderObject.h" | 61 #include "core/rendering/RenderObject.h" |
61 #include "platform/weborigin/KURL.h" | 62 #include "platform/weborigin/KURL.h" |
62 #include "wtf/StdLibExtras.h" | 63 #include "wtf/StdLibExtras.h" |
63 #include "wtf/text/StringBuilder.h" | 64 #include "wtf/text/StringBuilder.h" |
64 | 65 |
65 namespace blink { | 66 namespace blink { |
66 | 67 |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 return lastClosed; | 441 return lastClosed; |
441 } | 442 } |
442 | 443 |
443 static bool isHTMLBlockElement(const Node* node) | 444 static bool isHTMLBlockElement(const Node* node) |
444 { | 445 { |
445 ASSERT(node); | 446 ASSERT(node); |
446 return isHTMLTableCellElement(*node) | 447 return isHTMLTableCellElement(*node) |
447 || isNonTableCellHTMLBlockElement(node); | 448 || isNonTableCellHTMLBlockElement(node); |
448 } | 449 } |
449 | 450 |
450 static Node* ancestorToRetainStructureAndAppearanceForBlock(Node* commonAncestor
Block) | 451 static ContainerNode* ancestorToRetainStructureAndAppearanceForBlock(Node* commo
nAncestorBlock) |
451 { | 452 { |
452 if (!commonAncestorBlock) | 453 if (!commonAncestorBlock) |
453 return 0; | 454 return 0; |
454 | 455 |
455 if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*comm
onAncestorBlock)) { | 456 if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*comm
onAncestorBlock)) { |
456 ContainerNode* table = commonAncestorBlock->parentNode(); | 457 ContainerNode* table = commonAncestorBlock->parentNode(); |
457 while (table && !isHTMLTableElement(*table)) | 458 while (table && !isHTMLTableElement(*table)) |
458 table = table->parentNode(); | 459 table = table->parentNode(); |
459 | 460 |
460 return table; | 461 return table; |
461 } | 462 } |
462 | 463 |
463 if (isNonTableCellHTMLBlockElement(commonAncestorBlock)) | 464 if (isNonTableCellHTMLBlockElement(commonAncestorBlock)) |
464 return commonAncestorBlock; | 465 return toHTMLElement(commonAncestorBlock); |
465 | 466 |
466 return 0; | 467 return 0; |
467 } | 468 } |
468 | 469 |
469 static inline Node* ancestorToRetainStructureAndAppearance(Node* commonAncestor) | 470 static inline ContainerNode* ancestorToRetainStructureAndAppearance(Node* common
Ancestor) |
470 { | 471 { |
471 return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonA
ncestor)); | 472 return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonA
ncestor)); |
472 } | 473 } |
473 | 474 |
474 static inline Node* ancestorToRetainStructureAndAppearanceWithNoRenderer(Node* c
ommonAncestor) | 475 static inline ContainerNode* ancestorToRetainStructureAndAppearanceWithNoRendere
r(Node* commonAncestor) |
475 { | 476 { |
476 Node* commonAncestorBlock = enclosingNodeOfType(firstPositionInOrBeforeNode(
commonAncestor), isHTMLBlockElement); | 477 Node* commonAncestorBlock = enclosingNodeOfType(firstPositionInOrBeforeNode(
commonAncestor), isHTMLBlockElement); |
477 return ancestorToRetainStructureAndAppearanceForBlock(commonAncestorBlock); | 478 return ancestorToRetainStructureAndAppearanceForBlock(commonAncestorBlock); |
478 } | 479 } |
479 | 480 |
480 static bool propertyMissingOrEqualToNone(StylePropertySet* style, CSSPropertyID
propertyID) | 481 static bool propertyMissingOrEqualToNone(StylePropertySet* style, CSSPropertyID
propertyID) |
481 { | 482 { |
482 if (!style) | 483 if (!style) |
483 return false; | 484 return false; |
484 RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(propertyID); | 485 RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(propertyID); |
(...skipping 19 matching lines...) Expand all Loading... |
504 return nullptr; | 505 return nullptr; |
505 | 506 |
506 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t
o untangle | 507 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t
o untangle |
507 // the non-const-ness of styleFromMatchedRulesForElement. | 508 // the non-const-ness of styleFromMatchedRulesForElement. |
508 HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); | 509 HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); |
509 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin
eStyle()); | 510 RefPtrWillBeRawPtr<EditingStyle> style = EditingStyle::create(element->inlin
eStyle()); |
510 style->mergeStyleFromRules(element); | 511 style->mergeStyleFromRules(element); |
511 return style.release(); | 512 return style.release(); |
512 } | 513 } |
513 | 514 |
514 static bool isElementPresentational(const Node* node) | 515 static bool isPresentationalHTMLElement(const Node* node) |
515 { | 516 { |
516 return node->hasTagName(uTag) || node->hasTagName(sTag) || node->hasTagName(
strikeTag) | 517 if (!node->isHTMLElement()) |
517 || node->hasTagName(iTag) || node->hasTagName(emTag) || node->hasTagName
(bTag) || node->hasTagName(strongTag); | 518 return false; |
| 519 |
| 520 const HTMLElement& element = toHTMLElement(*node); |
| 521 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); |
518 } | 523 } |
519 | 524 |
520 static Node* highestAncestorToWrapMarkup(const Range* range, EAnnotateForInterch
ange shouldAnnotate, Node* constrainingAncestor) | 525 static ContainerNode* highestAncestorToWrapMarkup(const Range* range, EAnnotateF
orInterchange shouldAnnotate, Node* constrainingAncestor) |
521 { | 526 { |
522 Node* commonAncestor = range->commonAncestorContainer(); | 527 Node* commonAncestor = range->commonAncestorContainer(); |
523 ASSERT(commonAncestor); | 528 ASSERT(commonAncestor); |
524 Node* specialCommonAncestor = 0; | 529 ContainerNode* specialCommonAncestor = 0; |
525 if (shouldAnnotate == AnnotateForInterchange) { | 530 if (shouldAnnotate == AnnotateForInterchange) { |
526 // Include ancestors that aren't completely inside the range but are req
uired to retain | 531 // Include ancestors that aren't completely inside the range but are req
uired to retain |
527 // the structure and appearance of the copied markup. | 532 // the structure and appearance of the copied markup. |
528 specialCommonAncestor = ancestorToRetainStructureAndAppearance(commonAnc
estor); | 533 specialCommonAncestor = ancestorToRetainStructureAndAppearance(commonAnc
estor); |
529 | 534 |
530 if (Node* parentListNode = enclosingNodeOfType(firstPositionInOrBeforeNo
de(range->firstNode()), isListItem)) { | 535 if (Node* parentListNode = enclosingNodeOfType(firstPositionInOrBeforeNo
de(range->firstNode()), isListItem)) { |
531 if (blink::areRangesEqual(VisibleSelection::selectionFromContentsOfN
ode(parentListNode).toNormalizedRange().get(), range)) { | 536 if (blink::areRangesEqual(VisibleSelection::selectionFromContentsOfN
ode(parentListNode).toNormalizedRange().get(), range)) { |
532 specialCommonAncestor = parentListNode->parentNode(); | 537 specialCommonAncestor = parentListNode->parentNode(); |
533 while (specialCommonAncestor && !isListElement(specialCommonAnce
stor)) | 538 while (specialCommonAncestor && !isListElement(specialCommonAnce
stor)) |
534 specialCommonAncestor = specialCommonAncestor->parentNode(); | 539 specialCommonAncestor = specialCommonAncestor->parentNode(); |
535 } | 540 } |
536 } | 541 } |
537 | 542 |
538 // Retain the Mail quote level by including all ancestor mail block quot
es. | 543 // Retain the Mail quote level by including all ancestor mail block quot
es. |
539 if (Node* highestMailBlockquote = highestEnclosingNodeOfType(firstPositi
onInOrBeforeNode(range->firstNode()), isMailBlockquote, CanCrossEditingBoundary)
) | 544 if (HTMLQuoteElement* highestMailBlockquote = toHTMLQuoteElement(highest
EnclosingNodeOfType(firstPositionInOrBeforeNode(range->firstNode()), isMailHTMLB
lockquoteElement, CanCrossEditingBoundary))) |
540 specialCommonAncestor = highestMailBlockquote; | 545 specialCommonAncestor = highestMailBlockquote; |
541 } | 546 } |
542 | 547 |
543 Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : common
Ancestor; | 548 Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : common
Ancestor; |
544 if (checkAncestor->renderer()) { | 549 if (checkAncestor->renderer()) { |
545 Node* newSpecialCommonAncestor = highestEnclosingNodeOfType(firstPositio
nInNode(checkAncestor), &isElementPresentational, CanCrossEditingBoundary, const
rainingAncestor); | 550 HTMLElement* newSpecialCommonAncestor = toHTMLElement(highestEnclosingNo
deOfType(firstPositionInNode(checkAncestor), &isPresentationalHTMLElement, CanCr
ossEditingBoundary, constrainingAncestor)); |
546 if (newSpecialCommonAncestor) | 551 if (newSpecialCommonAncestor) |
547 specialCommonAncestor = newSpecialCommonAncestor; | 552 specialCommonAncestor = newSpecialCommonAncestor; |
548 } | 553 } |
549 | 554 |
550 // If a single tab is selected, commonAncestor will be a text node inside a
tab span. | 555 // If a single tab is selected, commonAncestor will be a text node inside a
tab span. |
551 // If two or more tabs are selected, commonAncestor will be the tab span. | 556 // If two or more tabs are selected, commonAncestor will be the tab span. |
552 // In either case, if there is a specialCommonAncestor already, it will nece
ssarily be above | 557 // In either case, if there is a specialCommonAncestor already, it will nece
ssarily be above |
553 // any tab span that needs to be included. | 558 // any tab span that needs to be included. |
554 if (!specialCommonAncestor && isTabSpanTextNode(commonAncestor)) | 559 if (!specialCommonAncestor && isTabSpanTextNode(commonAncestor)) |
555 specialCommonAncestor = commonAncestor->parentNode(); | 560 specialCommonAncestor = commonAncestor->parentNode(); |
556 if (!specialCommonAncestor && isTabSpanElement(commonAncestor)) | 561 if (!specialCommonAncestor && isTabSpanElement(commonAncestor)) |
557 specialCommonAncestor = commonAncestor; | 562 specialCommonAncestor = toElement(commonAncestor); |
558 | 563 |
559 if (Element* enclosingAnchor = enclosingElementWithTag(firstPositionInNode(s
pecialCommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) | 564 if (Element* enclosingAnchor = enclosingElementWithTag(firstPositionInNode(s
pecialCommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) |
560 specialCommonAncestor = enclosingAnchor; | 565 specialCommonAncestor = enclosingAnchor; |
561 | 566 |
562 return specialCommonAncestor; | 567 return specialCommonAncestor; |
563 } | 568 } |
564 | 569 |
565 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
nge? | 570 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
nge? |
566 // FIXME: At least, annotation and style info should probably not be included in
range.markupString() | 571 // FIXME: At least, annotation and style info should probably not be included in
range.markupString() |
567 static String createMarkupInternal(Document& document, const Range* range, const
Range* updatedRange, WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, | 572 static String createMarkupInternal(Document& document, const Range* range, const
Range* updatedRange, WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, |
(...skipping 10 matching lines...) Expand all Loading... |
578 if (!commonAncestor) | 583 if (!commonAncestor) |
579 return emptyString(); | 584 return emptyString(); |
580 | 585 |
581 document.updateLayoutIgnorePendingStylesheets(); | 586 document.updateLayoutIgnorePendingStylesheets(); |
582 | 587 |
583 Element* body = enclosingElementWithTag(firstPositionInNode(commonAncestor),
bodyTag); | 588 Element* body = enclosingElementWithTag(firstPositionInNode(commonAncestor),
bodyTag); |
584 Node* fullySelectedRoot = 0; | 589 Node* fullySelectedRoot = 0; |
585 // FIXME: Do this for all fully selected blocks, not just the body. | 590 // FIXME: Do this for all fully selected blocks, not just the body. |
586 if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(bod
y).toNormalizedRange().get(), range)) | 591 if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(bod
y).toNormalizedRange().get(), range)) |
587 fullySelectedRoot = body; | 592 fullySelectedRoot = body; |
588 Node* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRange, shou
ldAnnotate, constrainingAncestor); | 593 ContainerNode* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRa
nge, shouldAnnotate, constrainingAncestor); |
589 StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate
, updatedRange, specialCommonAncestor); | 594 StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate
, updatedRange, specialCommonAncestor); |
590 Node* pastEnd = updatedRange->pastLastNode(); | 595 Node* pastEnd = updatedRange->pastLastNode(); |
591 | 596 |
592 Node* startNode = updatedRange->firstNode(); | 597 Node* startNode = updatedRange->firstNode(); |
593 VisiblePosition visibleStart(updatedRange->startPosition(), VP_DEFAULT_AFFIN
ITY); | 598 VisiblePosition visibleStart(updatedRange->startPosition(), VP_DEFAULT_AFFIN
ITY); |
594 VisiblePosition visibleEnd(updatedRange->endPosition(), VP_DEFAULT_AFFINITY)
; | 599 VisiblePosition visibleEnd(updatedRange->endPosition(), VP_DEFAULT_AFFINITY)
; |
595 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(
visibleStart)) { | 600 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(
visibleStart)) { |
596 if (visibleStart == visibleEnd.previous()) | 601 if (visibleStart == visibleEnd.previous()) |
597 return interchangeNewlineString; | 602 return interchangeNewlineString; |
598 | 603 |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 node->document().updateLayoutIgnorePendingStylesheets(); | 1117 node->document().updateLayoutIgnorePendingStylesheets(); |
1113 | 1118 |
1114 StyledMarkupAccumulator accumulator(0, ResolveAllURLs, AnnotateForNavigation
Transition, nullptr, 0); | 1119 StyledMarkupAccumulator accumulator(0, ResolveAllURLs, AnnotateForNavigation
Transition, nullptr, 0); |
1115 accumulator.serializeNodes(node, NodeTraversal::nextSkippingChildren(*node))
; | 1120 accumulator.serializeNodes(node, NodeTraversal::nextSkippingChildren(*node))
; |
1116 | 1121 |
1117 static const char* documentMarkup = "<!DOCTYPE html><meta name=\"viewport\"
content=\"width=device-width, user-scalable=0\">"; | 1122 static const char* documentMarkup = "<!DOCTYPE html><meta name=\"viewport\"
content=\"width=device-width, user-scalable=0\">"; |
1118 return documentMarkup + accumulator.takeResults(); | 1123 return documentMarkup + accumulator.takeResults(); |
1119 } | 1124 } |
1120 | 1125 |
1121 } | 1126 } |
OLD | NEW |