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