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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 unsigned startOffset = 0; | 251 unsigned startOffset = 0; |
252 unsigned endOffset = textNode->length(); | 252 unsigned endOffset = textNode->length(); |
253 | 253 |
254 if (range && node == range->startContainer()) | 254 if (range && node == range->startContainer()) |
255 startOffset = range->startOffset(); | 255 startOffset = range->startOffset(); |
256 if (range && node == range->endContainer()) | 256 if (range && node == range->endContainer()) |
257 endOffset = range->endOffset(); | 257 endOffset = range->endOffset(); |
258 | 258 |
259 Position start = createLegacyEditingPosition(const_cast<Node*>(node), startO
ffset); | 259 Position start = createLegacyEditingPosition(const_cast<Node*>(node), startO
ffset); |
260 Position end = createLegacyEditingPosition(const_cast<Node*>(node), endOffse
t); | 260 Position end = createLegacyEditingPosition(const_cast<Node*>(node), endOffse
t); |
261 return plainText(Range::create(&node->document(), start, end).get()); | 261 return plainText(Range::create(node->document(), start, end).get()); |
262 } | 262 } |
263 | 263 |
264 String StyledMarkupAccumulator::stringValueForRange(const Node* node, const Rang
e* range) | 264 String StyledMarkupAccumulator::stringValueForRange(const Node* node, const Rang
e* range) |
265 { | 265 { |
266 if (!range) | 266 if (!range) |
267 return node->nodeValue(); | 267 return node->nodeValue(); |
268 | 268 |
269 String str = node->nodeValue(); | 269 String str = node->nodeValue(); |
270 if (node == range->endContainer()) | 270 if (node == range->endContainer()) |
271 str.truncate(range->endOffset()); | 271 str.truncate(range->endOffset()); |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 specialCommonAncestor = commonAncestor; | 535 specialCommonAncestor = commonAncestor; |
536 | 536 |
537 if (Node *enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(special
CommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) | 537 if (Node *enclosingAnchor = enclosingNodeWithTag(firstPositionInNode(special
CommonAncestor ? specialCommonAncestor : commonAncestor), aTag)) |
538 specialCommonAncestor = enclosingAnchor; | 538 specialCommonAncestor = enclosingAnchor; |
539 | 539 |
540 return specialCommonAncestor; | 540 return specialCommonAncestor; |
541 } | 541 } |
542 | 542 |
543 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
nge? | 543 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForIntercha
nge? |
544 // FIXME: At least, annotation and style info should probably not be included in
range.markupString() | 544 // FIXME: At least, annotation and style info should probably not be included in
range.markupString() |
545 static String createMarkupInternal(Document* document, const Range* range, const
Range* updatedRange, Vector<Node*>* nodes, | 545 static String createMarkupInternal(Document& document, const Range* range, const
Range* updatedRange, Vector<Node*>* nodes, |
546 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu
teURLs shouldResolveURLs, Node* constrainingAncestor) | 546 EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsolu
teURLs shouldResolveURLs, Node* constrainingAncestor) |
547 { | 547 { |
548 ASSERT(document); | |
549 ASSERT(range); | 548 ASSERT(range); |
550 ASSERT(updatedRange); | 549 ASSERT(updatedRange); |
551 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\""
AppleInterchangeNewline "\">")); | 550 DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, ("<br class=\""
AppleInterchangeNewline "\">")); |
552 | 551 |
553 bool collapsed = updatedRange->collapsed(ASSERT_NO_EXCEPTION); | 552 bool collapsed = updatedRange->collapsed(ASSERT_NO_EXCEPTION); |
554 if (collapsed) | 553 if (collapsed) |
555 return emptyString(); | 554 return emptyString(); |
556 Node* commonAncestor = updatedRange->commonAncestorContainer(ASSERT_NO_EXCEP
TION); | 555 Node* commonAncestor = updatedRange->commonAncestorContainer(ASSERT_NO_EXCEP
TION); |
557 if (!commonAncestor) | 556 if (!commonAncestor) |
558 return emptyString(); | 557 return emptyString(); |
559 | 558 |
560 document->updateLayoutIgnorePendingStylesheets(); | 559 document.updateLayoutIgnorePendingStylesheets(); |
561 | 560 |
562 Node* body = enclosingNodeWithTag(firstPositionInNode(commonAncestor), bodyT
ag); | 561 Node* body = enclosingNodeWithTag(firstPositionInNode(commonAncestor), bodyT
ag); |
563 Node* fullySelectedRoot = 0; | 562 Node* fullySelectedRoot = 0; |
564 // FIXME: Do this for all fully selected blocks, not just the body. | 563 // FIXME: Do this for all fully selected blocks, not just the body. |
565 if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(bod
y).toNormalizedRange().get(), range)) | 564 if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(bod
y).toNormalizedRange().get(), range)) |
566 fullySelectedRoot = body; | 565 fullySelectedRoot = body; |
567 Node* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRange, shou
ldAnnotate, constrainingAncestor); | 566 Node* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRange, shou
ldAnnotate, constrainingAncestor); |
568 StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate
, updatedRange, specialCommonAncestor); | 567 StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate
, updatedRange, specialCommonAncestor); |
569 Node* pastEnd = updatedRange->pastLastNode(); | 568 Node* pastEnd = updatedRange->pastLastNode(); |
570 | 569 |
(...skipping 26 matching lines...) Expand all Loading... |
597 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack
groundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr
) + "')"); | 596 fullySelectedRootStyle->style()->setProperty(CSSPropertyBack
groundImage, "url('" + toElement(fullySelectedRoot)->getAttribute(backgroundAttr
) + "')"); |
598 | 597 |
599 if (fullySelectedRootStyle->style()) { | 598 if (fullySelectedRootStyle->style()) { |
600 // Reset the CSS properties to avoid an assertion error in a
ddStyleMarkup(). | 599 // Reset the CSS properties to avoid an assertion error in a
ddStyleMarkup(). |
601 // This assertion is caused at least when we select all text
of a <body> element whose | 600 // This assertion is caused at least when we select all text
of a <body> element whose |
602 // 'text-decoration' property is "inherit", and copy it. | 601 // 'text-decoration' property is "inherit", and copy it. |
603 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
yle(), CSSPropertyTextDecoration)) | 602 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
yle(), CSSPropertyTextDecoration)) |
604 fullySelectedRootStyle->style()->setProperty(CSSProperty
TextDecoration, CSSValueNone); | 603 fullySelectedRootStyle->style()->setProperty(CSSProperty
TextDecoration, CSSValueNone); |
605 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
yle(), CSSPropertyWebkitTextDecorationsInEffect)) | 604 if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->st
yle(), CSSPropertyWebkitTextDecorationsInEffect)) |
606 fullySelectedRootStyle->style()->setProperty(CSSProperty
WebkitTextDecorationsInEffect, CSSValueNone); | 605 fullySelectedRootStyle->style()->setProperty(CSSProperty
WebkitTextDecorationsInEffect, CSSValueNone); |
607 accumulator.wrapWithStyleNode(fullySelectedRootStyle->style(
), document, true); | 606 accumulator.wrapWithStyleNode(fullySelectedRootStyle->style(
), &document, true); |
608 } | 607 } |
609 } else { | 608 } else { |
610 // Since this node and all the other ancestors are not in the se
lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode | 609 // Since this node and all the other ancestors are not in the se
lection we want to set RangeFullySelectsNode to DoesNotFullySelectNode |
611 // so that styles that affect the exterior of the node are not i
ncluded. | 610 // so that styles that affect the exterior of the node are not i
ncluded. |
612 accumulator.wrapWithNode(ancestor, convertBlocksToInlines, Style
dMarkupAccumulator::DoesNotFullySelectNode); | 611 accumulator.wrapWithNode(ancestor, convertBlocksToInlines, Style
dMarkupAccumulator::DoesNotFullySelectNode); |
613 } | 612 } |
614 if (nodes) | 613 if (nodes) |
615 nodes->append(ancestor); | 614 nodes->append(ancestor); |
616 | 615 |
617 lastClosed = ancestor; | 616 lastClosed = ancestor; |
618 | 617 |
619 if (ancestor == specialCommonAncestor) | 618 if (ancestor == specialCommonAncestor) |
620 break; | 619 break; |
621 } | 620 } |
622 } | 621 } |
623 | 622 |
624 // FIXME: The interchange newline should be placed in the block that it's in
, not after all of the content, unconditionally. | 623 // FIXME: The interchange newline should be placed in the block that it's in
, not after all of the content, unconditionally. |
625 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(
visibleEnd.previous())) | 624 if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(
visibleEnd.previous())) |
626 accumulator.appendString(interchangeNewlineString); | 625 accumulator.appendString(interchangeNewlineString); |
627 | 626 |
628 return accumulator.takeResults(); | 627 return accumulator.takeResults(); |
629 } | 628 } |
630 | 629 |
631 String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc
hange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveUR
Ls, Node* constrainingAncestor) | 630 String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc
hange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveUR
Ls, Node* constrainingAncestor) |
632 { | 631 { |
633 if (!range) | 632 if (!range) |
634 return emptyString(); | 633 return emptyString(); |
635 | 634 |
636 Document* document = range->ownerDocument(); | 635 Document& document = range->ownerDocument(); |
637 if (!document) | |
638 return emptyString(); | |
639 | |
640 const Range* updatedRange = range; | 636 const Range* updatedRange = range; |
641 | 637 |
642 return createMarkupInternal(document, range, updatedRange, nodes, shouldAnno
tate, convertBlocksToInlines, shouldResolveURLs, constrainingAncestor); | 638 return createMarkupInternal(document, range, updatedRange, nodes, shouldAnno
tate, convertBlocksToInlines, shouldResolveURLs, constrainingAncestor); |
643 } | 639 } |
644 | 640 |
645 PassRefPtr<DocumentFragment> createFragmentFromMarkup(Document* document, const
String& markup, const String& baseURL, ParserContentPolicy parserContentPolicy) | 641 PassRefPtr<DocumentFragment> createFragmentFromMarkup(Document* document, const
String& markup, const String& baseURL, ParserContentPolicy parserContentPolicy) |
646 { | 642 { |
647 ASSERT(document); | 643 ASSERT(document); |
648 // We use a fake body element here to trick the HTML parser to using the InB
ody insertion mode. | 644 // We use a fake body element here to trick the HTML parser to using the InB
ody insertion mode. |
649 RefPtr<HTMLBodyElement> fakeBody = HTMLBodyElement::create(*document); | 645 RefPtr<HTMLBodyElement> fakeBody = HTMLBodyElement::create(*document); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 RefPtr<DocumentFragment> taggedFragment = createFragmentFromMarkup(document,
taggedMarkup.toString(), baseURL, parserContentPolicy); | 707 RefPtr<DocumentFragment> taggedFragment = createFragmentFromMarkup(document,
taggedMarkup.toString(), baseURL, parserContentPolicy); |
712 RefPtr<Document> taggedDocument = Document::create(); | 708 RefPtr<Document> taggedDocument = Document::create(); |
713 taggedDocument->setContextFeatures(document->contextFeatures()); | 709 taggedDocument->setContextFeatures(document->contextFeatures()); |
714 taggedDocument->takeAllChildrenFrom(taggedFragment.get()); | 710 taggedDocument->takeAllChildrenFrom(taggedFragment.get()); |
715 | 711 |
716 RefPtr<Node> nodeBeforeContext; | 712 RefPtr<Node> nodeBeforeContext; |
717 RefPtr<Node> nodeAfterContext; | 713 RefPtr<Node> nodeAfterContext; |
718 if (!findNodesSurroundingContext(taggedDocument.get(), nodeBeforeContext, no
deAfterContext)) | 714 if (!findNodesSurroundingContext(taggedDocument.get(), nodeBeforeContext, no
deAfterContext)) |
719 return 0; | 715 return 0; |
720 | 716 |
721 RefPtr<Range> range = Range::create(taggedDocument.get(), | 717 RefPtr<Range> range = Range::create(*taggedDocument.get(), |
722 positionAfterNode(nodeBeforeContext.get()).parentAnchoredEquivalent(), | 718 positionAfterNode(nodeBeforeContext.get()).parentAnchoredEquivalent(), |
723 positionBeforeNode(nodeAfterContext.get()).parentAnchoredEquivalent()); | 719 positionBeforeNode(nodeAfterContext.get()).parentAnchoredEquivalent()); |
724 | 720 |
725 Node* commonAncestor = range->commonAncestorContainer(ASSERT_NO_EXCEPTION); | 721 Node* commonAncestor = range->commonAncestorContainer(ASSERT_NO_EXCEPTION); |
726 Node* specialCommonAncestor = ancestorToRetainStructureAndAppearanceWithNoRe
nderer(commonAncestor); | 722 Node* specialCommonAncestor = ancestorToRetainStructureAndAppearanceWithNoRe
nderer(commonAncestor); |
727 | 723 |
728 // When there's a special common ancestor outside of the fragment, we must i
nclude it as well to | 724 // When there's a special common ancestor outside of the fragment, we must i
nclude it as well to |
729 // preserve the structure and appearance of the fragment. For example, if th
e fragment contains | 725 // preserve the structure and appearance of the fragment. For example, if th
e fragment contains |
730 // TD, we need to include the enclosing TABLE tag as well. | 726 // TD, we need to include the enclosing TABLE tag as well. |
731 RefPtr<DocumentFragment> fragment = DocumentFragment::create(document); | 727 RefPtr<DocumentFragment> fragment = DocumentFragment::create(document); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 } | 808 } |
813 | 809 |
814 return false; | 810 return false; |
815 } | 811 } |
816 | 812 |
817 PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String
& text) | 813 PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String
& text) |
818 { | 814 { |
819 if (!context) | 815 if (!context) |
820 return 0; | 816 return 0; |
821 | 817 |
822 Document& document = *context->ownerDocument(); | 818 Document& document = context->ownerDocument(); |
823 RefPtr<DocumentFragment> fragment = document.createDocumentFragment(); | 819 RefPtr<DocumentFragment> fragment = document.createDocumentFragment(); |
824 | 820 |
825 if (text.isEmpty()) | 821 if (text.isEmpty()) |
826 return fragment.release(); | 822 return fragment.release(); |
827 | 823 |
828 String string = text; | 824 String string = text; |
829 string.replace("\r\n", "\n"); | 825 string.replace("\r\n", "\n"); |
830 string.replace('\r', '\n'); | 826 string.replace('\r', '\n'); |
831 | 827 |
832 if (shouldPreserveNewline(*context)) { | 828 if (shouldPreserveNewline(*context)) { |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 if (containerNode->hasOneChild()) { | 1069 if (containerNode->hasOneChild()) { |
1074 containerNode->replaceChild(textNode.release(), containerNode->firstChil
d(), es); | 1070 containerNode->replaceChild(textNode.release(), containerNode->firstChil
d(), es); |
1075 return; | 1071 return; |
1076 } | 1072 } |
1077 | 1073 |
1078 containerNode->removeChildren(); | 1074 containerNode->removeChildren(); |
1079 containerNode->appendChild(textNode.release(), es); | 1075 containerNode->appendChild(textNode.release(), es); |
1080 } | 1076 } |
1081 | 1077 |
1082 } | 1078 } |
OLD | NEW |