| 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 |