OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 splitTextAtEnd(start, end); | 344 splitTextAtEnd(start, end); |
345 start = startPosition(); | 345 start = startPosition(); |
346 end = endPosition(); | 346 end = endPosition(); |
347 } | 347 } |
348 | 348 |
349 // Calculate loop end point. | 349 // Calculate loop end point. |
350 // If the end node is before the start node (can only happen if the end node
is | 350 // If the end node is before the start node (can only happen if the end node
is |
351 // an ancestor of the start node), we gather nodes up to the next sibling of
the end node | 351 // an ancestor of the start node), we gather nodes up to the next sibling of
the end node |
352 Node *beyondEnd; | 352 Node *beyondEnd; |
353 if (start.deprecatedNode()->isDescendantOf(end.deprecatedNode())) | 353 if (start.deprecatedNode()->isDescendantOf(end.deprecatedNode())) |
354 beyondEnd = NodeTraversal::nextSkippingChildren(end.deprecatedNode()); | 354 beyondEnd = NodeTraversal::nextSkippingChildren(*end.deprecatedNode()); |
355 else | 355 else |
356 beyondEnd = NodeTraversal::next(*end.deprecatedNode()); | 356 beyondEnd = NodeTraversal::next(*end.deprecatedNode()); |
357 | 357 |
358 start = start.upstream(); // Move upstream to ensure we do not add redundant
spans. | 358 start = start.upstream(); // Move upstream to ensure we do not add redundant
spans. |
359 Node* startNode = start.deprecatedNode(); | 359 Node* startNode = start.deprecatedNode(); |
360 ASSERT(startNode); | 360 ASSERT(startNode); |
361 if (startNode->isTextNode() && start.deprecatedEditingOffset() >= caretMaxOf
fset(startNode)) // Move out of text node if range does not include its characte
rs. | 361 if (startNode->isTextNode() && start.deprecatedEditingOffset() >= caretMaxOf
fset(startNode)) // Move out of text node if range does not include its characte
rs. |
362 startNode = NodeTraversal::next(*startNode); | 362 startNode = NodeTraversal::next(*startNode); |
363 | 363 |
364 // Store away font size before making any changes to the document. | 364 // Store away font size before making any changes to the document. |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 ASSERT(startNode); | 676 ASSERT(startNode); |
677 | 677 |
678 if (start.deprecatedEditingOffset() >= caretMaxOffset(start.deprecatedNode()
)) { | 678 if (start.deprecatedEditingOffset() >= caretMaxOffset(start.deprecatedNode()
)) { |
679 startNode = NodeTraversal::next(*startNode); | 679 startNode = NodeTraversal::next(*startNode); |
680 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star
tNode)) < 0) | 680 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star
tNode)) < 0) |
681 return; | 681 return; |
682 } | 682 } |
683 | 683 |
684 Node* pastEndNode = end.deprecatedNode(); | 684 Node* pastEndNode = end.deprecatedNode(); |
685 if (end.deprecatedEditingOffset() >= caretMaxOffset(end.deprecatedNode())) | 685 if (end.deprecatedEditingOffset() >= caretMaxOffset(end.deprecatedNode())) |
686 pastEndNode = NodeTraversal::nextSkippingChildren(end.deprecatedNode()); | 686 pastEndNode = NodeTraversal::nextSkippingChildren(*end.deprecatedNode())
; |
687 | 687 |
688 // FIXME: Callers should perform this operation on a Range that includes the
br | 688 // FIXME: Callers should perform this operation on a Range that includes the
br |
689 // if they want style applied to the empty line. | 689 // if they want style applied to the empty line. |
690 if (start == end && start.deprecatedNode()->hasTagName(brTag)) | 690 if (start == end && start.deprecatedNode()->hasTagName(brTag)) |
691 pastEndNode = NodeTraversal::next(*start.deprecatedNode()); | 691 pastEndNode = NodeTraversal::next(*start.deprecatedNode()); |
692 | 692 |
693 // Start from the highest fully selected ancestor so that we can modify the
fully selected node. | 693 // Start from the highest fully selected ancestor so that we can modify the
fully selected node. |
694 // e.g. When applying font-size: large on <font color="blue">hello</font>, w
e need to include the font element in our run | 694 // e.g. When applying font-size: large on <font color="blue">hello</font>, w
e need to include the font element in our run |
695 // to generate <font color="blue" size="4">hello</font> instead of <font col
or="blue"><font size="4">hello</font></font> | 695 // to generate <font color="blue" size="4">hello</font> instead of <font col
or="blue"><font size="4">hello</font></font> |
696 RefPtr<Range> range = Range::create(startNode->document(), start, end); | 696 RefPtr<Range> range = Range::create(startNode->document(), start, end); |
697 Element* editableRoot = startNode->rootEditableElement(); | 697 Element* editableRoot = startNode->rootEditableElement(); |
698 if (startNode != editableRoot) { | 698 if (startNode != editableRoot) { |
699 while (editableRoot && startNode->parentNode() != editableRoot && isNode
VisiblyContainedWithin(startNode->parentNode(), range.get())) | 699 while (editableRoot && startNode->parentNode() != editableRoot && isNode
VisiblyContainedWithin(startNode->parentNode(), range.get())) |
700 startNode = startNode->parentNode(); | 700 startNode = startNode->parentNode(); |
701 } | 701 } |
702 | 702 |
703 applyInlineStyleToNodeRange(style, startNode, pastEndNode); | 703 applyInlineStyleToNodeRange(style, startNode, pastEndNode); |
704 } | 704 } |
705 | 705 |
706 static bool containsNonEditableRegion(Node* node) | 706 static bool containsNonEditableRegion(Node& node) |
707 { | 707 { |
708 if (!node->rendererIsEditable()) | 708 if (!node.rendererIsEditable()) |
709 return true; | 709 return true; |
710 | 710 |
711 Node* sibling = NodeTraversal::nextSkippingChildren(node); | 711 Node* sibling = NodeTraversal::nextSkippingChildren(node); |
712 for (Node* descendent = node->firstChild(); descendent && descendent != sibl
ing; descendent = NodeTraversal::next(*descendent)) { | 712 for (Node* descendent = node.firstChild(); descendent && descendent != sibli
ng; descendent = NodeTraversal::next(*descendent)) { |
713 if (!descendent->rendererIsEditable()) | 713 if (!descendent->rendererIsEditable()) |
714 return true; | 714 return true; |
715 } | 715 } |
716 | 716 |
717 return false; | 717 return false; |
718 } | 718 } |
719 | 719 |
720 struct InlineRunToApplyStyle { | 720 struct InlineRunToApplyStyle { |
721 InlineRunToApplyStyle(Node* start, Node* end, Node* pastEndNode) | 721 InlineRunToApplyStyle(Node* start, Node* end, Node* pastEndNode) |
722 : start(start) | 722 : start(start) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 continue; | 755 continue; |
756 | 756 |
757 if (!node->rendererIsRichlyEditable() && node->isHTMLElement()) { | 757 if (!node->rendererIsRichlyEditable() && node->isHTMLElement()) { |
758 // This is a plaintext-only region. Only proceed if it's fully selec
ted. | 758 // This is a plaintext-only region. Only proceed if it's fully selec
ted. |
759 // pastEndNode is the node after the last fully selected node, so if
it's inside node then | 759 // pastEndNode is the node after the last fully selected node, so if
it's inside node then |
760 // node isn't fully selected. | 760 // node isn't fully selected. |
761 if (pastEndNode && pastEndNode->isDescendantOf(node.get())) | 761 if (pastEndNode && pastEndNode->isDescendantOf(node.get())) |
762 break; | 762 break; |
763 // Add to this element's inline style and skip over its contents. | 763 // Add to this element's inline style and skip over its contents. |
764 HTMLElement* element = toHTMLElement(node); | 764 HTMLElement* element = toHTMLElement(node); |
765 next = NodeTraversal::nextSkippingChildren(node.get()); | 765 next = NodeTraversal::nextSkippingChildren(*node); |
766 if (!style->style()) | 766 if (!style->style()) |
767 continue; | 767 continue; |
768 RefPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCreateEmpty
(element->inlineStyle()); | 768 RefPtr<MutableStylePropertySet> inlineStyle = copyStyleOrCreateEmpty
(element->inlineStyle()); |
769 inlineStyle->mergeAndOverrideOnConflict(style->style()); | 769 inlineStyle->mergeAndOverrideOnConflict(style->style()); |
770 setNodeAttribute(element, styleAttr, inlineStyle->asText()); | 770 setNodeAttribute(element, styleAttr, inlineStyle->asText()); |
771 continue; | 771 continue; |
772 } | 772 } |
773 | 773 |
774 if (isBlock(node.get())) | 774 if (isBlock(node.get())) |
775 continue; | 775 continue; |
776 | 776 |
777 if (node->childNodeCount()) { | 777 if (node->childNodeCount()) { |
778 if (node->contains(pastEndNode.get()) || containsNonEditableRegion(n
ode.get()) || !node->parentNode()->rendererIsEditable()) | 778 if (node->contains(pastEndNode.get()) || containsNonEditableRegion(*
node) || !node->parentNode()->rendererIsEditable()) |
779 continue; | 779 continue; |
780 if (editingIgnoresContent(node.get())) { | 780 if (editingIgnoresContent(node.get())) { |
781 next = NodeTraversal::nextSkippingChildren(node.get()); | 781 next = NodeTraversal::nextSkippingChildren(*node); |
782 continue; | 782 continue; |
783 } | 783 } |
784 } | 784 } |
785 | 785 |
786 Node* runStart = node.get(); | 786 Node* runStart = node.get(); |
787 Node* runEnd = node.get(); | 787 Node* runEnd = node.get(); |
788 Node* sibling = node->nextSibling(); | 788 Node* sibling = node->nextSibling(); |
789 while (sibling && sibling != pastEndNode && !sibling->contains(pastEndNo
de.get()) | 789 while (sibling && sibling != pastEndNode && !sibling->contains(pastEndNo
de.get()) |
790 && (!isBlock(sibling) || sibling->hasTagName(brTag)) | 790 && (!isBlock(sibling) || sibling->hasTagName(brTag)) |
791 && !containsNonEditableRegion(sibling)) { | 791 && !containsNonEditableRegion(*sibling)) { |
792 runEnd = sibling; | 792 runEnd = sibling; |
793 sibling = runEnd->nextSibling(); | 793 sibling = runEnd->nextSibling(); |
794 } | 794 } |
795 next = NodeTraversal::nextSkippingChildren(runEnd); | 795 ASSERT(runEnd); |
| 796 next = NodeTraversal::nextSkippingChildren(*runEnd); |
796 | 797 |
797 Node* pastEndNode = NodeTraversal::nextSkippingChildren(runEnd); | 798 Node* pastEndNode = NodeTraversal::nextSkippingChildren(*runEnd); |
798 if (!shouldApplyInlineStyleToRun(style, runStart, pastEndNode)) | 799 if (!shouldApplyInlineStyleToRun(style, runStart, pastEndNode)) |
799 continue; | 800 continue; |
800 | 801 |
801 runs.append(InlineRunToApplyStyle(runStart, runEnd, pastEndNode)); | 802 runs.append(InlineRunToApplyStyle(runStart, runEnd, pastEndNode)); |
802 } | 803 } |
803 | 804 |
804 for (size_t i = 0; i < runs.size(); i++) { | 805 for (size_t i = 0; i < runs.size(); i++) { |
805 removeConflictingInlineStyleFromRun(style, runs[i].start, runs[i].end, r
uns[i].pastEndNode); | 806 removeConflictingInlineStyleFromRun(style, runs[i].start, runs[i].end, r
uns[i].pastEndNode); |
806 runs[i].positionForStyleComputation = positionToComputeInlineStyleChange
(runs[i].start, runs[i].dummyElement); | 807 runs[i].positionForStyleComputation = positionToComputeInlineStyleChange
(runs[i].start, runs[i].dummyElement); |
807 } | 808 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 return false; | 843 return false; |
843 } | 844 } |
844 | 845 |
845 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style,
RefPtr<Node>& runStart, RefPtr<Node>& runEnd, PassRefPtr<Node> pastEndNode) | 846 void ApplyStyleCommand::removeConflictingInlineStyleFromRun(EditingStyle* style,
RefPtr<Node>& runStart, RefPtr<Node>& runEnd, PassRefPtr<Node> pastEndNode) |
846 { | 847 { |
847 ASSERT(runStart && runEnd); | 848 ASSERT(runStart && runEnd); |
848 RefPtr<Node> next = runStart; | 849 RefPtr<Node> next = runStart; |
849 for (RefPtr<Node> node = next; node && node->inDocument() && node != pastEnd
Node; node = next) { | 850 for (RefPtr<Node> node = next; node && node->inDocument() && node != pastEnd
Node; node = next) { |
850 if (editingIgnoresContent(node.get())) { | 851 if (editingIgnoresContent(node.get())) { |
851 ASSERT(!node->contains(pastEndNode.get())); | 852 ASSERT(!node->contains(pastEndNode.get())); |
852 next = NodeTraversal::nextSkippingChildren(node.get()); | 853 next = NodeTraversal::nextSkippingChildren(*node); |
853 } else { | 854 } else { |
854 next = NodeTraversal::next(*node); | 855 next = NodeTraversal::next(*node); |
855 } | 856 } |
856 if (!node->isHTMLElement()) | 857 if (!node->isHTMLElement()) |
857 continue; | 858 continue; |
858 | 859 |
859 RefPtr<Node> previousSibling = node->previousSibling(); | 860 RefPtr<Node> previousSibling = node->previousSibling(); |
860 RefPtr<Node> nextSibling = node->nextSibling(); | 861 RefPtr<Node> nextSibling = node->nextSibling(); |
861 RefPtr<ContainerNode> parent = node->parentNode(); | 862 RefPtr<ContainerNode> parent = node->parentNode(); |
862 removeInlineStyleFromElement(style, toHTMLElement(node), RemoveAlways); | 863 removeInlineStyleFromElement(style, toHTMLElement(node), RemoveAlways); |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1102 // If pushDownInlineStyleAroundNode has pruned start.deprecatedNode() or end
.deprecatedNode(), | 1103 // If pushDownInlineStyleAroundNode has pruned start.deprecatedNode() or end
.deprecatedNode(), |
1103 // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAround
Node won't prune. | 1104 // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAround
Node won't prune. |
1104 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; | 1105 Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; |
1105 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; | 1106 Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; |
1106 | 1107 |
1107 RefPtr<Node> node = start.deprecatedNode(); | 1108 RefPtr<Node> node = start.deprecatedNode(); |
1108 while (node) { | 1109 while (node) { |
1109 RefPtr<Node> next; | 1110 RefPtr<Node> next; |
1110 if (editingIgnoresContent(node.get())) { | 1111 if (editingIgnoresContent(node.get())) { |
1111 ASSERT(node == end.deprecatedNode() || !node->contains(end.deprecate
dNode())); | 1112 ASSERT(node == end.deprecatedNode() || !node->contains(end.deprecate
dNode())); |
1112 next = NodeTraversal::nextSkippingChildren(node.get()); | 1113 next = NodeTraversal::nextSkippingChildren(*node); |
1113 } else { | 1114 } else { |
1114 next = NodeTraversal::next(*node); | 1115 next = NodeTraversal::next(*node); |
1115 } | 1116 } |
1116 if (node->isHTMLElement() && nodeFullySelected(node.get(), start, end))
{ | 1117 if (node->isHTMLElement() && nodeFullySelected(node.get(), start, end))
{ |
1117 RefPtr<HTMLElement> elem = toHTMLElement(node); | 1118 RefPtr<HTMLElement> elem = toHTMLElement(node); |
1118 RefPtr<Node> prev = NodeTraversal::previousPostOrder(*elem); | 1119 RefPtr<Node> prev = NodeTraversal::previousPostOrder(*elem); |
1119 RefPtr<Node> next = NodeTraversal::next(*elem); | 1120 RefPtr<Node> next = NodeTraversal::next(*elem); |
1120 RefPtr<EditingStyle> styleToPushDown; | 1121 RefPtr<EditingStyle> styleToPushDown; |
1121 RefPtr<Node> childNode; | 1122 RefPtr<Node> childNode; |
1122 if (isStyledInlineElementToRemove(elem.get())) { | 1123 if (isStyledInlineElementToRemove(elem.get())) { |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 String textToMove = nextText->data(); | 1547 String textToMove = nextText->data(); |
1547 insertTextIntoNode(childText, childText->length(), textToMove); | 1548 insertTextIntoNode(childText, childText->length(), textToMove); |
1548 removeNode(next); | 1549 removeNode(next); |
1549 // don't move child node pointer. it may want to merge with more text no
des. | 1550 // don't move child node pointer. it may want to merge with more text no
des. |
1550 } | 1551 } |
1551 | 1552 |
1552 updateStartEnd(newStart, newEnd); | 1553 updateStartEnd(newStart, newEnd); |
1553 } | 1554 } |
1554 | 1555 |
1555 } | 1556 } |
OLD | NEW |