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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 if (element->hasAttribute(styleAttr) && (shouldStyleAttributeBeEmpty == Allo
wNonEmptyStyleAttribute | 78 if (element->hasAttribute(styleAttr) && (shouldStyleAttributeBeEmpty == Allo
wNonEmptyStyleAttribute |
79 || !element->inlineStyle() || element->inlineStyle()->isEmpty())) | 79 || !element->inlineStyle() || element->inlineStyle()->isEmpty())) |
80 matchedAttributes++; | 80 matchedAttributes++; |
81 | 81 |
82 ASSERT(matchedAttributes <= element->attributeCount()); | 82 ASSERT(matchedAttributes <= element->attributeCount()); |
83 return matchedAttributes == element->attributeCount(); | 83 return matchedAttributes == element->attributeCount(); |
84 } | 84 } |
85 | 85 |
86 bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element) | 86 bool isStyleSpanOrSpanWithOnlyStyleAttribute(const Element* element) |
87 { | 87 { |
88 if (!element || !element->hasTagName(spanTag)) | 88 if (!isHTMLSpanElement(element)) |
89 return false; | 89 return false; |
90 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(element), AllowNonEm
ptyStyleAttribute); | 90 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(element), AllowNonEm
ptyStyleAttribute); |
91 } | 91 } |
92 | 92 |
93 static inline bool isSpanWithoutAttributesOrUnstyledStyleSpan(const Node* node) | 93 static inline bool isSpanWithoutAttributesOrUnstyledStyleSpan(const Node* node) |
94 { | 94 { |
95 if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag)) | 95 if (!isHTMLSpanElement(node)) |
96 return false; | 96 return false; |
97 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(node), StyleAttribut
eShouldBeEmpty); | 97 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(node), StyleAttribut
eShouldBeEmpty); |
98 } | 98 } |
99 | 99 |
100 bool isEmptyFontTag(const Element* element, ShouldStyleAttributeBeEmpty shouldSt
yleAttributeBeEmpty) | 100 bool isEmptyFontTag(const Element* element, ShouldStyleAttributeBeEmpty shouldSt
yleAttributeBeEmpty) |
101 { | 101 { |
102 if (!element || !element->hasTagName(fontTag)) | 102 if (!isHTMLFontElement(element)) |
103 return false; | 103 return false; |
104 | 104 |
105 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(element), shouldStyl
eAttributeBeEmpty); | 105 return hasNoAttributeOrOnlyStyleAttribute(toHTMLElement(element), shouldStyl
eAttributeBeEmpty); |
106 } | 106 } |
107 | 107 |
108 static PassRefPtr<Element> createFontElement(Document& document) | 108 static PassRefPtr<Element> createFontElement(Document& document) |
109 { | 109 { |
110 RefPtr<Element> fontNode = createHTMLElement(document, fontTag); | 110 RefPtr<Element> fontNode = createHTMLElement(document, fontTag); |
111 return fontNode.release(); | 111 return fontNode.release(); |
112 } | 112 } |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star
tNode)) < 0) | 688 if (!startNode || comparePositions(end, firstPositionInOrBeforeNode(star
tNode)) < 0) |
689 return; | 689 return; |
690 } | 690 } |
691 | 691 |
692 Node* pastEndNode = end.deprecatedNode(); | 692 Node* pastEndNode = end.deprecatedNode(); |
693 if (end.deprecatedEditingOffset() >= caretMaxOffset(end.deprecatedNode())) | 693 if (end.deprecatedEditingOffset() >= caretMaxOffset(end.deprecatedNode())) |
694 pastEndNode = NodeTraversal::nextSkippingChildren(*end.deprecatedNode())
; | 694 pastEndNode = NodeTraversal::nextSkippingChildren(*end.deprecatedNode())
; |
695 | 695 |
696 // FIXME: Callers should perform this operation on a Range that includes the
br | 696 // FIXME: Callers should perform this operation on a Range that includes the
br |
697 // if they want style applied to the empty line. | 697 // if they want style applied to the empty line. |
698 if (start == end && start.deprecatedNode()->hasTagName(brTag)) | 698 if (start == end && isHTMLBRElement(*start.deprecatedNode())) |
699 pastEndNode = NodeTraversal::next(*start.deprecatedNode()); | 699 pastEndNode = NodeTraversal::next(*start.deprecatedNode()); |
700 | 700 |
701 // Start from the highest fully selected ancestor so that we can modify the
fully selected node. | 701 // Start from the highest fully selected ancestor so that we can modify the
fully selected node. |
702 // e.g. When applying font-size: large on <font color="blue">hello</font>, w
e need to include the font element in our run | 702 // e.g. When applying font-size: large on <font color="blue">hello</font>, w
e need to include the font element in our run |
703 // to generate <font color="blue" size="4">hello</font> instead of <font col
or="blue"><font size="4">hello</font></font> | 703 // to generate <font color="blue" size="4">hello</font> instead of <font col
or="blue"><font size="4">hello</font></font> |
704 RefPtr<Range> range = Range::create(startNode->document(), start, end); | 704 RefPtr<Range> range = Range::create(startNode->document(), start, end); |
705 Element* editableRoot = startNode->rootEditableElement(); | 705 Element* editableRoot = startNode->rootEditableElement(); |
706 if (startNode != editableRoot) { | 706 if (startNode != editableRoot) { |
707 while (editableRoot && startNode->parentNode() != editableRoot && isNode
VisiblyContainedWithin(*startNode->parentNode(), *range)) | 707 while (editableRoot && startNode->parentNode() != editableRoot && isNode
VisiblyContainedWithin(*startNode->parentNode(), *range)) |
708 startNode = startNode->parentNode(); | 708 startNode = startNode->parentNode(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 if (editingIgnoresContent(node.get())) { | 788 if (editingIgnoresContent(node.get())) { |
789 next = NodeTraversal::nextSkippingChildren(*node); | 789 next = NodeTraversal::nextSkippingChildren(*node); |
790 continue; | 790 continue; |
791 } | 791 } |
792 } | 792 } |
793 | 793 |
794 Node* runStart = node.get(); | 794 Node* runStart = node.get(); |
795 Node* runEnd = node.get(); | 795 Node* runEnd = node.get(); |
796 Node* sibling = node->nextSibling(); | 796 Node* sibling = node->nextSibling(); |
797 while (sibling && sibling != pastEndNode && !sibling->contains(pastEndNo
de.get()) | 797 while (sibling && sibling != pastEndNode && !sibling->contains(pastEndNo
de.get()) |
798 && (!isBlock(sibling) || sibling->hasTagName(brTag)) | 798 && (!isBlock(sibling) || isHTMLBRElement(*sibling)) |
799 && !containsNonEditableRegion(*sibling)) { | 799 && !containsNonEditableRegion(*sibling)) { |
800 runEnd = sibling; | 800 runEnd = sibling; |
801 sibling = runEnd->nextSibling(); | 801 sibling = runEnd->nextSibling(); |
802 } | 802 } |
803 ASSERT(runEnd); | 803 ASSERT(runEnd); |
804 next = NodeTraversal::nextSkippingChildren(*runEnd); | 804 next = NodeTraversal::nextSkippingChildren(*runEnd); |
805 | 805 |
806 Node* pastEndNode = NodeTraversal::nextSkippingChildren(*runEnd); | 806 Node* pastEndNode = NodeTraversal::nextSkippingChildren(*runEnd); |
807 if (!shouldApplyInlineStyleToRun(style, runStart, pastEndNode)) | 807 if (!shouldApplyInlineStyleToRun(style, runStart, pastEndNode)) |
808 continue; | 808 continue; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 | 991 |
992 return result; | 992 return result; |
993 } | 993 } |
994 | 994 |
995 void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty
le) | 995 void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, EditingStyle* sty
le) |
996 { | 996 { |
997 ASSERT(node); | 997 ASSERT(node); |
998 | 998 |
999 node->document().updateStyleIfNeeded(); | 999 node->document().updateStyleIfNeeded(); |
1000 | 1000 |
1001 if (!style || style->isEmpty() || !node->renderer() || node->hasTagName(ifra
meTag)) | 1001 if (!style || style->isEmpty() || !node->renderer() || isHTMLIFrameElement(*
node)) |
1002 return; | 1002 return; |
1003 | 1003 |
1004 RefPtr<EditingStyle> newInlineStyle = style; | 1004 RefPtr<EditingStyle> newInlineStyle = style; |
1005 if (node->isHTMLElement() && toHTMLElement(node)->inlineStyle()) { | 1005 if (node->isHTMLElement() && toHTMLElement(node)->inlineStyle()) { |
1006 newInlineStyle = style->copy(); | 1006 newInlineStyle = style->copy(); |
1007 newInlineStyle->mergeInlineStyleOfElement(toHTMLElement(node), EditingSt
yle::OverrideValues); | 1007 newInlineStyle->mergeInlineStyleOfElement(toHTMLElement(node), EditingSt
yle::OverrideValues); |
1008 } | 1008 } |
1009 | 1009 |
1010 // Since addInlineStyleIfNeeded can't add styles to block-flow render object
s, add style attribute instead. | 1010 // Since addInlineStyleIfNeeded can't add styles to block-flow render object
s, add style attribute instead. |
1011 // FIXME: applyInlineStyleToRange should be used here instead. | 1011 // FIXME: applyInlineStyleToRange should be used here instead. |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 int endOffset = end.computeOffsetInContainerNode(); | 1297 int endOffset = end.computeOffsetInContainerNode(); |
1298 if (offsetIsBeforeLastNodeOffset(endOffset, endNode)) | 1298 if (offsetIsBeforeLastNodeOffset(endOffset, endNode)) |
1299 return false; | 1299 return false; |
1300 | 1300 |
1301 if (end.deprecatedNode()->nextSibling()) | 1301 if (end.deprecatedNode()->nextSibling()) |
1302 return false; | 1302 return false; |
1303 | 1303 |
1304 endNode = end.deprecatedNode()->parentNode(); | 1304 endNode = end.deprecatedNode()->parentNode(); |
1305 } | 1305 } |
1306 | 1306 |
1307 if (!endNode->isElementNode() || endNode->hasTagName(brTag)) | 1307 if (!endNode->isElementNode() || isHTMLBRElement(*endNode)) |
1308 return false; | 1308 return false; |
1309 | 1309 |
1310 Node* nextSibling = endNode->nextSibling(); | 1310 Node* nextSibling = endNode->nextSibling(); |
1311 if (nextSibling && areIdenticalElements(endNode, nextSibling)) { | 1311 if (nextSibling && areIdenticalElements(endNode, nextSibling)) { |
1312 Element* nextElement = toElement(nextSibling); | 1312 Element* nextElement = toElement(nextSibling); |
1313 Element* element = toElement(endNode); | 1313 Element* element = toElement(endNode); |
1314 Node* nextChild = nextElement->firstChild(); | 1314 Node* nextChild = nextElement->firstChild(); |
1315 | 1315 |
1316 mergeIdenticalElements(element, nextElement); | 1316 mergeIdenticalElements(element, nextElement); |
1317 | 1317 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 { | 1413 { |
1414 RefPtr<Node> startNode = passedStart; | 1414 RefPtr<Node> startNode = passedStart; |
1415 RefPtr<Node> endNode = passedEnd; | 1415 RefPtr<Node> endNode = passedEnd; |
1416 ASSERT(startNode->inDocument()); | 1416 ASSERT(startNode->inDocument()); |
1417 ASSERT(endNode->inDocument()); | 1417 ASSERT(endNode->inDocument()); |
1418 | 1418 |
1419 // Find appropriate font and span elements top-down. | 1419 // Find appropriate font and span elements top-down. |
1420 HTMLElement* fontContainer = 0; | 1420 HTMLElement* fontContainer = 0; |
1421 HTMLElement* styleContainer = 0; | 1421 HTMLElement* styleContainer = 0; |
1422 for (Node* container = startNode.get(); container && startNode == endNode; c
ontainer = container->firstChild()) { | 1422 for (Node* container = startNode.get(); container && startNode == endNode; c
ontainer = container->firstChild()) { |
1423 if (container->isHTMLElement() && container->hasTagName(fontTag)) | 1423 if (isHTMLFontElement(*container)) |
1424 fontContainer = toHTMLElement(container); | 1424 fontContainer = toHTMLElement(container); |
1425 bool styleContainerIsNotSpan = !styleContainer || !styleContainer->hasTa
gName(spanTag); | 1425 bool styleContainerIsNotSpan = !isHTMLSpanElement(styleContainer); |
1426 if (container->isHTMLElement()) { | 1426 if (container->isHTMLElement()) { |
1427 HTMLElement* containerElement = toHTMLElement(container); | 1427 HTMLElement* containerElement = toHTMLElement(container); |
1428 if (containerElement->hasTagName(spanTag) || (styleContainerIsNotSpa
n && containerElement->hasChildren())) | 1428 if (isHTMLSpanElement(*containerElement) || (styleContainerIsNotSpan
&& containerElement->hasChildren())) |
1429 styleContainer = toHTMLElement(container); | 1429 styleContainer = toHTMLElement(container); |
1430 } | 1430 } |
1431 if (!container->firstChild()) | 1431 if (!container->firstChild()) |
1432 break; | 1432 break; |
1433 startNode = container->firstChild(); | 1433 startNode = container->firstChild(); |
1434 endNode = container->lastChild(); | 1434 endNode = container->lastChild(); |
1435 } | 1435 } |
1436 | 1436 |
1437 // Font tags need to go outside of CSS so that CSS font sizes override leagc
y font sizes. | 1437 // Font tags need to go outside of CSS so that CSS font sizes override leagc
y font sizes. |
1438 if (styleChange.applyFontColor() || styleChange.applyFontFace() || styleChan
ge.applyFontSize()) { | 1438 if (styleChange.applyFontColor() || styleChange.applyFontFace() || styleChan
ge.applyFontSize()) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1542 String textToMove = nextText->data(); | 1542 String textToMove = nextText->data(); |
1543 insertTextIntoNode(childText, childText->length(), textToMove); | 1543 insertTextIntoNode(childText, childText->length(), textToMove); |
1544 removeNode(next); | 1544 removeNode(next); |
1545 // don't move child node pointer. it may want to merge with more text no
des. | 1545 // don't move child node pointer. it may want to merge with more text no
des. |
1546 } | 1546 } |
1547 | 1547 |
1548 updateStartEnd(newStart, newEnd); | 1548 updateStartEnd(newStart, newEnd); |
1549 } | 1549 } |
1550 | 1550 |
1551 } | 1551 } |
OLD | NEW |