summaryrefslogtreecommitdiffstats
path: root/WebCore/editing/ReplaceSelectionCommand.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:23:55 +0100
committerSteve Block <steveblock@google.com>2010-04-27 17:07:03 +0100
commit692e5dbf12901edacf14812a6fae25462920af42 (patch)
treed62802373a429e0a9dc093b6046c166b2c514285 /WebCore/editing/ReplaceSelectionCommand.cpp
parente24bea4efef1c414137d36a9778aa4e142e10c7d (diff)
downloadexternal_webkit-692e5dbf12901edacf14812a6fae25462920af42.zip
external_webkit-692e5dbf12901edacf14812a6fae25462920af42.tar.gz
external_webkit-692e5dbf12901edacf14812a6fae25462920af42.tar.bz2
Merge webkit.org at r55033 : Initial merge by git
Change-Id: I98a4af828067cc243ec3dc5e5826154dd88074b5
Diffstat (limited to 'WebCore/editing/ReplaceSelectionCommand.cpp')
-rw-r--r--WebCore/editing/ReplaceSelectionCommand.cpp57
1 files changed, 49 insertions, 8 deletions
diff --git a/WebCore/editing/ReplaceSelectionCommand.cpp b/WebCore/editing/ReplaceSelectionCommand.cpp
index f26757e..bac090c 100644
--- a/WebCore/editing/ReplaceSelectionCommand.cpp
+++ b/WebCore/editing/ReplaceSelectionCommand.cpp
@@ -468,6 +468,17 @@ void ReplaceSelectionCommand::negateStyleRulesThatAffectAppearance()
e->getInlineStyleDecl()->setProperty(CSSPropertyDisplay, CSSValueInline);
if (e->renderer() && e->renderer()->style()->floating() != FNONE)
e->getInlineStyleDecl()->setProperty(CSSPropertyFloat, CSSValueNone);
+
+ // Undo the effects of page zoom if we have an absolute font size. When we copy, we
+ // compute the new font size as an absolute size so pasting will cause the zoom to be
+ // applied twice.
+ if (e->renderer() && e->renderer()->style() && e->renderer()->style()->effectiveZoom() != 1.0
+ && e->renderer()->style()->fontDescription().isAbsoluteSize()) {
+ float newSize = e->renderer()->style()->fontDescription().specifiedSize() / e->renderer()->style()->effectiveZoom();
+ ExceptionCode ec = 0;
+ e->style()->setProperty(CSSPropertyFontSize, String::number(newSize), false, ec);
+ ASSERT(!ec);
+ }
}
if (node == m_lastLeafInserted)
break;
@@ -638,10 +649,11 @@ void ReplaceSelectionCommand::handleStyleSpans()
}
// There are non-redundant styles on sourceDocumentStyleSpan, but there is no
- // copiedRangeStyleSpan. Clear the redundant styles from sourceDocumentStyleSpan
- // and return.
+ // copiedRangeStyleSpan. Remove the span, because it could be surrounding block elements,
+ // and apply the styles to its children.
if (sourceDocumentStyle->length() > 0 && !copiedRangeStyleSpan) {
- setNodeAttribute(static_cast<Element*>(sourceDocumentStyleSpan), styleAttr, sourceDocumentStyle->cssText());
+ copyStyleToChildren(sourceDocumentStyleSpan, sourceDocumentStyle.get());
+ removeNodePreservingChildren(sourceDocumentStyleSpan);
return;
}
@@ -673,6 +685,34 @@ void ReplaceSelectionCommand::handleStyleSpans()
setNodeAttribute(static_cast<Element*>(copiedRangeStyleSpan), styleAttr, copiedRangeStyle->cssText());
}
+// Take the style attribute of a span and apply it to it's children instead. This allows us to
+// convert invalid HTML where a span contains block elements into valid HTML while preserving
+// styles.
+void ReplaceSelectionCommand::copyStyleToChildren(Node* parentNode, const CSSMutableStyleDeclaration* parentStyle)
+{
+ ASSERT(parentNode->hasTagName(spanTag));
+ for (Node* childNode = parentNode->firstChild(); childNode; childNode = childNode->nextSibling()) {
+ if (childNode->isTextNode() || !isBlock(childNode) || childNode->hasTagName(preTag)) {
+ // In this case, put a span tag around the child node.
+ RefPtr<Node> newSpan = parentNode->cloneNode(false);
+ setNodeAttribute(static_cast<Element*>(newSpan.get()), styleAttr, parentStyle->cssText());
+ insertNodeAfter(newSpan, childNode);
+ ExceptionCode ec = 0;
+ newSpan->appendChild(childNode, ec);
+ ASSERT(!ec);
+ childNode = newSpan.get();
+ } else if (childNode->isHTMLElement()) {
+ // Copy the style attribute and merge them into the child node. We don't want to override
+ // existing styles, so don't clobber on merge.
+ RefPtr<CSSMutableStyleDeclaration> newStyle = parentStyle->copy();
+ HTMLElement* childElement = static_cast<HTMLElement*>(childNode);
+ RefPtr<CSSMutableStyleDeclaration> existingStyles = childElement->getInlineStyleDecl()->copy();
+ existingStyles->merge(newStyle.get(), false);
+ setNodeAttribute(childElement, styleAttr, existingStyles->cssText());
+ }
+ }
+}
+
void ReplaceSelectionCommand::mergeEndIfNeeded()
{
if (!m_shouldMergeEnd)
@@ -871,7 +911,8 @@ void ReplaceSelectionCommand::doApply()
fragment.removeNode(refNode);
Node* blockStart = enclosingBlock(insertionPos.node());
- if (isListElement(refNode.get()) && blockStart->renderer()->isListItem())
+ if ((isListElement(refNode.get()) || (isStyleSpan(refNode.get()) && isListElement(refNode->firstChild())))
+ && blockStart->renderer()->isListItem())
refNode = insertAsListItems(refNode, blockStart, insertionPos);
else
insertNodeAtAndUpdateNodesInserted(refNode, insertionPos);
@@ -1122,15 +1163,15 @@ void ReplaceSelectionCommand::insertNodeBeforeAndUpdateNodesInserted(PassRefPtr<
// If the user is inserting a list into an existing list, instead of nesting the list,
// we put the list items into the existing list.
-Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtr<Node> listElement, Node* insertionNode, const Position& p)
+Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtr<Node> listElement, Node* insertionBlock, const Position& insertPos)
{
while (listElement->hasChildNodes() && isListElement(listElement->firstChild()) && listElement->childNodeCount() == 1)
listElement = listElement->firstChild();
- bool isStart = isStartOfParagraph(p);
- bool isEnd = isEndOfParagraph(p);
+ bool isStart = isStartOfParagraph(insertPos);
+ bool isEnd = isEndOfParagraph(insertPos);
- Node* lastNode = insertionNode;
+ Node* lastNode = insertionBlock;
while (RefPtr<Node> listItem = listElement->firstChild()) {
ExceptionCode ec = 0;
listElement->removeChild(listItem.get(), ec);