summaryrefslogtreecommitdiffstats
path: root/WebCore/editing/ApplyStyleCommand.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-08-04 11:41:34 +0100
committerSteve Block <steveblock@google.com>2010-08-09 12:04:44 +0100
commitdb14019a23d96bc8a444b6576a5da8bd1cfbc8b0 (patch)
tree9f793c5b0f5e1f2aca8247158920e2c4bf962bbf /WebCore/editing/ApplyStyleCommand.cpp
parentbf916837aa84f1e4b00e6ed6268516c2acd27545 (diff)
downloadexternal_webkit-db14019a23d96bc8a444b6576a5da8bd1cfbc8b0.zip
external_webkit-db14019a23d96bc8a444b6576a5da8bd1cfbc8b0.tar.gz
external_webkit-db14019a23d96bc8a444b6576a5da8bd1cfbc8b0.tar.bz2
Merge WebKit at r64523 : Initial merge by git.
Change-Id: Ibb796c6802e757b1d9b40f58205cfbe4da95fcd4
Diffstat (limited to 'WebCore/editing/ApplyStyleCommand.cpp')
-rw-r--r--WebCore/editing/ApplyStyleCommand.cpp131
1 files changed, 90 insertions, 41 deletions
diff --git a/WebCore/editing/ApplyStyleCommand.cpp b/WebCore/editing/ApplyStyleCommand.cpp
index 8847714..d865468 100644
--- a/WebCore/editing/ApplyStyleCommand.cpp
+++ b/WebCore/editing/ApplyStyleCommand.cpp
@@ -910,7 +910,10 @@ void ApplyStyleCommand::applyInlineStyle(CSSMutableStyleDeclaration *style)
// split the start node and containing element if the selection starts inside of it
bool splitStart = isValidCaretPositionInTextNode(start);
if (splitStart) {
- splitTextElementAtStart(start, end);
+ if (shouldSplitTextElement(start.node()->parentElement(), style))
+ splitTextElementAtStart(start, end);
+ else
+ splitTextAtStart(start, end);
start = startPosition();
end = endPosition();
startDummySpanAncestor = dummySpanAncestorForNode(start.node());
@@ -919,7 +922,10 @@ void ApplyStyleCommand::applyInlineStyle(CSSMutableStyleDeclaration *style)
// split the end node and containing element if the selection ends inside of it
bool splitEnd = isValidCaretPositionInTextNode(end);
if (splitEnd) {
- splitTextElementAtEnd(start, end);
+ if (shouldSplitTextElement(end.node()->parentElement(), style))
+ splitTextElementAtEnd(start, end);
+ else
+ splitTextAtEnd(start, end);
start = startPosition();
end = endPosition();
endDummySpanAncestor = dummySpanAncestorForNode(end.node());
@@ -1176,6 +1182,40 @@ bool ApplyStyleCommand::implicitlyStyledElementShouldBeRemovedWhenApplyingStyle(
return false;
}
+bool ApplyStyleCommand::removeInlineStyleFromElement(CSSMutableStyleDeclaration* style, HTMLElement* element, InlineStyleRemovalMode mode)
+{
+ ASSERT(style);
+ ASSERT(element);
+
+ bool removed = false;
+
+ if (m_styledInlineElement && element->hasTagName(m_styledInlineElement->tagQName())) {
+ removed = true;
+ if (mode == RemoveAttributesAndElements)
+ removeNodePreservingChildren(element);
+ }
+
+ if (implicitlyStyledElementShouldBeRemovedWhenApplyingStyle(element, style)) {
+ removed = true;
+ if (mode == RemoveAttributesAndElements)
+ replaceWithSpanOrRemoveIfWithoutAttributes(element);
+ }
+
+ if (!element->inDocument())
+ return removed;
+
+ // If the node was converted to a span, the span may still contain relevant
+ // styles which must be removed (e.g. <b style='font-weight: bold'>)
+ if (removeHTMLFontStyle(style, element, mode))
+ removed = true;
+ if (removeHTMLBidiEmbeddingStyle(style, element, mode))
+ removed = true;
+ if (removeCSSStyle(style, element, mode))
+ removed = true;
+
+ return removed;
+}
+
void ApplyStyleCommand::replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement*& elem)
{
bool removeNode = false;
@@ -1200,65 +1240,84 @@ void ApplyStyleCommand::replaceWithSpanOrRemoveIfWithoutAttributes(HTMLElement*&
}
}
-void ApplyStyleCommand::removeHTMLFontStyle(CSSMutableStyleDeclaration *style, HTMLElement *elem)
+bool ApplyStyleCommand::removeHTMLFontStyle(CSSMutableStyleDeclaration* style, HTMLElement* elem, InlineStyleRemovalMode mode)
{
ASSERT(style);
ASSERT(elem);
if (!elem->hasLocalName(fontTag))
- return;
-
+ return false;
+
+ bool removed = false;
CSSMutableStyleDeclaration::const_iterator end = style->end();
for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) {
+ const QualifiedName* attrToRemove = 0;
switch ((*it).id()) {
- case CSSPropertyColor:
- removeNodeAttribute(elem, colorAttr);
- break;
- case CSSPropertyFontFamily:
- removeNodeAttribute(elem, faceAttr);
- break;
- case CSSPropertyFontSize:
- removeNodeAttribute(elem, sizeAttr);
- break;
+ case CSSPropertyColor:
+ attrToRemove = &colorAttr;
+ break;
+ case CSSPropertyFontFamily:
+ attrToRemove = &faceAttr;
+ break;
+ case CSSPropertyFontSize:
+ attrToRemove = &sizeAttr;
+ break;
+ }
+
+ if (attrToRemove) {
+ removed = true;
+ if (mode == RemoveAttributesAndElements)
+ removeNodeAttribute(elem, *attrToRemove);
}
}
- if (isEmptyFontTag(elem))
+ if (isEmptyFontTag(elem) && mode == RemoveAttributesAndElements)
removeNodePreservingChildren(elem);
+
+ return removed;
}
-void ApplyStyleCommand::removeHTMLBidiEmbeddingStyle(CSSMutableStyleDeclaration *style, HTMLElement *elem)
+bool ApplyStyleCommand::removeHTMLBidiEmbeddingStyle(CSSMutableStyleDeclaration* style, HTMLElement* elem, InlineStyleRemovalMode mode)
{
ASSERT(style);
ASSERT(elem);
if (!elem->hasAttribute(dirAttr))
- return;
+ return false;
if (!style->getPropertyCSSValue(CSSPropertyUnicodeBidi) && !style->getPropertyCSSValue(CSSPropertyDirection))
- return;
+ return false;
+
+ if (mode == RemoveNone)
+ return true;
removeNodeAttribute(elem, dirAttr);
// FIXME: should this be isSpanWithoutAttributesOrUnstyleStyleSpan? Need a test.
if (isUnstyledStyleSpan(elem))
removeNodePreservingChildren(elem);
+
+ return true;
}
-void ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration* style, HTMLElement* elem)
+bool ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration* style, HTMLElement* elem, InlineStyleRemovalMode mode)
{
ASSERT(style);
ASSERT(elem);
CSSMutableStyleDeclaration* decl = elem->inlineStyleDecl();
if (!decl)
- return;
+ return false;
+ bool removed = false;
CSSMutableStyleDeclaration::const_iterator end = style->end();
for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) {
CSSPropertyID propertyID = static_cast<CSSPropertyID>((*it).id());
RefPtr<CSSValue> value = decl->getPropertyCSSValue(propertyID);
if (value && (propertyID != CSSPropertyWhiteSpace || !isTabSpanNode(elem))) {
+ removed = true;
+ if (mode == RemoveNone)
+ return true;
removeCSSProperty(decl, propertyID);
if (propertyID == CSSPropertyUnicodeBidi && !decl->getPropertyValue(CSSPropertyDirection).isEmpty())
removeCSSProperty(decl, CSSPropertyDirection);
@@ -1271,6 +1330,8 @@ void ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration* style, HTMLEl
if (isSpanWithoutAttributesOrUnstyleStyleSpan(elem))
removeNodePreservingChildren(elem);
+
+ return removed;
}
static bool hasTextDecorationProperty(Node *node)
@@ -1472,19 +1533,7 @@ void ApplyStyleCommand::removeInlineStyle(PassRefPtr<CSSMutableStyleDeclaration>
HTMLElement* elem = static_cast<HTMLElement*>(node);
Node* prev = elem->traversePreviousNodePostOrder();
Node* next = elem->traverseNextNode();
- if (m_styledInlineElement && elem->hasTagName(m_styledInlineElement->tagQName()))
- removeNodePreservingChildren(elem);
-
- if (implicitlyStyledElementShouldBeRemovedWhenApplyingStyle(elem, style.get()))
- replaceWithSpanOrRemoveIfWithoutAttributes(elem);
-
- // If the node was converted to a span, the span may still contain relevant
- // styles which must be removed (e.g. <b style='font-weight: bold'>)
- if (elem->inDocument()) {
- removeHTMLFontStyle(style.get(), elem);
- removeHTMLBidiEmbeddingStyle(style.get(), elem);
- removeCSSStyle(style.get(), elem);
- }
+ removeInlineStyleFromElement(style.get(), elem);
if (!elem->inDocument()) {
if (s.node() == elem) {
// Since elem must have been fully selected, and it is at the start
@@ -1554,10 +1603,6 @@ void ApplyStyleCommand::splitTextAtEnd(const Position& start, const Position& en
void ApplyStyleCommand::splitTextElementAtStart(const Position& start, const Position& end)
{
- Node* parent = start.node()->parentNode();
- if (!parent || !parent->parentElement() || !parent->parentElement()->isContentEditable())
- return splitTextAtStart(start, end);
-
int endOffsetAdjustment = start.node() == end.node() ? start.deprecatedEditingOffset() : 0;
Text* text = static_cast<Text*>(start.node());
splitTextNodeContainingElement(text, start.deprecatedEditingOffset());
@@ -1566,10 +1611,6 @@ void ApplyStyleCommand::splitTextElementAtStart(const Position& start, const Pos
void ApplyStyleCommand::splitTextElementAtEnd(const Position& start, const Position& end)
{
- Node* parent = end.node()->parentNode();
- if (!parent || !parent->parentElement() || !parent->parentElement()->isContentEditable())
- return splitTextAtEnd(start, end);
-
Text* text = static_cast<Text*>(end.node());
splitTextNodeContainingElement(text, end.deprecatedEditingOffset());
@@ -1580,6 +1621,14 @@ void ApplyStyleCommand::splitTextElementAtEnd(const Position& start, const Posit
updateStartEnd(Position(startNode, start.deprecatedEditingOffset()), Position(prevNode->parent(), prevNode->nodeIndex() + 1));
}
+bool ApplyStyleCommand::shouldSplitTextElement(Element* element, CSSMutableStyleDeclaration* style)
+{
+ if (!element || !element->isHTMLElement() || !element->parentElement() || !element->parentElement()->isContentEditable())
+ return false;
+
+ return shouldRemoveInlineStyleFromElement(style, static_cast<HTMLElement*>(element));
+}
+
bool ApplyStyleCommand::isValidCaretPositionInTextNode(const Position& position)
{
Node* node = position.node();