Commit 0d96cf61 authored by rniwa@webkit.org's avatar rniwa@webkit.org

2010-11-08 Ryosuke Niwa <rniwa@webkit.org>

        Reviewed by Darin Adler.

        Remove the remaining editing-style functions from ApplyStyleCommand
        https://bugs.webkit.org/show_bug.cgi?id=49155

        Replaced removeNonEditingProperties, editingStyleAtPosition, prepareEditingStyleToApplyAt,
        and removeStylesAddedByNode in ApplyStyleCommand.cpp by removeNonEditingProperties, EditingStyle::create,
        prepareToApplyAt, and removeStyleAddedByNode in EditingStyle.cpp.

        Also removed unnecessary header includes from various cpp files.

        No tests are added since this is a cleanup.

        * editing/ApplyStyleCommand.cpp: Removed removeNonEditingProperties, editingStyleAtPosition,
        prepareEditingStyleToApplyAt, and removeStylesAddedByNode.
        * editing/ApplyStyleCommand.h: Ditto.
        * editing/DeleteSelectionCommand.cpp: Removed removeEnclosingAnchorStyle.
        (WebCore::DeleteSelectionCommand::saveTypingStyleState): Calls removeStylesAddedByNode instead.
        * editing/EditingStyle.cpp:
        (WebCore::copyEditingProperties): Moved and renamed ApplyStyleCommand::removeNonEditingProperties.
        (WebCore::editingStyleFromComputedStyle): Calls copyEditingProperties. Changed the argument to PassRefPtr
        as supposed to a raw pointer for convenience.
        (WebCore::EditingStyle::init): Calls editingStyleFromComputedStyle.
        (WebCore::EditingStyle::removeStyleAddedByNode): Added.
        (WebCore::EditingStyle::removeStyleConflictingWithStyleOfNode): Added.
        (WebCore::EditingStyle::removeNonEditingProperties): Added.
        (WebCore::editingStyleIncludingTypingStyle): Calls copyEditingProperties.
        * editing/EditingStyle.h: Added prototypes.
        * editing/Editor.cpp:
        (WebCore::Editor::selectionComputedStyle): Uses EditingStyle.
        * editing/InsertParagraphSeparatorCommand.cpp:
        (WebCore::InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion): Ditto.
        (WebCore::InsertParagraphSeparatorCommand::applyStyleAfterInsertion): Ditto.
        * editing/InsertParagraphSeparatorCommand.h:
        * editing/RemoveFormatCommand.cpp:
        (WebCore::RemoveFormatCommand::doApply): Ditto.
        * editing/ReplaceSelectionCommand.cpp:
        (WebCore::handleStyleSpansBeforeInsertion): Ditto.
        (WebCore::ReplaceSelectionCommand::handleStyleSpans): Ditto.
        (WebCore::ReplaceSelectionCommand::doApply): Ditto.
        (WebCore::ReplaceSelectionCommand::completeHTMLReplacement): Ditto.
        * editing/ReplaceSelectionCommand.h:
        * editing/markup.cpp: Removed removeEnclosingMailBlockquoteStyle and removeDefaultStyles.
        (WebCore::createMarkup): Uses EditingStyle.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@71556 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 0ffc60e2
2010-11-08 Ryosuke Niwa <rniwa@webkit.org>
Reviewed by Darin Adler.
Remove the remaining editing-style functions from ApplyStyleCommand
https://bugs.webkit.org/show_bug.cgi?id=49155
Replaced removeNonEditingProperties, editingStyleAtPosition, prepareEditingStyleToApplyAt,
and removeStylesAddedByNode in ApplyStyleCommand.cpp by removeNonEditingProperties, EditingStyle::create,
prepareToApplyAt, and removeStyleAddedByNode in EditingStyle.cpp.
Also removed unnecessary header includes from various cpp files.
No tests are added since this is a cleanup.
* editing/ApplyStyleCommand.cpp: Removed removeNonEditingProperties, editingStyleAtPosition,
prepareEditingStyleToApplyAt, and removeStylesAddedByNode.
* editing/ApplyStyleCommand.h: Ditto.
* editing/DeleteSelectionCommand.cpp: Removed removeEnclosingAnchorStyle.
(WebCore::DeleteSelectionCommand::saveTypingStyleState): Calls removeStylesAddedByNode instead.
* editing/EditingStyle.cpp:
(WebCore::copyEditingProperties): Moved and renamed ApplyStyleCommand::removeNonEditingProperties.
(WebCore::editingStyleFromComputedStyle): Calls copyEditingProperties. Changed the argument to PassRefPtr
as supposed to a raw pointer for convenience.
(WebCore::EditingStyle::init): Calls editingStyleFromComputedStyle.
(WebCore::EditingStyle::removeStyleAddedByNode): Added.
(WebCore::EditingStyle::removeStyleConflictingWithStyleOfNode): Added.
(WebCore::EditingStyle::removeNonEditingProperties): Added.
(WebCore::editingStyleIncludingTypingStyle): Calls copyEditingProperties.
* editing/EditingStyle.h: Added prototypes.
* editing/Editor.cpp:
(WebCore::Editor::selectionComputedStyle): Uses EditingStyle.
* editing/InsertParagraphSeparatorCommand.cpp:
(WebCore::InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion): Ditto.
(WebCore::InsertParagraphSeparatorCommand::applyStyleAfterInsertion): Ditto.
* editing/InsertParagraphSeparatorCommand.h:
* editing/RemoveFormatCommand.cpp:
(WebCore::RemoveFormatCommand::doApply): Ditto.
* editing/ReplaceSelectionCommand.cpp:
(WebCore::handleStyleSpansBeforeInsertion): Ditto.
(WebCore::ReplaceSelectionCommand::handleStyleSpans): Ditto.
(WebCore::ReplaceSelectionCommand::doApply): Ditto.
(WebCore::ReplaceSelectionCommand::completeHTMLReplacement): Ditto.
* editing/ReplaceSelectionCommand.h:
* editing/markup.cpp: Removed removeEnclosingMailBlockquoteStyle and removeDefaultStyles.
(WebCore::createMarkup): Uses EditingStyle.
2010-11-08 Simon Fraser <simon.fraser@apple.com>
Reviewed by Dan Bernstein.
......@@ -429,104 +429,6 @@ RefPtr<CSSMutableStyleDeclaration> getPropertiesNotIn(CSSStyleDeclaration* style
return result;
}
// Editing style properties must be preserved during editing operation.
// e.g. when a user inserts a new paragraph, all properties listed here must be copied to the new paragraph.
// FIXME: The current editingStyleProperties contains all inheritableProperties but we may not need to preserve all inheritable properties
static const int editingStyleProperties[] = {
// CSS inheritable properties
CSSPropertyBorderCollapse,
CSSPropertyColor,
CSSPropertyFontFamily,
CSSPropertyFontSize,
CSSPropertyFontStyle,
CSSPropertyFontVariant,
CSSPropertyFontWeight,
CSSPropertyLetterSpacing,
CSSPropertyLineHeight,
CSSPropertyOrphans,
CSSPropertyTextAlign,
CSSPropertyTextIndent,
CSSPropertyTextTransform,
CSSPropertyWhiteSpace,
CSSPropertyWidows,
CSSPropertyWordSpacing,
CSSPropertyWebkitBorderHorizontalSpacing,
CSSPropertyWebkitBorderVerticalSpacing,
CSSPropertyWebkitTextDecorationsInEffect,
CSSPropertyWebkitTextFillColor,
CSSPropertyWebkitTextSizeAdjust,
CSSPropertyWebkitTextStrokeColor,
CSSPropertyWebkitTextStrokeWidth,
};
size_t numEditingStyleProperties = sizeof(editingStyleProperties)/sizeof(editingStyleProperties[0]);
RefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::removeNonEditingProperties(CSSStyleDeclaration* style)
{
return style->copyPropertiesInSet(editingStyleProperties, numEditingStyleProperties);
}
PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::editingStyleAtPosition(Position pos, ShouldIncludeTypingStyle shouldIncludeTypingStyle)
{
RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = pos.computedStyle();
RefPtr<CSSMutableStyleDeclaration> style;
if (!computedStyleAtPosition)
style = CSSMutableStyleDeclaration::create();
else
style = removeNonEditingProperties(computedStyleAtPosition.get());
if (style && pos.node() && pos.node()->computedStyle()) {
RenderStyle* renderStyle = pos.node()->computedStyle();
// If a node's text fill color is invalid, then its children use
// their font-color as their text fill color (they don't
// inherit it). Likewise for stroke color.
ExceptionCode ec = 0;
if (!renderStyle->textFillColor().isValid())
style->removeProperty(CSSPropertyWebkitTextFillColor, ec);
if (!renderStyle->textStrokeColor().isValid())
style->removeProperty(CSSPropertyWebkitTextStrokeColor, ec);
ASSERT(ec == 0);
if (renderStyle->fontDescription().keywordSize())
style->setProperty(CSSPropertyFontSize, computedStyleAtPosition->getFontSizeCSSValuePreferringKeyword()->cssText());
}
if (shouldIncludeTypingStyle == IncludeTypingStyle) {
RefPtr<CSSMutableStyleDeclaration> typingStyle = pos.node()->document()->frame()->selection()->typingStyle();
if (typingStyle)
style->merge(typingStyle.get());
}
return style.release();
}
void prepareEditingStyleToApplyAt(CSSMutableStyleDeclaration* editingStyle, Position pos)
{
// ReplaceSelectionCommand::handleStyleSpans() requires that this function only removes the editing style.
// If this function was modified in the future to delete all redundant properties, then add a boolean value to indicate
// which one of editingStyleAtPosition or computedStyle is called.
RefPtr<CSSMutableStyleDeclaration> style = ApplyStyleCommand::editingStyleAtPosition(pos);
style->diff(editingStyle);
// if alpha value is zero, we don't add the background color.
RefPtr<CSSValue> backgroundColor = editingStyle->getPropertyCSSValue(CSSPropertyBackgroundColor);
if (backgroundColor && backgroundColor->isPrimitiveValue()) {
CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(backgroundColor.get());
Color color = Color(primitiveValue->getRGBA32Value());
ExceptionCode ec;
if (color.alpha() == 0)
editingStyle->removeProperty(CSSPropertyBackgroundColor, ec);
}
}
void removeStylesAddedByNode(CSSMutableStyleDeclaration* editingStyle, Node* node)
{
ASSERT(node);
ASSERT(node->parentNode());
RefPtr<CSSMutableStyleDeclaration> parentStyle = ApplyStyleCommand::editingStyleAtPosition(Position(node->parentNode(), 0));
RefPtr<CSSMutableStyleDeclaration> style = ApplyStyleCommand::editingStyleAtPosition(Position(node, 0));
parentStyle->diff(style.get());
style->diff(editingStyle);
}
ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, EditAction editingAction, EPropertyLevel propertyLevel)
: CompositeEditCommand(document)
, m_style(style->makeMutable())
......
......@@ -64,9 +64,6 @@ public:
return adoptRef(new ApplyStyleCommand(document, style, isInlineElementToRemoveFunction, action));
}
static RefPtr<CSSMutableStyleDeclaration> removeNonEditingProperties(CSSStyleDeclaration* style);
static PassRefPtr<CSSMutableStyleDeclaration> editingStyleAtPosition(Position pos, ShouldIncludeTypingStyle shouldIncludeTypingStyle = IgnoreTypingStyle);
private:
ApplyStyleCommand(Document*, CSSStyleDeclaration*, EditAction, EPropertyLevel);
ApplyStyleCommand(Document*, CSSStyleDeclaration*, const Position& start, const Position& end, EditAction, EPropertyLevel);
......@@ -137,9 +134,6 @@ bool isStyleSpan(const Node*);
PassRefPtr<HTMLElement> createStyleSpanElement(Document*);
RefPtr<CSSMutableStyleDeclaration> getPropertiesNotIn(CSSStyleDeclaration* styleWithRedundantProperties, CSSStyleDeclaration* baseStyle);
void prepareEditingStyleToApplyAt(CSSMutableStyleDeclaration*, Position);
void removeStylesAddedByNode(CSSMutableStyleDeclaration*, Node*);
} // namespace WebCore
#endif
......@@ -26,25 +26,18 @@
#include "config.h"
#include "DeleteSelectionCommand.h"
#include "CSSMutableStyleDeclaration.h"
#include "Document.h"
#include "DocumentFragment.h"
#include "Editor.h"
#include "EditorClient.h"
#include "Element.h"
#include "Frame.h"
#include "Logging.h"
#include "CSSComputedStyleDeclaration.h"
#include "htmlediting.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "markup.h"
#include "RenderTableCell.h"
#include "ReplaceSelectionCommand.h"
#include "Text.h"
#include "TextIterator.h"
#include "visible_units.h"
#include "ApplyStyleCommand.h"
namespace WebCore {
......@@ -272,15 +265,6 @@ void DeleteSelectionCommand::initializePositionData()
m_endBlock = enclosingNodeOfType(rangeCompliantEquivalent(m_upstreamEnd), &isBlock, false);
}
static void removeEnclosingAnchorStyle(CSSMutableStyleDeclaration* style, const Position& position)
{
Node* enclosingAnchor = enclosingAnchorElement(position);
if (!enclosingAnchor || !enclosingAnchor->parentNode())
return;
removeStylesAddedByNode(style, enclosingAnchor);
}
void DeleteSelectionCommand::saveTypingStyleState()
{
// A common case is deleting characters that are all from the same text node. In
......@@ -295,8 +279,7 @@ void DeleteSelectionCommand::saveTypingStyleState()
// Figure out the typing style in effect before the delete is done.
m_typingStyle = EditingStyle::create(positionBeforeTabSpan(m_selectionToDelete.start()));
removeEnclosingAnchorStyle(m_typingStyle->style(), m_selectionToDelete.start());
m_typingStyle->removeStyleAddedByNode(enclosingAnchorElement(m_selectionToDelete.start()));
// If we're deleting into a Mail blockquote, save the style at end() instead of start()
// We'll use this later in computeTypingStyleAfterDelete if we end up outside of a Mail blockquote
......
......@@ -36,11 +36,47 @@
namespace WebCore {
static PassRefPtr<CSSMutableStyleDeclaration> editingStyleFromComputedStyle(CSSComputedStyleDeclaration* style)
// Editing style properties must be preserved during editing operation.
// e.g. when a user inserts a new paragraph, all properties listed here must be copied to the new paragraph.
// FIXME: The current editingStyleProperties contains all inheritableProperties but we may not need to preserve all inheritable properties
static const int editingStyleProperties[] = {
// CSS inheritable properties
CSSPropertyBorderCollapse,
CSSPropertyColor,
CSSPropertyFontFamily,
CSSPropertyFontSize,
CSSPropertyFontStyle,
CSSPropertyFontVariant,
CSSPropertyFontWeight,
CSSPropertyLetterSpacing,
CSSPropertyLineHeight,
CSSPropertyOrphans,
CSSPropertyTextAlign,
CSSPropertyTextIndent,
CSSPropertyTextTransform,
CSSPropertyWhiteSpace,
CSSPropertyWidows,
CSSPropertyWordSpacing,
CSSPropertyWebkitBorderHorizontalSpacing,
CSSPropertyWebkitBorderVerticalSpacing,
CSSPropertyWebkitTextDecorationsInEffect,
CSSPropertyWebkitTextFillColor,
CSSPropertyWebkitTextSizeAdjust,
CSSPropertyWebkitTextStrokeColor,
CSSPropertyWebkitTextStrokeWidth,
};
size_t numEditingStyleProperties = sizeof(editingStyleProperties) / sizeof(editingStyleProperties[0]);
static PassRefPtr<CSSMutableStyleDeclaration> copyEditingProperties(CSSStyleDeclaration* style)
{
return style->copyPropertiesInSet(editingStyleProperties, numEditingStyleProperties);
}
static PassRefPtr<CSSMutableStyleDeclaration> editingStyleFromComputedStyle(PassRefPtr<CSSComputedStyleDeclaration> style)
{
if (!style)
return CSSMutableStyleDeclaration::create();
return ApplyStyleCommand::removeNonEditingProperties(style);
return copyEditingProperties(style.get());
}
EditingStyle::EditingStyle()
......@@ -69,7 +105,7 @@ EditingStyle::EditingStyle(const CSSStyleDeclaration* style)
void EditingStyle::init(Node* node)
{
RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = computedStyle(node);
m_mutableStyle = editingStyleFromComputedStyle(computedStyleAtPosition.get());
m_mutableStyle = editingStyleFromComputedStyle(computedStyleAtPosition);
if (node && node->computedStyle()) {
RenderStyle* renderStyle = node->computedStyle();
......@@ -127,6 +163,35 @@ void EditingStyle::removeBlockProperties()
m_mutableStyle->removeBlockProperties();
}
void EditingStyle::removeStyleAddedByNode(Node* node)
{
if (!node || !node->parentNode())
return;
RefPtr<CSSMutableStyleDeclaration> parentStyle = editingStyleFromComputedStyle(computedStyle(node->parentNode()));
RefPtr<CSSMutableStyleDeclaration> nodeStyle = editingStyleFromComputedStyle(computedStyle(node));
parentStyle->diff(nodeStyle.get());
nodeStyle->diff(m_mutableStyle.get());
}
void EditingStyle::removeStyleConflictingWithStyleOfNode(Node* node)
{
if (!node || !node->parentNode())
return;
RefPtr<CSSMutableStyleDeclaration> parentStyle = editingStyleFromComputedStyle(computedStyle(node->parentNode()));
RefPtr<CSSMutableStyleDeclaration> nodeStyle = editingStyleFromComputedStyle(computedStyle(node));
parentStyle->diff(nodeStyle.get());
CSSMutableStyleDeclaration::const_iterator end = nodeStyle->end();
for (CSSMutableStyleDeclaration::const_iterator it = nodeStyle->begin(); it != end; ++it)
m_mutableStyle->removeProperty(it->id());
}
void EditingStyle::removeNonEditingProperties()
{
if (m_mutableStyle)
m_mutableStyle = copyEditingProperties(m_mutableStyle.get());
}
void EditingStyle::prepareToApplyAt(const Position& position)
{
// ReplaceSelectionCommand::handleStyleSpans() requires that this function only removes the editing style.
......@@ -148,11 +213,8 @@ PassRefPtr<EditingStyle> editingStyleIncludingTypingStyle(const Position& positi
{
RefPtr<EditingStyle> editingStyle = EditingStyle::create(position);
RefPtr<CSSMutableStyleDeclaration> typingStyle = position.node()->document()->frame()->selection()->typingStyle();
if (typingStyle) {
RefPtr<CSSMutableStyleDeclaration> inheritableTypingStyle = typingStyle->copy();
ApplyStyleCommand::removeNonEditingProperties(inheritableTypingStyle.get());
editingStyle->style()->merge(inheritableTypingStyle.get(), true);
}
if (typingStyle)
editingStyle->style()->merge(copyEditingProperties(typingStyle.get()).get());
return editingStyle;
}
......
......@@ -68,6 +68,9 @@ public:
void setStyle(PassRefPtr<CSSMutableStyleDeclaration>);
void clear();
void removeBlockProperties();
void removeStyleAddedByNode(Node* node);
void removeStyleConflictingWithStyleOfNode(Node* node);
void removeNonEditingProperties();
void prepareToApplyAt(const Position&);
private:
......
......@@ -3085,10 +3085,10 @@ PassRefPtr<CSSMutableStyleDeclaration> Editor::selectionComputedStyle(bool& shou
if (!m_frame->selection()->typingStyle())
return mutableStyle;
RefPtr<CSSMutableStyleDeclaration> typingStyle = m_frame->selection()->typingStyle()->copy();
ApplyStyleCommand::removeNonEditingProperties(typingStyle.get());
prepareEditingStyleToApplyAt(typingStyle.get(), position);
mutableStyle->merge(typingStyle.get());
RefPtr<EditingStyle> typingStyle = EditingStyle::create(m_frame->selection()->typingStyle());
typingStyle->removeNonEditingProperties();
typingStyle->prepareToApplyAt(position);
mutableStyle->merge(typingStyle->style());
return mutableStyle;
}
......
......@@ -26,19 +26,16 @@
#include "config.h"
#include "InsertParagraphSeparatorCommand.h"
#include "CSSComputedStyleDeclaration.h"
#include "CSSMutableStyleDeclaration.h"
#include "CSSPropertyNames.h"
#include "Document.h"
#include "EditingStyle.h"
#include "HTMLElement.h"
#include "HTMLNames.h"
#include "InsertLineBreakCommand.h"
#include "Logging.h"
#include "RenderObject.h"
#include "Text.h"
#include "htmlediting.h"
#include "visible_units.h"
#include "ApplyStyleCommand.h"
namespace WebCore {
......@@ -82,7 +79,7 @@ void InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion(const Positi
if (!isStartOfParagraph(visiblePos) && !isEndOfParagraph(visiblePos))
return;
m_style = ApplyStyleCommand::editingStyleAtPosition(pos, IncludeTypingStyle);
m_style = editingStyleIncludingTypingStyle(pos);
}
void InsertParagraphSeparatorCommand::applyStyleAfterInsertion(Node* originalEnclosingBlock)
......@@ -95,14 +92,13 @@ void InsertParagraphSeparatorCommand::applyStyleAfterInsertion(Node* originalEnc
originalEnclosingBlock->hasTagName(h4Tag) ||
originalEnclosingBlock->hasTagName(h5Tag))
return;
if (!m_style)
return;
prepareEditingStyleToApplyAt(m_style.get(), endingSelection().start());
if (m_style->length() > 0)
applyStyle(m_style.get());
m_style->prepareToApplyAt(endingSelection().start());
if (!m_style->isEmpty())
applyStyle(m_style->style());
}
bool InsertParagraphSeparatorCommand::shouldUseDefaultParagraphElement(Node* enclosingBlock) const
......
......@@ -30,6 +30,8 @@
namespace WebCore {
class EditingStyle;
class InsertParagraphSeparatorCommand : public CompositeEditCommand {
public:
static PassRefPtr<InsertParagraphSeparatorCommand> create(Document* document, bool useDefaultParagraphElement = false)
......@@ -46,13 +48,13 @@ private:
void applyStyleAfterInsertion(Node* originalEnclosingBlock);
void getAncestorsInsideBlock(const Node* insertionNode, Element* outerBlock, Vector<Element*>& ancestors);
PassRefPtr<Element> cloneHierarchyUnderNewBlock(const Vector<Element*>& ancestors, PassRefPtr<Element> blockToInsert);
bool shouldUseDefaultParagraphElement(Node*) const;
virtual bool preservesTypingStyle() const;
RefPtr<CSSMutableStyleDeclaration> m_style;
RefPtr<EditingStyle> m_style;
bool m_mustUseDefaultParagraphElement;
};
......
......@@ -28,18 +28,11 @@
#include "RemoveFormatCommand.h"
#include "ApplyStyleCommand.h"
#include "CSSComputedStyleDeclaration.h"
#include "CSSMutableStyleDeclaration.h"
#include "CSSValueKeywords.h"
#include "Editor.h"
#include "EditingStyle.h"
#include "Element.h"
#include "Frame.h"
#include "HTMLElement.h"
#include "HTMLNames.h"
#include "VisibleSelection.h"
#include "SelectionController.h"
#include "TextIterator.h"
#include "TypingCommand.h"
#include "htmlediting.h"
namespace WebCore {
......@@ -92,9 +85,9 @@ void RemoveFormatCommand::doApply()
// Get the default style for this editable root, it's the style that we'll give the
// content that we're operating on.
Node* root = frame->selection()->rootEditableElement();
RefPtr<CSSMutableStyleDeclaration> defaultStyle = ApplyStyleCommand::editingStyleAtPosition(Position(root, 0));
RefPtr<EditingStyle> defaultStyle = EditingStyle::create(root);
applyCommandToComposite(ApplyStyleCommand::create(document(), defaultStyle.get(), isElementForRemoveFormatCommand, editingAction()));
applyCommandToComposite(ApplyStyleCommand::create(document(), defaultStyle->style(), isElementForRemoveFormatCommand, editingAction()));
}
}
......@@ -31,7 +31,6 @@
#include "BreakBlockquoteCommand.h"
#include "CSSComputedStyleDeclaration.h"
#include "CSSMutableStyleDeclaration.h"
#include "CSSProperty.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
#include "Document.h"
......@@ -552,35 +551,36 @@ VisiblePosition ReplaceSelectionCommand::positionAtStartOfInsertedContent()
static bool handleStyleSpansBeforeInsertion(ReplacementFragment& fragment, const Position& insertionPos)
{
Node* topNode = fragment.firstChild();
// Handling the case where we are doing Paste as Quotation or pasting into quoted content is more complicated (see handleStyleSpans)
// and doesn't receive the optimization.
if (isMailPasteAsQuotationNode(topNode) || nearestMailBlockquote(topNode))
return false;
// Either there are no style spans in the fragment or a WebKit client has added content to the fragment
// before inserting it. Look for and handle style spans after insertion.
if (!isStyleSpan(topNode))
return false;
Node* sourceDocumentStyleSpan = topNode;
RefPtr<Node> copiedRangeStyleSpan = sourceDocumentStyleSpan->firstChild();
RefPtr<CSSMutableStyleDeclaration> styleAtInsertionPos = ApplyStyleCommand::editingStyleAtPosition(rangeCompliantEquivalent(insertionPos));
RefPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(rangeCompliantEquivalent(insertionPos));
String styleText = styleAtInsertionPos->style()->cssText();
String styleText = styleAtInsertionPos->cssText();
// FIXME: This string comparison is a naive way of comparing two styles.
// We should be taking the diff and check that the diff is empty.
if (styleText == static_cast<Element*>(sourceDocumentStyleSpan)->getAttribute(styleAttr)) {
fragment.removeNodePreservingChildren(sourceDocumentStyleSpan);
if (!isStyleSpan(copiedRangeStyleSpan.get()))
return true;
}
if (isStyleSpan(copiedRangeStyleSpan.get()) && styleText == static_cast<Element*>(copiedRangeStyleSpan.get())->getAttribute(styleAttr)) {
fragment.removeNodePreservingChildren(copiedRangeStyleSpan.get());
return true;
}
return false;
}
......@@ -615,29 +615,20 @@ void ReplaceSelectionCommand::handleStyleSpans()
// we are here because of a document.execCommand("InsertHTML", ...) call.
if (!sourceDocumentStyleSpan)
return;
RefPtr<CSSMutableStyleDeclaration> sourceDocumentStyle = static_cast<HTMLElement*>(sourceDocumentStyleSpan)->getInlineStyleDecl()->copy();
RefPtr<EditingStyle> sourceDocumentStyle = EditingStyle::create(static_cast<HTMLElement*>(sourceDocumentStyleSpan)->getInlineStyleDecl());
ContainerNode* context = sourceDocumentStyleSpan->parentNode();
// If Mail wraps the fragment with a Paste as Quotation blockquote, or if you're pasting into a quoted region,
// styles from blockquoteNode are allowed to override those from the source document, see <rdar://problem/4930986> and <rdar://problem/5089327>.
Node* blockquoteNode = isMailPasteAsQuotationNode(context) ? context : nearestMailBlockquote(context);
if (blockquoteNode) {
RefPtr<CSSMutableStyleDeclaration> blockquoteStyle = ApplyStyleCommand::editingStyleAtPosition(Position(blockquoteNode, 0));
RefPtr<CSSMutableStyleDeclaration> parentStyle = ApplyStyleCommand::editingStyleAtPosition(Position(blockquoteNode->parentNode(), 0));
parentStyle->diff(blockquoteStyle.get());
CSSMutableStyleDeclaration::const_iterator end = blockquoteStyle->end();
for (CSSMutableStyleDeclaration::const_iterator it = blockquoteStyle->begin(); it != end; ++it) {
const CSSProperty& property = *it;
sourceDocumentStyle->removeProperty(property.id());
}
sourceDocumentStyle->removeStyleConflictingWithStyleOfNode(blockquoteNode);
context = blockquoteNode->parentNode();
}
// This operation requires that only editing styles to be removed from sourceDocumentStyle.
prepareEditingStyleToApplyAt(sourceDocumentStyle.get(), Position(context, 0));
sourceDocumentStyle->prepareToApplyAt(firstPositionInNode(context));
// Remove block properties in the span's style. This prevents properties that probably have no effect
// currently from affecting blocks later if the style is cloned for a new block element during a future
......@@ -645,49 +636,44 @@ void ReplaceSelectionCommand::handleStyleSpans()
// FIXME: They *can* have an effect currently if blocks beneath the style span aren't individually marked
// with block styles by the editing engine used to style them. WebKit doesn't do this, but others might.
sourceDocumentStyle->removeBlockProperties();
// The styles on sourceDocumentStyleSpan are all redundant, and there is no copiedRangeStyleSpan
// to consider. We're finished.
if (sourceDocumentStyle->length() == 0 && !copiedRangeStyleSpan) {
if (sourceDocumentStyle->isEmpty() && !copiedRangeStyleSpan) {
removeNodePreservingChildren(sourceDocumentStyleSpan);
return;
}
// There are non-redundant styles on sourceDocumentStyleSpan, but there is no
// copiedRangeStyleSpan. Remove the span, because it could be surrounding block elements,
// and apply the styles to its children.
if (sourceDocumentStyle->length() > 0 && !copiedRangeStyleSpan) {
copyStyleToChildren(sourceDocumentStyleSpan, sourceDocumentStyle.get());
if (!sourceDocumentStyle->isEmpty() && !copiedRangeStyleSpan) {
copyStyleToChildren(sourceDocumentStyleSpan, sourceDocumentStyle->style());
removeNodePreservingChildren(sourceDocumentStyleSpan);
return;
}
RefPtr<CSSMutableStyleDeclaration> copiedRangeStyle = static_cast<HTMLElement*>(copiedRangeStyleSpan)->getInlineStyleDecl()->copy();
RefPtr<EditingStyle> copiedRangeStyle = EditingStyle::create(static_cast<HTMLElement*>(copiedRangeStyleSpan)->getInlineStyleDecl());
// We're going to put sourceDocumentStyleSpan's non-redundant styles onto copiedRangeStyleSpan,
// as long as they aren't overridden by ones on copiedRangeStyleSpan.
sourceDocumentStyle->merge(copiedRangeStyle.get(), true);
copiedRangeStyle = sourceDocumentStyle;
copiedRangeStyle->style()->merge(sourceDocumentStyle->style(), false);
removeNodePreservingChildren(sourceDocumentStyleSpan);
// Remove redundant styles.
context = copiedRangeStyleSpan->parentNode();
prepareEditingStyleToApplyAt(copiedRangeStyle.get(), Position(context, 0));
// See the comments above about removing block properties.
copiedRangeStyle->prepareToApplyAt(firstPositionInNode(context));
copiedRangeStyle->removeBlockProperties();
// All the styles on copiedRangeStyleSpan are redundant, remove it.
if (copiedRangeStyle->length() == 0) {
if (copiedRangeStyle->isEmpty()) {
removeNodePreservingChildren(copiedRangeStyleSpan);
return;
}
// Clear the redundant styles from the span's style attribute.
// FIXME: If font-family:-webkit-monospace is non-redundant, then the font-size should stay, even if it
// appears redundant.
setNodeAttribute(static_cast<Element*>(copiedRangeStyleSpan), styleAttr, copiedRangeStyle->cssText());
setNodeAttribute(static_cast<Element*>(copiedRangeStyleSpan), styleAttr, copiedRangeStyle->style()->cssText());
}
// Take the style attribute of a span and apply it to it's children instead. This allows us to
......@@ -805,8 +791,8 @@ void ReplaceSelectionCommand::doApply()
m_matchStyle = false;