diff options
author | John Reck <jreck@google.com> | 2010-11-04 12:00:17 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2010-11-09 11:35:04 -0800 |
commit | e14391e94c850b8bd03680c23b38978db68687a8 (patch) | |
tree | 3fed87e6620fecaf3edc7259ae58a11662bedcb2 /WebCore/editing/ApplyStyleCommand.cpp | |
parent | 1bd705833a68f07850cf7e204b26f8d328d16951 (diff) | |
download | external_webkit-e14391e94c850b8bd03680c23b38978db68687a8.zip external_webkit-e14391e94c850b8bd03680c23b38978db68687a8.tar.gz external_webkit-e14391e94c850b8bd03680c23b38978db68687a8.tar.bz2 |
Merge Webkit at r70949: Initial merge by git.
Change-Id: I77b8645c083b5d0da8dba73ed01d4014aab9848e
Diffstat (limited to 'WebCore/editing/ApplyStyleCommand.cpp')
-rw-r--r-- | WebCore/editing/ApplyStyleCommand.cpp | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/WebCore/editing/ApplyStyleCommand.cpp b/WebCore/editing/ApplyStyleCommand.cpp index 3f60a8b..8862da7 100644 --- a/WebCore/editing/ApplyStyleCommand.cpp +++ b/WebCore/editing/ApplyStyleCommand.cpp @@ -538,6 +538,7 @@ ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* st , m_useEndingSelection(true) , m_styledInlineElement(0) , m_removeOnly(false) + , m_isInlineElementToRemoveFunction(0) { } @@ -551,6 +552,7 @@ ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* st , m_useEndingSelection(false) , m_styledInlineElement(0) , m_removeOnly(false) + , m_isInlineElementToRemoveFunction(0) { } @@ -564,6 +566,21 @@ ApplyStyleCommand::ApplyStyleCommand(PassRefPtr<Element> element, bool removeOnl , m_useEndingSelection(true) , m_styledInlineElement(element) , m_removeOnly(removeOnly) + , m_isInlineElementToRemoveFunction(0) +{ +} + +ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, IsInlineElementToRemoveFunction isInlineElementToRemoveFunction, EditAction editingAction) + : CompositeEditCommand(document) + , m_style(style->makeMutable()) + , m_editingAction(editingAction) + , m_propertyLevel(PropertyDefault) + , m_start(endingSelection().start().downstream()) + , m_end(endingSelection().end().upstream()) + , m_useEndingSelection(true) + , m_styledInlineElement(0) + , m_removeOnly(true) + , m_isInlineElementToRemoveFunction(isInlineElementToRemoveFunction) { } @@ -605,7 +622,7 @@ void ApplyStyleCommand::doApply() applyBlockStyle(blockStyle.get()); // apply any remaining styles to the inline elements // NOTE: hopefully, this string comparison is the same as checking for a non-null diff - if (blockStyle->length() < m_style->length() || m_styledInlineElement) { + if (blockStyle->length() < m_style->length() || m_styledInlineElement || m_isInlineElementToRemoveFunction) { RefPtr<CSSMutableStyleDeclaration> inlineStyle = m_style->copy(); applyRelativeFontStyleChange(inlineStyle.get()); blockStyle->diff(inlineStyle.get()); @@ -664,9 +681,11 @@ void ApplyStyleCommand::applyBlockStyle(CSSMutableStyleDeclaration *style) StyleChange styleChange(style, paragraphStart.deepEquivalent()); if (styleChange.cssStyle().length() || m_removeOnly) { RefPtr<Node> block = enclosingBlock(paragraphStart.deepEquivalent().node()); - RefPtr<Node> newBlock = moveParagraphContentsToNewBlockIfNecessary(paragraphStart.deepEquivalent()); - if (newBlock) - block = newBlock; + if (!m_removeOnly) { + RefPtr<Node> newBlock = moveParagraphContentsToNewBlockIfNecessary(paragraphStart.deepEquivalent()); + if (newBlock) + block = newBlock; + } ASSERT(block->isHTMLElement()); if (block->isHTMLElement()) { removeCSSStyle(style, static_cast<HTMLElement*>(block.get())); @@ -1104,8 +1123,10 @@ void ApplyStyleCommand::fixRangeAndApplyInlineStyle(CSSMutableStyleDeclaration* // to generate <font color="blue" size="4">hello</font> instead of <font color="blue"><font size="4">hello</font></font> RefPtr<Range> range = Range::create(startNode->document(), start, end); Element* editableRoot = startNode->rootEditableElement(); - while (editableRoot && startNode->parentNode() != editableRoot && isNodeVisiblyContainedWithin(startNode->parentNode(), range.get())) - startNode = startNode->parentNode(); + if (startNode != editableRoot) { + while (editableRoot && startNode->parentNode() != editableRoot && isNodeVisiblyContainedWithin(startNode->parentNode(), range.get())) + startNode = startNode->parentNode(); + } applyInlineStyleToNodeRange(style, startNode, pastEndNode); } @@ -1126,6 +1147,9 @@ static bool containsNonEditableRegion(Node* node) void ApplyStyleCommand::applyInlineStyleToNodeRange(CSSMutableStyleDeclaration* style, Node* node, Node* pastEndNode) { + if (m_removeOnly) + return; + for (Node* next; node && node != pastEndNode; node = next) { next = node->traverseNextNode(); @@ -1171,10 +1195,16 @@ void ApplyStyleCommand::applyInlineStyleToNodeRange(CSSMutableStyleDeclaration* if (!removeStyleFromRunBeforeApplyingStyle(style, node, runEnd)) continue; - addInlineStyleIfNeeded(style, node, runEnd, m_removeOnly ? DoNotAddStyledElement : AddStyledElement); + addInlineStyleIfNeeded(style, node, runEnd, AddStyledElement); } } +bool ApplyStyleCommand::isStyledInlineElementToRemove(Element* element) const +{ + return (m_styledInlineElement && element->hasTagName(m_styledInlineElement->tagQName())) + || (m_isInlineElementToRemoveFunction && m_isInlineElementToRemoveFunction(element)); +} + bool ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle(CSSMutableStyleDeclaration* style, Node*& runStart, Node*& runEnd) { ASSERT(runStart && runEnd && runStart->parentNode() == runEnd->parentNode()); @@ -1183,6 +1213,7 @@ bool ApplyStyleCommand::removeStyleFromRunBeforeApplyingStyle(CSSMutableStyleDec for (Node* node = runStart; node && node != pastEndNode; node = node->traverseNextNode()) { if (node->childNodeCount()) continue; + // We don't consider m_isInlineElementToRemoveFunction here because we never apply style when m_isInlineElementToRemoveFunction is specified if (getPropertiesNotIn(style, computedStyle(node).get())->length() || (m_styledInlineElement && !enclosingNodeWithTag(positionBeforeNode(node), m_styledInlineElement->tagQName()))) { needToApplyStyle = true; @@ -1222,7 +1253,7 @@ bool ApplyStyleCommand::removeInlineStyleFromElement(CSSMutableStyleDeclaration* if (!element->parentNode() || !element->parentNode()->isContentEditable()) return false; - if (m_styledInlineElement && element->hasTagName(m_styledInlineElement->tagQName())) { + if (isStyledInlineElementToRemove(element)) { if (mode == RemoveNone) return true; ASSERT(extractedStyle); @@ -1331,7 +1362,7 @@ bool ApplyStyleCommand::removeImplicitlyStyledElement(CSSMutableStyleDeclaration continue; // If CSS value is primitive, then skip if they are equal. } - if (extractedStyle) + if (extractedStyle && mapValue) extractedStyle->setProperty(equivalent.propertyID, mapValue->cssText()); if (mode == RemoveNone) @@ -1504,6 +1535,9 @@ void ApplyStyleCommand::pushDownInlineStyleAroundNode(CSSMutableStyleDeclaration // The outer loop is traversing the tree vertically from highestAncestor to targetNode Node* current = highestAncestor; + // Along the way, styled elements that contain targetNode are removed and accumulated into elementsToPushDown. + // Each child of the removed element, exclusing ancestors of targetNode, is then wrapped by clones of elements in elementsToPushDown. + Vector<RefPtr<Element> > elementsToPushDown; while (current != targetNode) { ASSERT(current); ASSERT(current->isHTMLElement()); @@ -1511,8 +1545,10 @@ void ApplyStyleCommand::pushDownInlineStyleAroundNode(CSSMutableStyleDeclaration Node* child = current->firstChild(); Node* lastChild = current->lastChild(); RefPtr<StyledElement> styledElement; - if (current->isStyledElement() && m_styledInlineElement && current->hasTagName(m_styledInlineElement->tagQName())) + if (current->isStyledElement() && isStyledInlineElementToRemove(static_cast<Element*>(current))) { styledElement = static_cast<StyledElement*>(current); + elementsToPushDown.append(styledElement); + } RefPtr<CSSMutableStyleDeclaration> styleToPushDown = CSSMutableStyleDeclaration::create(); removeInlineStyleFromElement(style, static_cast<HTMLElement*>(current), RemoveIfNeeded, styleToPushDown.get()); @@ -1521,17 +1557,14 @@ void ApplyStyleCommand::pushDownInlineStyleAroundNode(CSSMutableStyleDeclaration while (child) { Node* nextChild = child->nextSibling(); - if (child != targetNode && styledElement) { - // If child has children, wrap children of child by a clone of the styled element to avoid infinite loop. - // Otherwise, wrap the child by the styled element, and we won't fall into an infinite loop. - RefPtr<Element> wrapper = styledElement->cloneElementWithoutChildren(); - ExceptionCode ec = 0; - wrapper->removeAttribute(styleAttr, ec); - ASSERT(!ec); - if (child->firstChild()) - surroundNodeRangeWithElement(child->firstChild(), child->lastChild(), wrapper); - else + if (!child->contains(targetNode) && elementsToPushDown.size()) { + for (size_t i = 0; i < elementsToPushDown.size(); i++) { + RefPtr<Element> wrapper = elementsToPushDown[i]->cloneElementWithoutChildren(); + ExceptionCode ec = 0; + wrapper->removeAttribute(styleAttr, ec); + ASSERT(!ec); surroundNodeRangeWithElement(child, child, wrapper); + } } // Apply text decoration to all nodes containing targetNode and their siblings but NOT to targetNode @@ -1594,7 +1627,7 @@ void ApplyStyleCommand::removeInlineStyle(PassRefPtr<CSSMutableStyleDeclaration> RefPtr<Node> next = elem->traverseNextNode(); RefPtr<CSSMutableStyleDeclaration> styleToPushDown; PassRefPtr<Node> childNode = 0; - if (m_styledInlineElement && elem->hasTagName(m_styledInlineElement->tagQName())) { + if (isStyledInlineElementToRemove(elem.get())) { styleToPushDown = CSSMutableStyleDeclaration::create(); childNode = elem->firstChild(); } |