diff options
Diffstat (limited to 'src/3rdparty/webkit/WebCore/editing/ApplyStyleCommand.cpp')
-rw-r--r-- | src/3rdparty/webkit/WebCore/editing/ApplyStyleCommand.cpp | 89 |
1 files changed, 56 insertions, 33 deletions
diff --git a/src/3rdparty/webkit/WebCore/editing/ApplyStyleCommand.cpp b/src/3rdparty/webkit/WebCore/editing/ApplyStyleCommand.cpp index 0c3aa42..89d862f 100644 --- a/src/3rdparty/webkit/WebCore/editing/ApplyStyleCommand.cpp +++ b/src/3rdparty/webkit/WebCore/editing/ApplyStyleCommand.cpp @@ -383,7 +383,11 @@ size_t numEditingStyleProperties = sizeof(editingStyleProperties)/sizeof(editing PassRefPtr<CSSMutableStyleDeclaration> editingStyleAtPosition(Position pos, ShouldIncludeTypingStyle shouldIncludeTypingStyle) { RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = pos.computedStyle(); - RefPtr<CSSMutableStyleDeclaration> style = computedStyleAtPosition->copyPropertiesInSet(editingStyleProperties, numEditingStyleProperties); + RefPtr<CSSMutableStyleDeclaration> style; + if (!computedStyleAtPosition) + style = CSSMutableStyleDeclaration::create(); + else + style = computedStyleAtPosition->copyPropertiesInSet(editingStyleProperties, numEditingStyleProperties); if (style && pos.node() && pos.node()->computedStyle()) { RenderStyle* renderStyle = pos.node()->computedStyle(); @@ -1075,6 +1079,23 @@ void ApplyStyleCommand::applyInlineStyleToRange(CSSMutableStyleDeclaration* styl } } +bool ApplyStyleCommand::shouldRemoveTextDecorationTag(CSSStyleDeclaration* styleToApply, int textDecorationAddedByTag) const +{ + // Honor text-decorations-in-effect + RefPtr<CSSValue> textDecorationsToApply = styleToApply->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect); + if (!textDecorationsToApply || !textDecorationsToApply->isValueList()) + textDecorationsToApply = styleToApply->getPropertyCSSValue(CSSPropertyTextDecoration); + + // When there is no text decorations to apply, remove any one of u, s, & strike + if (!textDecorationsToApply || !textDecorationsToApply->isValueList()) + return true; + + // Remove node if it implicitly adds style not present in styleToApply + CSSValueList* valueList = static_cast<CSSValueList*>(textDecorationsToApply.get()); + RefPtr<CSSPrimitiveValue> value = CSSPrimitiveValue::createIdentifier(textDecorationAddedByTag); + return !valueList->hasValue(value.get()); +} + // This function maps from styling tags to CSS styles. Used for knowing which // styling tags should be removed when toggling styles. bool ApplyStyleCommand::implicitlyStyledElementShouldBeRemovedWhenApplyingStyle(HTMLElement* elem, CSSMutableStyleDeclaration* style) @@ -1088,36 +1109,25 @@ bool ApplyStyleCommand::implicitlyStyledElementShouldBeRemovedWhenApplyingStyle( case CSSPropertyFontWeight: // IE inserts "strong" tags for execCommand("bold"), so we remove them, even though they're not strictly presentational if (elem->hasLocalName(bTag) || elem->hasLocalName(strongTag)) - return true; + return !equalIgnoringCase(property.value()->cssText(), "bold") || !elem->hasChildNodes(); break; case CSSPropertyVerticalAlign: - if (elem->hasLocalName(subTag) || elem->hasLocalName(supTag)) - return true; + if (elem->hasLocalName(subTag)) + return !equalIgnoringCase(property.value()->cssText(), "sub") || !elem->hasChildNodes(); + if (elem->hasLocalName(supTag)) + return !equalIgnoringCase(property.value()->cssText(), "sup") || !elem->hasChildNodes(); break; case CSSPropertyFontStyle: // IE inserts "em" tags for execCommand("italic"), so we remove them, even though they're not strictly presentational if (elem->hasLocalName(iTag) || elem->hasLocalName(emTag)) - return true; + return !equalIgnoringCase(property.value()->cssText(), "italic") || !elem->hasChildNodes(); break; case CSSPropertyTextDecoration: case CSSPropertyWebkitTextDecorationsInEffect: - ASSERT(property.value()); - if (property.value()->isValueList()) { - CSSValueList* valueList = static_cast<CSSValueList*>(property.value()); - DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, underline, (CSSPrimitiveValue::createIdentifier(CSSValueUnderline))); - DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, lineThrough, (CSSPrimitiveValue::createIdentifier(CSSValueLineThrough))); - // Because style is new style to be applied, we delete element only if the element is not used in style. - if (!valueList->hasValue(underline.get()) && elem->hasLocalName(uTag)) - return true; - if (!valueList->hasValue(lineThrough.get()) && (elem->hasLocalName(strikeTag) || elem->hasLocalName(sTag))) - return true; - } else { - // If the value is NOT a list, then it must be "none", in which case we should remove all text decorations. - ASSERT(property.value()->cssText() == "none"); - if (elem->hasLocalName(uTag) || elem->hasLocalName(strikeTag) || elem->hasLocalName(sTag)) - return true; - } - break; + if (elem->hasLocalName(uTag)) + return shouldRemoveTextDecorationTag(style, CSSValueUnderline) || !elem->hasChildNodes(); + else if (elem->hasLocalName(sTag) || elem->hasTagName(strikeTag)) + return shouldRemoveTextDecorationTag(style,CSSValueLineThrough) || !elem->hasChildNodes(); } } return false; @@ -1303,19 +1313,18 @@ void ApplyStyleCommand::applyTextDecorationStyle(Node *node, CSSMutableStyleDecl if (!style || style->cssText().isEmpty()) return; - if (node->isTextNode()) { - RefPtr<HTMLElement> styleSpan = createStyleSpanElement(document()); - surroundNodeRangeWithElement(node, node, styleSpan.get()); - node = styleSpan.get(); - } - - if (!node->isElementNode()) - return; + StyleChange styleChange(style, Position(node, 0)); + if (styleChange.cssStyle().length()) { + if (node->isTextNode()) { + RefPtr<HTMLElement> styleSpan = createStyleSpanElement(document()); + surroundNodeRangeWithElement(node, node, styleSpan.get()); + node = styleSpan.get(); + } - HTMLElement *element = static_cast<HTMLElement *>(node); + if (!node->isElementNode()) + return; - StyleChange styleChange(style, Position(element, 0)); - if (styleChange.cssStyle().length()) { + HTMLElement *element = static_cast<HTMLElement *>(node); String cssText = styleChange.cssStyle(); CSSMutableStyleDeclaration *decl = element->inlineStyleDecl(); if (decl) @@ -1675,6 +1684,20 @@ void ApplyStyleCommand::surroundNodeRangeWithElement(Node* startNode, Node* endN break; node = next; } + + Node* nextSibling = element->nextSibling(); + Node* previousSibling = element->previousSibling(); + if (nextSibling && nextSibling->isElementNode() && nextSibling->isContentEditable() + && areIdenticalElements(element.get(), static_cast<Element*>(nextSibling))) + mergeIdenticalElements(element, static_cast<Element*>(nextSibling)); + + if (previousSibling && previousSibling->isElementNode() && previousSibling->isContentEditable()) { + Node* mergedElement = previousSibling->nextSibling(); + if (mergedElement->isElementNode() && mergedElement->isContentEditable() + && areIdenticalElements(static_cast<Element*>(previousSibling), static_cast<Element*>(mergedElement))) + mergeIdenticalElements(static_cast<Element*>(previousSibling), static_cast<Element*>(mergedElement)); + } + // FIXME: We should probably call updateStartEnd if the start or end was in the node // range so that the endingSelection() is canonicalized. See the comments at the end of // VisibleSelection::validate(). |