diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
commit | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch) | |
tree | b34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/WebCore/editing | |
parent | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff) | |
download | qtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz |
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/WebCore/editing')
27 files changed, 306 insertions, 287 deletions
diff --git a/Source/WebCore/editing/ApplyBlockElementCommand.cpp b/Source/WebCore/editing/ApplyBlockElementCommand.cpp index 45fcf27e1..b32641be7 100644 --- a/Source/WebCore/editing/ApplyBlockElementCommand.cpp +++ b/Source/WebCore/editing/ApplyBlockElementCommand.cpp @@ -80,10 +80,10 @@ void ApplyBlockElementCommand::doApply() VisiblePosition endOfSelection = selection.visibleEnd(); ASSERT(!startOfSelection.isNull()); ASSERT(!endOfSelection.isNull()); - Element* startScope = 0; - int startIndex = indexForVisiblePosition(startOfSelection, &startScope); - Element* endScope = 0; - int endIndex = indexForVisiblePosition(endOfSelection, &endScope); + RefPtr<Element> startScope; + int startIndex = indexForVisiblePosition(startOfSelection, startScope); + RefPtr<Element> endScope; + int endIndex = indexForVisiblePosition(endOfSelection, endScope); formatSelection(startOfSelection, endOfSelection); @@ -93,8 +93,8 @@ void ApplyBlockElementCommand::doApply() ASSERT(startIndex >= 0); ASSERT(startIndex <= endIndex); if (startScope == endScope && startIndex >= 0 && startIndex <= endIndex) { - VisiblePosition start(visiblePositionForIndex(startIndex, startScope)); - VisiblePosition end(visiblePositionForIndex(endIndex, endScope)); + VisiblePosition start(visiblePositionForIndex(startIndex, startScope.get())); + VisiblePosition end(visiblePositionForIndex(endIndex, endScope.get())); if (start.isNotNull() && end.isNotNull()) setEndingSelection(VisibleSelection(start, end, endingSelection().isDirectional())); } @@ -162,7 +162,7 @@ static bool isNewLineAtPosition(const Position& position) return false; ExceptionCode ec = 0; - String textAtPosition = static_cast<Text*>(textNode)->substringData(offset, 1, ec); + String textAtPosition = toText(textNode)->substringData(offset, 1, ec); if (ec) return false; @@ -257,18 +257,18 @@ VisiblePosition ApplyBlockElementCommand::endOfNextParagrahSplittingTextNodesIfN if (text == start.containerNode() && text->previousSibling() && text->previousSibling()->isTextNode()) { ASSERT(start.offsetInContainerNode() < position.offsetInContainerNode()); - start = Position(static_cast<Text*>(text->previousSibling()), start.offsetInContainerNode()); + start = Position(toText(text->previousSibling()), start.offsetInContainerNode()); } if (text == end.containerNode() && text->previousSibling() && text->previousSibling()->isTextNode()) { ASSERT(end.offsetInContainerNode() < position.offsetInContainerNode()); - end = Position(static_cast<Text*>(text->previousSibling()), end.offsetInContainerNode()); + end = Position(toText(text->previousSibling()), end.offsetInContainerNode()); } if (text == m_endOfLastParagraph.containerNode()) { if (m_endOfLastParagraph.offsetInContainerNode() < position.offsetInContainerNode()) { // We can only fix endOfLastParagraph if the previous node was still text and hasn't been modified by script. if (text->previousSibling()->isTextNode() - && static_cast<unsigned>(m_endOfLastParagraph.offsetInContainerNode()) <= static_cast<Text*>(text->previousSibling())->length()) - m_endOfLastParagraph = Position(static_cast<Text*>(text->previousSibling()), m_endOfLastParagraph.offsetInContainerNode()); + && static_cast<unsigned>(m_endOfLastParagraph.offsetInContainerNode()) <= toText(text->previousSibling())->length()) + m_endOfLastParagraph = Position(toText(text->previousSibling()), m_endOfLastParagraph.offsetInContainerNode()); } else m_endOfLastParagraph = Position(text.get(), m_endOfLastParagraph.offsetInContainerNode() - 1); } diff --git a/Source/WebCore/editing/ApplyStyleCommand.cpp b/Source/WebCore/editing/ApplyStyleCommand.cpp index 1adde10cf..25444bb7d 100644 --- a/Source/WebCore/editing/ApplyStyleCommand.cpp +++ b/Source/WebCore/editing/ApplyStyleCommand.cpp @@ -387,7 +387,7 @@ void ApplyStyleCommand::applyRelativeFontStyleChange(EditingStyle* style) float desiredFontSize = max(MinimumFontSize, startingFontSizes.get(node) + style->fontSizeDelta()); RefPtr<CSSValue> value = inlineStyleDecl->getPropertyCSSValue(CSSPropertyFontSize); if (value) { - inlineStyleDecl->removeProperty(CSSPropertyFontSize); + element->removeInlineStyleProperty(CSSPropertyFontSize); currentFontSize = computedFontSize(node); } if (currentFontSize != desiredFontSize) { @@ -444,7 +444,7 @@ HTMLElement* ApplyStyleCommand::splitAncestorsWithUnicodeBidi(Node* node, bool b Node* nextHighestAncestorWithUnicodeBidi = 0; int highestAncestorUnicodeBidi = 0; for (Node* n = node->parentNode(); n != block; n = n->parentNode()) { - int unicodeBidi = getIdentifierValue(computedStyle(n).get(), CSSPropertyUnicodeBidi); + int unicodeBidi = getIdentifierValue(CSSComputedStyleDeclaration::create(n).get(), CSSPropertyUnicodeBidi); if (unicodeBidi && unicodeBidi != CSSValueNormal) { highestAncestorUnicodeBidi = unicodeBidi; nextHighestAncestorWithUnicodeBidi = highestAncestorWithUnicodeBidi; @@ -496,7 +496,7 @@ void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, Node* unsp continue; StyledElement* element = static_cast<StyledElement*>(n); - int unicodeBidi = getIdentifierValue(computedStyle(element).get(), CSSPropertyUnicodeBidi); + int unicodeBidi = getIdentifierValue(CSSComputedStyleDeclaration::create(element).get(), CSSPropertyUnicodeBidi); if (!unicodeBidi || unicodeBidi == CSSValueNormal) continue; @@ -522,7 +522,7 @@ void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, Node* unsp static Node* highestEmbeddingAncestor(Node* startNode, Node* enclosingNode) { for (Node* n = startNode; n && n != enclosingNode; n = n->parentNode()) { - if (n->isHTMLElement() && getIdentifierValue(computedStyle(n).get(), CSSPropertyUnicodeBidi) == CSSValueEmbed) + if (n->isHTMLElement() && getIdentifierValue(CSSComputedStyleDeclaration::create(n).get(), CSSPropertyUnicodeBidi) == CSSValueEmbed) return n; } @@ -1123,14 +1123,14 @@ void ApplyStyleCommand::splitTextAtEnd(const Position& start, const Position& en ASSERT(end.containerNode()->isTextNode()); bool shouldUpdateStart = start.anchorType() == Position::PositionIsOffsetInAnchor && start.containerNode() == end.containerNode(); - Text* text = static_cast<Text *>(end.deprecatedNode()); + Text* text = toText(end.deprecatedNode()); splitTextNode(text, end.offsetInContainerNode()); Node* prevNode = text->previousSibling(); if (!prevNode || !prevNode->isTextNode()) return; - Position newStart = shouldUpdateStart ? Position(static_cast<Text*>(prevNode), start.offsetInContainerNode()) : start; + Position newStart = shouldUpdateStart ? Position(toText(prevNode), start.offsetInContainerNode()) : start; updateStartEnd(newStart, lastPositionInNode(prevNode)); } @@ -1162,7 +1162,7 @@ void ApplyStyleCommand::splitTextElementAtEnd(const Position& start, const Posit if (!firstTextNode || !firstTextNode->isTextNode()) return; - Position newStart = shouldUpdateStart ? Position(static_cast<Text*>(firstTextNode), start.offsetInContainerNode()) : start; + Position newStart = shouldUpdateStart ? Position(toText(firstTextNode), start.offsetInContainerNode()) : start; updateStartEnd(newStart, positionAfterNode(firstTextNode)); } @@ -1410,7 +1410,7 @@ float ApplyStyleCommand::computedFontSize(Node* node) if (!node) return 0; - RefPtr<CSSComputedStyleDeclaration> style = computedStyle(node); + RefPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration::create(node); if (!style) return 0; @@ -1433,8 +1433,8 @@ void ApplyStyleCommand::joinChildTextNodes(Node* node, const Position& start, co while (child) { Node* next = child->nextSibling(); if (child->isTextNode() && next && next->isTextNode()) { - Text* childText = static_cast<Text *>(child); - Text* nextText = static_cast<Text *>(next); + Text* childText = toText(child); + Text* nextText = toText(next); if (start.anchorType() == Position::PositionIsOffsetInAnchor && next == start.containerNode()) newStart = Position(childText, childText->length() + start.offsetInContainerNode()); if (end.anchorType() == Position::PositionIsOffsetInAnchor && next == end.containerNode()) diff --git a/Source/WebCore/editing/BreakBlockquoteCommand.cpp b/Source/WebCore/editing/BreakBlockquoteCommand.cpp index 76e9159ac..d3639398a 100644 --- a/Source/WebCore/editing/BreakBlockquoteCommand.cpp +++ b/Source/WebCore/editing/BreakBlockquoteCommand.cpp @@ -107,7 +107,7 @@ void BreakBlockquoteCommand::doApply() // Split at pos if in the middle of a text node. if (startNode->isTextNode()) { - Text* textNode = static_cast<Text*>(startNode); + Text* textNode = toText(startNode); if ((unsigned)pos.deprecatedEditingOffset() >= textNode->length()) { startNode = startNode->traverseNextNode(); ASSERT(startNode); diff --git a/Source/WebCore/editing/CompositeEditCommand.cpp b/Source/WebCore/editing/CompositeEditCommand.cpp index 2a629c3a0..f57657137 100644 --- a/Source/WebCore/editing/CompositeEditCommand.cpp +++ b/Source/WebCore/editing/CompositeEditCommand.cpp @@ -356,7 +356,7 @@ void CompositeEditCommand::insertNodeAt(PassRefPtr<Node> insertChild, const Posi } else if (caretMinOffset(refChild) >= offset) insertNodeBefore(insertChild, refChild); else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) { - splitTextNode(static_cast<Text *>(refChild), offset); + splitTextNode(toText(refChild), offset); // Mutation events (bug 22634) from the text node insertion may have removed the refChild if (!refChild->inDocument()) @@ -532,7 +532,7 @@ Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode())) return positionInParentAfterNode(tabSpan); - splitTextNodeContainingElement(static_cast<Text *>(pos.containerNode()), pos.offsetInContainerNode()); + splitTextNodeContainingElement(toText(pos.containerNode()), pos.offsetInContainerNode()); return positionInParentBeforeNode(tabSpan); } @@ -590,7 +590,7 @@ bool CompositeEditCommand::canRebalance(const Position& position) const if (position.anchorType() != Position::PositionIsOffsetInAnchor || !node || !node->isTextNode()) return false; - Text* textNode = static_cast<Text*>(node); + Text* textNode = toText(node); if (textNode->length() == 0) return false; @@ -610,14 +610,14 @@ void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position) // If the rebalance is for the single offset, and neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing. int offset = position.deprecatedEditingOffset(); - String text = static_cast<Text*>(node)->data(); + String text = toText(node)->data(); if (!isWhitespace(text[offset])) { offset--; if (offset < 0 || !isWhitespace(text[offset])) return; } - rebalanceWhitespaceOnTextSubstring(static_cast<Text*>(node), position.offsetInContainerNode(), position.offsetInContainerNode()); + rebalanceWhitespaceOnTextSubstring(toText(node), position.offsetInContainerNode(), position.offsetInContainerNode()); } void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(PassRefPtr<Text> prpTextNode, int startOffset, int endOffset) @@ -659,7 +659,7 @@ void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& positio Node* node = position.deprecatedNode(); if (!node || !node->isTextNode()) return; - Text* textNode = static_cast<Text*>(node); + Text* textNode = toText(node); if (textNode->length() == 0) return; @@ -677,9 +677,9 @@ void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& positio Position previous(previousVisiblePos.deepEquivalent()); if (isCollapsibleWhitespace(previousVisiblePos.characterAfter()) && previous.deprecatedNode()->isTextNode() && !previous.deprecatedNode()->hasTagName(brTag)) - replaceTextInNodePreservingMarkers(static_cast<Text*>(previous.deprecatedNode()), previous.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); + replaceTextInNodePreservingMarkers(toText(previous.deprecatedNode()), previous.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); if (isCollapsibleWhitespace(visiblePos.characterAfter()) && position.deprecatedNode()->isTextNode() && !position.deprecatedNode()->hasTagName(brTag)) - replaceTextInNodePreservingMarkers(static_cast<Text*>(position.deprecatedNode()), position.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); + replaceTextInNodePreservingMarkers(toText(position.deprecatedNode()), position.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); } void CompositeEditCommand::rebalanceWhitespace() @@ -698,6 +698,8 @@ void CompositeEditCommand::deleteInsignificantText(PassRefPtr<Text> textNode, un if (!textNode || start >= end) return; + document()->updateLayout(); + RenderText* textRenderer = toRenderText(textNode->renderer()); if (!textRenderer) return; @@ -780,18 +782,20 @@ void CompositeEditCommand::deleteInsignificantText(const Position& start, const if (comparePositions(start, end) >= 0) return; - Node* next; - for (Node* node = start.deprecatedNode(); node; node = next) { - next = node->traverseNextNode(); - if (node->isTextNode()) { - Text* textNode = static_cast<Text*>(node); - int startOffset = node == start.deprecatedNode() ? start.deprecatedEditingOffset() : 0; - int endOffset = node == end.deprecatedNode() ? end.deprecatedEditingOffset() : static_cast<int>(textNode->length()); - deleteInsignificantText(textNode, startOffset, endOffset); - } + Vector<RefPtr<Text> > nodes; + for (Node* node = start.deprecatedNode(); node; node = node->traverseNextNode()) { + if (node->isTextNode()) + nodes.append(toText(node)); if (node == end.deprecatedNode()) break; } + + for (size_t i = 0; i < nodes.size(); ++i) { + Text* textNode = nodes[i].get(); + int startOffset = textNode == start.deprecatedNode() ? start.deprecatedEditingOffset() : 0; + int endOffset = textNode == end.deprecatedNode() ? end.deprecatedEditingOffset() : static_cast<int>(textNode->length()); + deleteInsignificantText(textNode, startOffset, endOffset); + } } void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos) @@ -857,7 +861,7 @@ void CompositeEditCommand::removePlaceholderAt(const Position& p) return; } - deleteTextFromNode(static_cast<Text*>(p.anchorNode()), p.offsetInContainerNode(), 1); + deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); } PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position) @@ -1033,7 +1037,7 @@ void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination) else if (lineBreakExistsAtPosition(position)) { // There is a preserved '\n' at caretAfterDelete. // We can safely assume this is a text node. - Text* textNode = static_cast<Text*>(node); + Text* textNode = toText(node); if (textNode->length() == 1) removeNodeAndPruneAncestors(node); else @@ -1326,7 +1330,7 @@ bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph() removeNodeAndPruneAncestors(caretPos.deprecatedNode()); else if (caretPos.deprecatedNode()->isTextNode()) { ASSERT(caretPos.deprecatedEditingOffset() == 0); - Text* textNode = static_cast<Text*>(caretPos.deprecatedNode()); + Text* textNode = toText(caretPos.deprecatedNode()); ContainerNode* parentNode = textNode->parentNode(); // The preserved newline must be the first thing in the node, since otherwise the previous // paragraph would be quoted, and we verified that it wasn't above. diff --git a/Source/WebCore/editing/DeleteButtonController.cpp b/Source/WebCore/editing/DeleteButtonController.cpp index 2a3005ea6..e8b05eca5 100644 --- a/Source/WebCore/editing/DeleteButtonController.cpp +++ b/Source/WebCore/editing/DeleteButtonController.cpp @@ -205,17 +205,16 @@ void DeleteButtonController::createDeletionUI() RefPtr<HTMLDivElement> container = HTMLDivElement::create(m_target->document()); container->setIdAttribute(containerElementIdentifier); - StylePropertySet* style = container->ensureInlineStyleDecl(); - style->setProperty(CSSPropertyWebkitUserDrag, CSSValueNone); - style->setProperty(CSSPropertyWebkitUserSelect, CSSValueNone); - style->setProperty(CSSPropertyWebkitUserModify, CSSValueReadOnly); - style->setProperty(CSSPropertyVisibility, CSSValueHidden); - style->setProperty(CSSPropertyPosition, CSSValueAbsolute); - style->setProperty(CSSPropertyCursor, CSSValueDefault); - style->setProperty(CSSPropertyTop, "0"); - style->setProperty(CSSPropertyRight, "0"); - style->setProperty(CSSPropertyBottom, "0"); - style->setProperty(CSSPropertyLeft, "0"); + container->setInlineStyleProperty(CSSPropertyWebkitUserDrag, CSSValueNone); + container->setInlineStyleProperty(CSSPropertyWebkitUserSelect, CSSValueNone); + container->setInlineStyleProperty(CSSPropertyWebkitUserModify, CSSValueReadOnly); + container->setInlineStyleProperty(CSSPropertyVisibility, CSSValueHidden); + container->setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); + container->setInlineStyleProperty(CSSPropertyCursor, CSSValueDefault); + container->setInlineStyleProperty(CSSPropertyTop, "0"); + container->setInlineStyleProperty(CSSPropertyRight, "0"); + container->setInlineStyleProperty(CSSPropertyBottom, "0"); + container->setInlineStyleProperty(CSSPropertyLeft, "0"); RefPtr<HTMLDivElement> outline = HTMLDivElement::create(m_target->document()); outline->setIdAttribute(outlineElementIdentifier); @@ -223,16 +222,15 @@ void DeleteButtonController::createDeletionUI() const int borderWidth = 4; const int borderRadius = 6; - style = outline->ensureInlineStyleDecl(); - style->setProperty(CSSPropertyPosition, CSSValueAbsolute); - style->setProperty(CSSPropertyZIndex, String::number(-1000000)); - style->setProperty(CSSPropertyTop, String::number(-borderWidth - m_target->renderBox()->borderTop()) + "px"); - style->setProperty(CSSPropertyRight, String::number(-borderWidth - m_target->renderBox()->borderRight()) + "px"); - style->setProperty(CSSPropertyBottom, String::number(-borderWidth - m_target->renderBox()->borderBottom()) + "px"); - style->setProperty(CSSPropertyLeft, String::number(-borderWidth - m_target->renderBox()->borderLeft()) + "px"); - style->setProperty(CSSPropertyBorder, String::number(borderWidth) + "px solid rgba(0, 0, 0, 0.6)"); - style->setProperty(CSSPropertyWebkitBorderRadius, String::number(borderRadius) + "px"); - style->setProperty(CSSPropertyVisibility, CSSValueVisible); + outline->setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); + outline->setInlineStyleProperty(CSSPropertyZIndex, String::number(-1000000)); + outline->setInlineStyleProperty(CSSPropertyTop, String::number(-borderWidth - m_target->renderBox()->borderTop()) + "px"); + outline->setInlineStyleProperty(CSSPropertyRight, String::number(-borderWidth - m_target->renderBox()->borderRight()) + "px"); + outline->setInlineStyleProperty(CSSPropertyBottom, String::number(-borderWidth - m_target->renderBox()->borderBottom()) + "px"); + outline->setInlineStyleProperty(CSSPropertyLeft, String::number(-borderWidth - m_target->renderBox()->borderLeft()) + "px"); + outline->setInlineStyleProperty(CSSPropertyBorder, String::number(borderWidth) + "px solid rgba(0, 0, 0, 0.6)"); + outline->setInlineStyleProperty(CSSPropertyWebkitBorderRadius, String::number(borderRadius) + "px"); + outline->setInlineStyleProperty(CSSPropertyVisibility, CSSValueVisible); ExceptionCode ec = 0; container->appendChild(outline.get(), ec); @@ -247,14 +245,13 @@ void DeleteButtonController::createDeletionUI() const int buttonHeight = 30; const int buttonBottomShadowOffset = 2; - style = button->ensureInlineStyleDecl(); - style->setProperty(CSSPropertyPosition, CSSValueAbsolute); - style->setProperty(CSSPropertyZIndex, String::number(1000000)); - style->setProperty(CSSPropertyTop, String::number((-buttonHeight / 2) - m_target->renderBox()->borderTop() - (borderWidth / 2) + buttonBottomShadowOffset) + "px"); - style->setProperty(CSSPropertyLeft, String::number((-buttonWidth / 2) - m_target->renderBox()->borderLeft() - (borderWidth / 2)) + "px"); - style->setProperty(CSSPropertyWidth, String::number(buttonWidth) + "px"); - style->setProperty(CSSPropertyHeight, String::number(buttonHeight) + "px"); - style->setProperty(CSSPropertyVisibility, CSSValueVisible); + button->setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute); + button->setInlineStyleProperty(CSSPropertyZIndex, String::number(1000000)); + button->setInlineStyleProperty(CSSPropertyTop, String::number((-buttonHeight / 2) - m_target->renderBox()->borderTop() - (borderWidth / 2) + buttonBottomShadowOffset) + "px"); + button->setInlineStyleProperty(CSSPropertyLeft, String::number((-buttonWidth / 2) - m_target->renderBox()->borderLeft() - (borderWidth / 2)) + "px"); + button->setInlineStyleProperty(CSSPropertyWidth, String::number(buttonWidth) + "px"); + button->setInlineStyleProperty(CSSPropertyHeight, String::number(buttonHeight) + "px"); + button->setInlineStyleProperty(CSSPropertyVisibility, CSSValueVisible); float deviceScaleFactor = WebCore::deviceScaleFactor(m_frame); RefPtr<Image> buttonImage; @@ -310,12 +307,12 @@ void DeleteButtonController::show(HTMLElement* element) } if (m_target->renderer()->style()->position() == StaticPosition) { - m_target->ensureInlineStyleDecl()->setProperty(CSSPropertyPosition, CSSValueRelative); + m_target->setInlineStyleProperty(CSSPropertyPosition, CSSValueRelative); m_wasStaticPositioned = true; } if (m_target->renderer()->style()->hasAutoZIndex()) { - m_target->ensureInlineStyleDecl()->setProperty(CSSPropertyZIndex, "0"); + m_target->setInlineStyleProperty(CSSPropertyZIndex, "0"); m_wasAutoZIndex = true; } } @@ -331,9 +328,9 @@ void DeleteButtonController::hide() if (m_target) { if (m_wasStaticPositioned) - m_target->ensureInlineStyleDecl()->setProperty(CSSPropertyPosition, CSSValueStatic); + m_target->setInlineStyleProperty(CSSPropertyPosition, CSSValueStatic); if (m_wasAutoZIndex) - m_target->ensureInlineStyleDecl()->setProperty(CSSPropertyZIndex, CSSValueAuto); + m_target->setInlineStyleProperty(CSSPropertyZIndex, CSSValueAuto); } m_wasStaticPositioned = false; diff --git a/Source/WebCore/editing/DeleteSelectionCommand.cpp b/Source/WebCore/editing/DeleteSelectionCommand.cpp index 839b73420..9a94509ce 100644 --- a/Source/WebCore/editing/DeleteSelectionCommand.cpp +++ b/Source/WebCore/editing/DeleteSelectionCommand.cpp @@ -423,7 +423,7 @@ void DeleteSelectionCommand::handleGeneralDelete() } if (startOffset >= caretMaxOffset(startNode) && startNode->isTextNode()) { - Text *text = static_cast<Text *>(startNode); + Text* text = toText(startNode); if (text->length() > (unsigned)caretMaxOffset(startNode)) deleteTextFromNode(text, caretMaxOffset(startNode), text->length() - caretMaxOffset(startNode)); } @@ -441,7 +441,7 @@ void DeleteSelectionCommand::handleGeneralDelete() if (m_downstreamEnd.deprecatedEditingOffset() - startOffset > 0) { if (startNode->isTextNode()) { // in a text node that needs to be trimmed - Text* text = static_cast<Text*>(startNode); + Text* text = toText(startNode); deleteTextFromNode(text, startOffset, m_downstreamEnd.deprecatedEditingOffset() - startOffset); } else { removeChildrenInRange(startNode, startOffset, m_downstreamEnd.deprecatedEditingOffset()); @@ -461,14 +461,14 @@ void DeleteSelectionCommand::handleGeneralDelete() if (startOffset > 0) { if (startNode->isTextNode()) { // in a text node that needs to be trimmed - Text *text = static_cast<Text *>(node.get()); + Text* text = toText(node.get()); deleteTextFromNode(text, startOffset, text->length() - startOffset); node = node->traverseNextNode(); } else { node = startNode->childNode(startOffset); } } else if (startNode == m_upstreamEnd.deprecatedNode() && startNode->isTextNode()) { - Text* text = static_cast<Text*>(m_upstreamEnd.deprecatedNode()); + Text* text = toText(m_upstreamEnd.deprecatedNode()); deleteTextFromNode(text, 0, m_upstreamEnd.deprecatedEditingOffset()); } @@ -501,7 +501,7 @@ void DeleteSelectionCommand::handleGeneralDelete() } else { if (m_downstreamEnd.deprecatedNode()->isTextNode()) { // in a text node that needs to be trimmed - Text* text = static_cast<Text*>(m_downstreamEnd.deprecatedNode()); + Text* text = toText(m_downstreamEnd.deprecatedNode()); if (m_downstreamEnd.deprecatedEditingOffset() > 0) { deleteTextFromNode(text, 0, m_downstreamEnd.deprecatedEditingOffset()); } @@ -533,12 +533,12 @@ void DeleteSelectionCommand::fixupWhitespace() document()->updateLayoutIgnorePendingStylesheets(); // FIXME: isRenderedCharacter should be removed, and we should use VisiblePosition::characterAfter and VisiblePosition::characterBefore if (m_leadingWhitespace.isNotNull() && !m_leadingWhitespace.isRenderedCharacter() && m_leadingWhitespace.deprecatedNode()->isTextNode()) { - Text* textNode = static_cast<Text*>(m_leadingWhitespace.deprecatedNode()); + Text* textNode = toText(m_leadingWhitespace.deprecatedNode()); ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace()); replaceTextInNodePreservingMarkers(textNode, m_leadingWhitespace.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); } if (m_trailingWhitespace.isNotNull() && !m_trailingWhitespace.isRenderedCharacter() && m_trailingWhitespace.deprecatedNode()->isTextNode()) { - Text* textNode = static_cast<Text*>(m_trailingWhitespace.deprecatedNode()); + Text* textNode = toText(m_trailingWhitespace.deprecatedNode()); ASSERT(!textNode->renderer() ||textNode->renderer()->style()->collapseWhiteSpace()); replaceTextInNodePreservingMarkers(textNode, m_trailingWhitespace.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); } diff --git a/Source/WebCore/editing/EditingStyle.cpp b/Source/WebCore/editing/EditingStyle.cpp index 98224f243..57291c1f5 100644 --- a/Source/WebCore/editing/EditingStyle.cpp +++ b/Source/WebCore/editing/EditingStyle.cpp @@ -378,7 +378,7 @@ void EditingStyle::init(Node* node, PropertiesToInclude propertiesToInclude) else if (isTabSpanNode(node)) node = node->parentNode(); - RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = computedStyle(node); + RefPtr<CSSComputedStyleDeclaration> computedStyleAtPosition = CSSComputedStyleDeclaration::create(node); m_mutableStyle = propertiesToInclude == AllProperties && computedStyleAtPosition ? computedStyleAtPosition->copy() : editingStyleFromComputedStyle(computedStyleAtPosition); if (propertiesToInclude == EditingPropertiesInEffect) { @@ -558,8 +558,8 @@ void EditingStyle::removeStyleAddedByNode(Node* node) { if (!node || !node->parentNode()) return; - RefPtr<StylePropertySet> parentStyle = editingStyleFromComputedStyle(computedStyle(node->parentNode()), AllEditingProperties); - RefPtr<StylePropertySet> nodeStyle = editingStyleFromComputedStyle(computedStyle(node), AllEditingProperties); + RefPtr<StylePropertySet> parentStyle = editingStyleFromComputedStyle(CSSComputedStyleDeclaration::create(node->parentNode()), AllEditingProperties); + RefPtr<StylePropertySet> nodeStyle = editingStyleFromComputedStyle(CSSComputedStyleDeclaration::create(node), AllEditingProperties); nodeStyle->removeEquivalentProperties(parentStyle->ensureCSSStyleDeclaration()); m_mutableStyle->removeEquivalentProperties(nodeStyle->ensureCSSStyleDeclaration()); } @@ -569,8 +569,8 @@ void EditingStyle::removeStyleConflictingWithStyleOfNode(Node* node) if (!node || !node->parentNode() || !m_mutableStyle) return; - RefPtr<StylePropertySet> parentStyle = editingStyleFromComputedStyle(computedStyle(node->parentNode()), AllEditingProperties); - RefPtr<StylePropertySet> nodeStyle = editingStyleFromComputedStyle(computedStyle(node), AllEditingProperties); + RefPtr<StylePropertySet> parentStyle = editingStyleFromComputedStyle(CSSComputedStyleDeclaration::create(node->parentNode()), AllEditingProperties); + RefPtr<StylePropertySet> nodeStyle = editingStyleFromComputedStyle(CSSComputedStyleDeclaration::create(node), AllEditingProperties); nodeStyle->removeEquivalentProperties(parentStyle->ensureCSSStyleDeclaration()); unsigned propertyCount = nodeStyle->propertyCount(); @@ -641,7 +641,7 @@ TriState EditingStyle::triStateOfStyle(const VisibleSelection& selection) const TriState state = FalseTriState; for (Node* node = selection.start().deprecatedNode(); node; node = node->traverseNextNode()) { - RefPtr<CSSComputedStyleDeclaration> nodeStyle = computedStyle(node); + RefPtr<CSSComputedStyleDeclaration> nodeStyle = CSSComputedStyleDeclaration::create(node); if (nodeStyle) { TriState nodeState = triStateOfStyle(nodeStyle.get(), node->isTextNode() ? EditingStyle::DoNotIgnoreTextOnlyProperties : EditingStyle::IgnoreTextOnlyProperties); if (node == selection.start().deprecatedNode()) @@ -813,7 +813,7 @@ bool EditingStyle::extractConflictingImplicitStyleOfAttributes(HTMLElement* elem bool EditingStyle::styleIsPresentInComputedStyleOfNode(Node* node) const { - return !m_mutableStyle || getPropertiesNotIn(m_mutableStyle.get(), computedStyle(node).get())->isEmpty(); + return !m_mutableStyle || getPropertiesNotIn(m_mutableStyle.get(), CSSComputedStyleDeclaration::create(node).get())->isEmpty(); } bool EditingStyle::elementIsStyledSpanOrHTMLEquivalent(const HTMLElement* element) @@ -1061,7 +1061,7 @@ void EditingStyle::mergeStyleFromRulesForSerialization(StyledElement* element) // The property value, if it's a percentage, may not reflect the actual computed value. // For example: style="height: 1%; overflow: visible;" in quirksmode // FIXME: There are others like this, see <rdar://problem/5195123> Slashdot copy/paste fidelity problem - RefPtr<CSSComputedStyleDeclaration> computedStyleForElement = computedStyle(element); + RefPtr<CSSComputedStyleDeclaration> computedStyleForElement = CSSComputedStyleDeclaration::create(element); RefPtr<StylePropertySet> fromComputedStyle = StylePropertySet::create(); { unsigned propertyCount = m_mutableStyle->propertyCount(); @@ -1182,6 +1182,91 @@ PassRefPtr<EditingStyle> EditingStyle::styleAtSelectionStart(const VisibleSelect return style; } +WritingDirection EditingStyle::textDirectionForSelection(const VisibleSelection& selection, EditingStyle* typingStyle, bool& hasNestedOrMultipleEmbeddings) +{ + hasNestedOrMultipleEmbeddings = true; + + if (selection.isNone()) + return NaturalWritingDirection; + + Position position = selection.start().downstream(); + + Node* node = position.deprecatedNode(); + if (!node) + return NaturalWritingDirection; + + Position end; + if (selection.isRange()) { + end = selection.end().upstream(); + + Node* pastLast = Range::create(end.document(), position.parentAnchoredEquivalent(), end.parentAnchoredEquivalent())->pastLastNode(); + for (Node* n = node; n && n != pastLast; n = n->traverseNextNode()) { + if (!n->isStyledElement()) + continue; + + RefPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration::create(n); + RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropertyUnicodeBidi); + if (!unicodeBidi || !unicodeBidi->isPrimitiveValue()) + continue; + + int unicodeBidiValue = static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent(); + if (unicodeBidiValue == CSSValueEmbed || unicodeBidiValue == CSSValueBidiOverride) + return NaturalWritingDirection; + } + } + + if (selection.isCaret()) { + WritingDirection direction; + if (typingStyle && typingStyle->textDirection(direction)) { + hasNestedOrMultipleEmbeddings = false; + return direction; + } + node = selection.visibleStart().deepEquivalent().deprecatedNode(); + } + + // The selection is either a caret with no typing attributes or a range in which no embedding is added, so just use the start position + // to decide. + Node* block = enclosingBlock(node); + WritingDirection foundDirection = NaturalWritingDirection; + + for (; node != block; node = node->parentNode()) { + if (!node->isStyledElement()) + continue; + + RefPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration::create(node); + RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropertyUnicodeBidi); + if (!unicodeBidi || !unicodeBidi->isPrimitiveValue()) + continue; + + int unicodeBidiValue = static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent(); + if (unicodeBidiValue == CSSValueNormal) + continue; + + if (unicodeBidiValue == CSSValueBidiOverride) + return NaturalWritingDirection; + + ASSERT(unicodeBidiValue == CSSValueEmbed); + RefPtr<CSSValue> direction = style->getPropertyCSSValue(CSSPropertyDirection); + if (!direction || !direction->isPrimitiveValue()) + continue; + + int directionValue = static_cast<CSSPrimitiveValue*>(direction.get())->getIdent(); + if (directionValue != CSSValueLtr && directionValue != CSSValueRtl) + continue; + + if (foundDirection != NaturalWritingDirection) + return NaturalWritingDirection; + + // In the range case, make sure that the embedding element persists until the end of the range. + if (selection.isRange() && !end.deprecatedNode()->isDescendantOf(node)) + return NaturalWritingDirection; + + foundDirection = directionValue == CSSValueLtr ? LeftToRightWritingDirection : RightToLeftWritingDirection; + } + hasNestedOrMultipleEmbeddings = false; + return foundDirection; +} + static void reconcileTextDecorationProperties(StylePropertySet* style) { RefPtr<CSSValue> textDecorationsInEffect = style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect); @@ -1487,7 +1572,7 @@ bool hasTransparentBackgroundColor(StylePropertySet* style) PassRefPtr<CSSValue> backgroundColorInEffect(Node* node) { for (Node* ancestor = node; ancestor; ancestor = ancestor->parentNode()) { - RefPtr<CSSComputedStyleDeclaration> ancestorStyle = computedStyle(ancestor); + RefPtr<CSSComputedStyleDeclaration> ancestorStyle = CSSComputedStyleDeclaration::create(ancestor); if (!hasTransparentBackgroundColor(ancestorStyle.get())) return ancestorStyle->getPropertyCSSValue(CSSPropertyBackgroundColor); } diff --git a/Source/WebCore/editing/EditingStyle.h b/Source/WebCore/editing/EditingStyle.h index 6b60920c6..71dc652f0 100644 --- a/Source/WebCore/editing/EditingStyle.h +++ b/Source/WebCore/editing/EditingStyle.h @@ -145,6 +145,7 @@ public: bool shouldUseFixedDefaultFontSize() const { return m_shouldUseFixedDefaultFontSize; } static PassRefPtr<EditingStyle> styleAtSelectionStart(const VisibleSelection&, bool shouldUseBackgroundColorInEffect = false); + static WritingDirection textDirectionForSelection(const VisibleSelection&, EditingStyle* typingStyle, bool& hasNestedOrMultipleEmbeddings); private: EditingStyle(); EditingStyle(Node*, PropertiesToInclude); diff --git a/Source/WebCore/editing/Editor.cpp b/Source/WebCore/editing/Editor.cpp index 97b153365..1ce24e538 100644 --- a/Source/WebCore/editing/Editor.cpp +++ b/Source/WebCore/editing/Editor.cpp @@ -418,7 +418,7 @@ void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, return; RefPtr<Range> rangeToCheck = Range::create(m_frame->document(), firstPositionInNode(nodeToCheck), lastPositionInNode(nodeToCheck)); - m_spellChecker->requestCheckingFor(SpellCheckRequest::create(resolveTextCheckingTypeMask(TextCheckingTypeSpelling | TextCheckingTypeGrammar), rangeToCheck, rangeToCheck)); + m_spellChecker->requestCheckingFor(SpellCheckRequest::create(resolveTextCheckingTypeMask(TextCheckingTypeSpelling | TextCheckingTypeGrammar), TextCheckingProcessBatch, rangeToCheck, rangeToCheck)); } void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace) @@ -499,92 +499,6 @@ void Editor::respondToChangedContents(const VisibleSelection& endingSelection) client()->respondToChangedContents(); } -WritingDirection Editor::textDirectionForSelection(bool& hasNestedOrMultipleEmbeddings) const -{ - hasNestedOrMultipleEmbeddings = true; - - if (m_frame->selection()->isNone()) - return NaturalWritingDirection; - - Position position = m_frame->selection()->selection().start().downstream(); - - Node* node = position.deprecatedNode(); - if (!node) - return NaturalWritingDirection; - - Position end; - if (m_frame->selection()->isRange()) { - end = m_frame->selection()->selection().end().upstream(); - - Node* pastLast = Range::create(m_frame->document(), position.parentAnchoredEquivalent(), end.parentAnchoredEquivalent())->pastLastNode(); - for (Node* n = node; n && n != pastLast; n = n->traverseNextNode()) { - if (!n->isStyledElement()) - continue; - - RefPtr<CSSComputedStyleDeclaration> style = computedStyle(n); - RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropertyUnicodeBidi); - if (!unicodeBidi || !unicodeBidi->isPrimitiveValue()) - continue; - - int unicodeBidiValue = static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent(); - if (unicodeBidiValue == CSSValueEmbed || unicodeBidiValue == CSSValueBidiOverride) - return NaturalWritingDirection; - } - } - - if (m_frame->selection()->isCaret()) { - RefPtr<EditingStyle> typingStyle = m_frame->selection()->typingStyle(); - WritingDirection direction; - if (typingStyle && typingStyle->textDirection(direction)) { - hasNestedOrMultipleEmbeddings = false; - return direction; - } - node = m_frame->selection()->selection().visibleStart().deepEquivalent().deprecatedNode(); - } - - // The selection is either a caret with no typing attributes or a range in which no embedding is added, so just use the start position - // to decide. - Node* block = enclosingBlock(node); - WritingDirection foundDirection = NaturalWritingDirection; - - for (; node != block; node = node->parentNode()) { - if (!node->isStyledElement()) - continue; - - RefPtr<CSSComputedStyleDeclaration> style = computedStyle(node); - RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropertyUnicodeBidi); - if (!unicodeBidi || !unicodeBidi->isPrimitiveValue()) - continue; - - int unicodeBidiValue = static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent(); - if (unicodeBidiValue == CSSValueNormal) - continue; - - if (unicodeBidiValue == CSSValueBidiOverride) - return NaturalWritingDirection; - - ASSERT(unicodeBidiValue == CSSValueEmbed); - RefPtr<CSSValue> direction = style->getPropertyCSSValue(CSSPropertyDirection); - if (!direction || !direction->isPrimitiveValue()) - continue; - - int directionValue = static_cast<CSSPrimitiveValue*>(direction.get())->getIdent(); - if (directionValue != CSSValueLtr && directionValue != CSSValueRtl) - continue; - - if (foundDirection != NaturalWritingDirection) - return NaturalWritingDirection; - - // In the range case, make sure that the embedding element persists until the end of the range. - if (m_frame->selection()->isRange() && !end.deprecatedNode()->isDescendantOf(node)) - return NaturalWritingDirection; - - foundDirection = directionValue == CSSValueLtr ? LeftToRightWritingDirection : RightToLeftWritingDirection; - } - hasNestedOrMultipleEmbeddings = false; - return foundDirection; -} - bool Editor::hasBidiSelection() const { if (m_frame->selection()->isNone()) @@ -764,7 +678,7 @@ Node* Editor::findEventTargetFromSelection() const return findEventTargetFrom(m_frame->selection()->selection()); } -void Editor::applyStyle(CSSStyleDeclaration* style, EditAction editingAction) +void Editor::applyStyle(StylePropertySet* style, EditAction editingAction) { switch (m_frame->selection()->selectionType()) { case VisibleSelection::NoSelection: @@ -780,12 +694,12 @@ void Editor::applyStyle(CSSStyleDeclaration* style, EditAction editingAction) } } -bool Editor::shouldApplyStyle(CSSStyleDeclaration* style, Range* range) +bool Editor::shouldApplyStyle(StylePropertySet* style, Range* range) { return client()->shouldApplyStyle(style, range); } -void Editor::applyParagraphStyle(CSSStyleDeclaration* style, EditAction editingAction) +void Editor::applyParagraphStyle(StylePropertySet* style, EditAction editingAction) { switch (m_frame->selection()->selectionType()) { case VisibleSelection::NoSelection: @@ -799,18 +713,18 @@ void Editor::applyParagraphStyle(CSSStyleDeclaration* style, EditAction editingA } } -void Editor::applyStyleToSelection(CSSStyleDeclaration* style, EditAction editingAction) +void Editor::applyStyleToSelection(StylePropertySet* style, EditAction editingAction) { - if (!style || !style->length() || !canEditRichly()) + if (!style || style->isEmpty() || !canEditRichly()) return; if (client() && client()->shouldApplyStyle(style, m_frame->selection()->toNormalizedRange().get())) applyStyle(style, editingAction); } -void Editor::applyParagraphStyleToSelection(CSSStyleDeclaration* style, EditAction editingAction) +void Editor::applyParagraphStyleToSelection(StylePropertySet* style, EditAction editingAction) { - if (!style || !style->length() || !canEditRichly()) + if (!style || style->isEmpty() || !canEditRichly()) return; if (client() && client()->shouldApplyStyle(style, m_frame->selection()->toNormalizedRange().get())) @@ -1348,7 +1262,7 @@ void Editor::setBaseWritingDirection(WritingDirection direction) RefPtr<StylePropertySet> style = StylePropertySet::create(); style->setProperty(CSSPropertyDirection, direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", false); - applyParagraphStyleToSelection(style->ensureCSSStyleDeclaration(), EditActionSetWritingDirection); + applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection); } void Editor::selectComposition() @@ -1502,7 +1416,7 @@ void Editor::setComposition(const String& text, const Vector<CompositionUnderlin unsigned extentOffset = extent.deprecatedEditingOffset(); if (baseNode && baseNode == extentNode && baseNode->isTextNode() && baseOffset + text.length() == extentOffset) { - m_compositionNode = static_cast<Text*>(baseNode); + m_compositionNode = toText(baseNode); m_compositionStart = baseOffset; m_compositionEnd = extentOffset; m_customCompositionUnderlines = underlines; @@ -2021,7 +1935,7 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textC bool asynchronous = m_frame && m_frame->settings() && m_frame->settings()->asynchronousSpellCheckingEnabled() && !shouldShowCorrectionPanel; // In asynchronous mode, we intentionally check paragraph-wide sentence. - RefPtr<SpellCheckRequest> request = SpellCheckRequest::create(resolveTextCheckingTypeMask(textCheckingOptions), asynchronous ? paragraphRange : rangeToCheck, paragraphRange); + RefPtr<SpellCheckRequest> request = SpellCheckRequest::create(resolveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessIncremental, asynchronous ? paragraphRange : rangeToCheck, paragraphRange); if (asynchronous) { m_spellChecker->requestCheckingFor(request); @@ -2665,9 +2579,9 @@ bool Editor::shouldChangeSelection(const VisibleSelection& oldSelection, const V return client() && client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(), affinity, stillSelecting); } -void Editor::computeAndSetTypingStyle(CSSStyleDeclaration* style, EditAction editingAction) +void Editor::computeAndSetTypingStyle(StylePropertySet* style, EditAction editingAction) { - if (!style || !style->length()) { + if (!style || style->isEmpty()) { m_frame->selection()->clearTypingStyle(); return; } @@ -2676,7 +2590,7 @@ void Editor::computeAndSetTypingStyle(CSSStyleDeclaration* style, EditAction edi RefPtr<EditingStyle> typingStyle; if (m_frame->selection()->typingStyle()) { typingStyle = m_frame->selection()->typingStyle()->copy(); - typingStyle->overrideWithStyle(style->makeMutable().get()); + typingStyle->overrideWithStyle(style); } else typingStyle = EditingStyle::create(style); @@ -2745,10 +2659,13 @@ void Editor::applyEditingStyleToElement(Element* element) const ASSERT(element->isStyledElement()); if (!element->isStyledElement()) return; - StylePropertySet* style = static_cast<StyledElement*>(element)->ensureInlineStyleDecl(); - style->setProperty(CSSPropertyWordWrap, "break-word", false); - style->setProperty(CSSPropertyWebkitNbspMode, "space", false); - style->setProperty(CSSPropertyWebkitLineBreak, "after-white-space", false); + + // Mutate using the CSSOM wrapper so we get the same event behavior as a script. + CSSStyleDeclaration* style = static_cast<StyledElement*>(element)->style(); + ExceptionCode ec; + style->setPropertyInternal(CSSPropertyWordWrap, "break-word", false, ec); + style->setPropertyInternal(CSSPropertyWebkitNbspMode, "space", false, ec); + style->setPropertyInternal(CSSPropertyWebkitLineBreak, "after-white-space", false, ec); } // Searches from the beginning of the document if nothing is selected. diff --git a/Source/WebCore/editing/Editor.h b/Source/WebCore/editing/Editor.h index 5a7815892..e398bbf3e 100644 --- a/Source/WebCore/editing/Editor.h +++ b/Source/WebCore/editing/Editor.h @@ -46,7 +46,6 @@ typedef int NSWritingDirection; namespace WebCore { -class CSSStyleDeclaration; class Clipboard; class CompositeEditCommand; class DeleteButtonController; @@ -63,6 +62,7 @@ class SimpleFontData; class SpellChecker; class SpellCheckRequest; class SpellingCorrectionController; +class StylePropertySet; class Text; class TextCheckerClient; class TextEvent; @@ -130,7 +130,7 @@ public: bool shouldInsertText(const String&, Range*, EditorInsertAction) const; bool shouldShowDeleteInterface(HTMLElement*) const; bool shouldDeleteRange(Range*) const; - bool shouldApplyStyle(CSSStyleDeclaration*, Range*); + bool shouldApplyStyle(StylePropertySet*, Range*); void respondToChangedSelection(const VisibleSelection& oldSelection); void respondToChangedContents(const VisibleSelection& endingSelection); @@ -138,7 +138,6 @@ public: bool selectionStartHasStyle(int propertyID, const String& value) const; TriState selectionHasStyle(int propertyID, const String& value) const; String selectionStartCSSPropertyValue(int propertyID); - WritingDirection textDirectionForSelection(bool&) const; TriState selectionUnorderedListState() const; TriState selectionOrderedListState() const; @@ -162,10 +161,10 @@ public: Node* removedAnchor() const { return m_removedAnchor.get(); } void setRemovedAnchor(PassRefPtr<Node> n) { m_removedAnchor = n; } - void applyStyle(CSSStyleDeclaration*, EditAction = EditActionUnspecified); - void applyParagraphStyle(CSSStyleDeclaration*, EditAction = EditActionUnspecified); - void applyStyleToSelection(CSSStyleDeclaration*, EditAction); - void applyParagraphStyleToSelection(CSSStyleDeclaration*, EditAction); + void applyStyle(StylePropertySet*, EditAction = EditActionUnspecified); + void applyParagraphStyle(StylePropertySet*, EditAction = EditActionUnspecified); + void applyStyleToSelection(StylePropertySet*, EditAction); + void applyParagraphStyleToSelection(StylePropertySet*, EditAction); void appliedEditing(PassRefPtr<CompositeEditCommand>); void unappliedEditing(PassRefPtr<EditCommandComposition>); @@ -346,7 +345,7 @@ public: const VisibleSelection& mark() const; // Mark, to be used as emacs uses it. void setMark(const VisibleSelection&); - void computeAndSetTypingStyle(CSSStyleDeclaration* , EditAction = EditActionUnspecified); + void computeAndSetTypingStyle(StylePropertySet* , EditAction = EditActionUnspecified); void applyEditingStyleToBodyElement() const; void applyEditingStyleToElement(Element*) const; diff --git a/Source/WebCore/editing/EditorCommand.cpp b/Source/WebCore/editing/EditorCommand.cpp index a2ad63372..a4137425d 100644 --- a/Source/WebCore/editing/EditorCommand.cpp +++ b/Source/WebCore/editing/EditorCommand.cpp @@ -103,11 +103,11 @@ static bool applyCommandToFrame(Frame* frame, EditorCommandSource source, EditAc // FIXME: We don't call shouldApplyStyle when the source is DOM; is there a good reason for that? switch (source) { case CommandFromMenuOrKeyBinding: - frame->editor()->applyStyleToSelection(style->ensureCSSStyleDeclaration(), action); + frame->editor()->applyStyleToSelection(style, action); return true; case CommandFromDOM: case CommandFromDOMWithUserInterface: - frame->editor()->applyStyle(style->ensureCSSStyleDeclaration()); + frame->editor()->applyStyle(style); return true; } ASSERT_NOT_REACHED(); @@ -179,11 +179,11 @@ static bool executeApplyParagraphStyle(Frame* frame, EditorCommandSource source, // FIXME: We don't call shouldApplyStyle when the source is DOM; is there a good reason for that? switch (source) { case CommandFromMenuOrKeyBinding: - frame->editor()->applyParagraphStyleToSelection(style->ensureCSSStyleDeclaration(), action); + frame->editor()->applyParagraphStyleToSelection(style.get(), action); return true; case CommandFromDOM: case CommandFromDOMWithUserInterface: - frame->editor()->applyParagraphStyle(style->ensureCSSStyleDeclaration()); + frame->editor()->applyParagraphStyle(style.get()); return true; } ASSERT_NOT_REACHED(); @@ -241,7 +241,9 @@ static String valueStyle(Frame* frame, int propertyID) static TriState stateTextWritingDirection(Frame* frame, WritingDirection direction) { bool hasNestedOrMultipleEmbeddings; - WritingDirection selectionDirection = frame->editor()->textDirectionForSelection(hasNestedOrMultipleEmbeddings); + WritingDirection selectionDirection = EditingStyle::textDirectionForSelection(frame->selection()->selection(), + frame->selection()->typingStyle(), hasNestedOrMultipleEmbeddings); + // FXIME: We should be returning MixedTriState when selectionDirection == direction && hasNestedOrMultipleEmbeddings return (selectionDirection == direction && !hasNestedOrMultipleEmbeddings) ? TrueTriState : FalseTriState; } @@ -583,7 +585,7 @@ static bool executeMakeTextWritingDirectionLeftToRight(Frame* frame, Event*, Edi RefPtr<StylePropertySet> style = StylePropertySet::create(); style->setProperty(CSSPropertyUnicodeBidi, CSSValueEmbed); style->setProperty(CSSPropertyDirection, CSSValueLtr); - frame->editor()->applyStyle(style->ensureCSSStyleDeclaration(), EditActionSetWritingDirection); + frame->editor()->applyStyle(style.get(), EditActionSetWritingDirection); return true; } @@ -591,7 +593,7 @@ static bool executeMakeTextWritingDirectionNatural(Frame* frame, Event*, EditorC { RefPtr<StylePropertySet> style = StylePropertySet::create(); style->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal); - frame->editor()->applyStyle(style->ensureCSSStyleDeclaration(), EditActionSetWritingDirection); + frame->editor()->applyStyle(style.get(), EditActionSetWritingDirection); return true; } @@ -600,7 +602,7 @@ static bool executeMakeTextWritingDirectionRightToLeft(Frame* frame, Event*, Edi RefPtr<StylePropertySet> style = StylePropertySet::create(); style->setProperty(CSSPropertyUnicodeBidi, CSSValueEmbed); style->setProperty(CSSPropertyDirection, CSSValueRtl); - frame->editor()->applyStyle(style->ensureCSSStyleDeclaration(), EditActionSetWritingDirection); + frame->editor()->applyStyle(style.get(), EditActionSetWritingDirection); return true; } diff --git a/Source/WebCore/editing/FrameSelection.cpp b/Source/WebCore/editing/FrameSelection.cpp index fc7286eba..de2d65d7e 100644 --- a/Source/WebCore/editing/FrameSelection.cpp +++ b/Source/WebCore/editing/FrameSelection.cpp @@ -425,10 +425,17 @@ static void updatePositionAfterAdoptingTextReplacement(Position& position, Chara position.moveToOffset(positionOffset - oldLength + newLength); } +static inline bool nodeIsDetachedFromDocument(Node* node) +{ + ASSERT(node); + Node* highest = highestAncestor(node); + return highest->nodeType() == Node::DOCUMENT_FRAGMENT_NODE && !highest->isShadowRoot(); +} + void FrameSelection::textWillBeReplaced(CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength) { // The fragment check is a performance optimization. See http://trac.webkit.org/changeset/30062. - if (isNone() || !node || highestAncestor(node)->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) + if (isNone() || !node || nodeIsDetachedFromDocument(node)) return; Position base = m_selection.base(); diff --git a/Source/WebCore/editing/InsertLineBreakCommand.cpp b/Source/WebCore/editing/InsertLineBreakCommand.cpp index c8e8b83c3..f64763235 100644 --- a/Source/WebCore/editing/InsertLineBreakCommand.cpp +++ b/Source/WebCore/editing/InsertLineBreakCommand.cpp @@ -137,7 +137,7 @@ void InsertLineBreakCommand::doApply() setEndingSelection(VisibleSelection(positionInParentAfterNode(nodeToInsert.get()), DOWNSTREAM, endingSelection().isDirectional())); } else if (pos.deprecatedNode()->isTextNode()) { // Split a text node - Text* textNode = static_cast<Text*>(pos.deprecatedNode()); + Text* textNode = toText(pos.deprecatedNode()); splitTextNode(textNode, pos.deprecatedEditingOffset()); insertNodeBefore(nodeToInsert, textNode); Position endingPosition = firstPositionInNode(textNode); diff --git a/Source/WebCore/editing/InsertListCommand.cpp b/Source/WebCore/editing/InsertListCommand.cpp index dbc22ba7d..e4e357826 100644 --- a/Source/WebCore/editing/InsertListCommand.cpp +++ b/Source/WebCore/editing/InsertListCommand.cpp @@ -152,11 +152,11 @@ void InsertListCommand::doApply() // FIXME: This is an inefficient way to keep selection alive because indexForVisiblePosition walks from // the beginning of the document to the endOfSelection everytime this code is executed. // But not using index is hard because there are so many ways we can lose selection inside doApplyForSingleParagraph. - Element* scope = 0; - int indexForEndOfSelection = indexForVisiblePosition(endOfSelection, &scope); + RefPtr<Element> scope; + int indexForEndOfSelection = indexForVisiblePosition(endOfSelection, scope); doApplyForSingleParagraph(forceCreateList, listTag, currentSelection.get()); if (endOfSelection.isNull() || endOfSelection.isOrphan() || startOfLastParagraph.isNull() || startOfLastParagraph.isOrphan()) { - endOfSelection = visiblePositionForIndex(indexForEndOfSelection, scope); + endOfSelection = visiblePositionForIndex(indexForEndOfSelection, scope.get()); // If endOfSelection is null, then some contents have been deleted from the document. // This should never happen and if it did, exit early immediately because we've lost the loop invariant. ASSERT(endOfSelection.isNotNull()); diff --git a/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp b/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp index 4aec419a1..46f3c8a5d 100644 --- a/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp +++ b/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp @@ -322,14 +322,14 @@ void InsertParagraphSeparatorCommand::doApply() // FIXME: leadingWhitespacePosition is returning the position before preserved newlines for positions // after the preserved newline, causing the newline to be turned into a nbsp. if (leadingWhitespace.isNotNull() && leadingWhitespace.deprecatedNode()->isTextNode()) { - Text* textNode = static_cast<Text*>(leadingWhitespace.deprecatedNode()); + Text* textNode = toText(leadingWhitespace.deprecatedNode()); ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace()); replaceTextInNodePreservingMarkers(textNode, leadingWhitespace.deprecatedEditingOffset(), 1, nonBreakingSpaceString()); } // Split at pos if in the middle of a text node. if (insertionPosition.deprecatedNode()->isTextNode()) { - Text* textNode = static_cast<Text*>(insertionPosition.deprecatedNode()); + Text* textNode = toText(insertionPosition.deprecatedNode()); bool atEnd = (unsigned)insertionPosition.deprecatedEditingOffset() >= textNode->length(); if (insertionPosition.deprecatedEditingOffset() > 0 && !atEnd) { splitTextNode(textNode, insertionPosition.deprecatedEditingOffset()); @@ -389,7 +389,7 @@ void InsertParagraphSeparatorCommand::doApply() ASSERT(!insertionPosition.deprecatedNode()->renderer() || insertionPosition.deprecatedNode()->renderer()->style()->collapseWhiteSpace()); deleteInsignificantTextDownstream(insertionPosition); if (insertionPosition.deprecatedNode()->isTextNode()) - insertTextIntoNode(static_cast<Text*>(insertionPosition.deprecatedNode()), 0, nonBreakingSpaceString()); + insertTextIntoNode(toText(insertionPosition.deprecatedNode()), 0, nonBreakingSpaceString()); } } diff --git a/Source/WebCore/editing/InsertTextCommand.cpp b/Source/WebCore/editing/InsertTextCommand.cpp index b2c0af06e..39fa2a897 100644 --- a/Source/WebCore/editing/InsertTextCommand.cpp +++ b/Source/WebCore/editing/InsertTextCommand.cpp @@ -209,7 +209,7 @@ Position InsertTextCommand::insertTab(const Position& pos) // keep tabs coalesced in tab span if (isTabSpanTextNode(node)) { - RefPtr<Text> textNode = static_cast<Text*>(node); + RefPtr<Text> textNode = toText(node); insertTextIntoNode(textNode, offset, "\t"); return Position(textNode.release(), offset + 1); } @@ -221,7 +221,7 @@ Position InsertTextCommand::insertTab(const Position& pos) if (!node->isTextNode()) { insertNodeAt(spanNode.get(), insertPos); } else { - RefPtr<Text> textNode = static_cast<Text*>(node); + RefPtr<Text> textNode = toText(node); if (offset >= textNode->length()) insertNodeAfter(spanNode, textNode.release()); else { diff --git a/Source/WebCore/editing/MarkupAccumulator.cpp b/Source/WebCore/editing/MarkupAccumulator.cpp index 306a84655..476904ebc 100644 --- a/Source/WebCore/editing/MarkupAccumulator.cpp +++ b/Source/WebCore/editing/MarkupAccumulator.cpp @@ -419,7 +419,7 @@ void MarkupAccumulator::appendStartMarkup(StringBuilder& result, const Node* nod switch (node->nodeType()) { case Node::TEXT_NODE: - appendText(result, static_cast<Text*>(const_cast<Node*>(node))); + appendText(result, toText(const_cast<Node*>(node))); break; case Node::COMMENT_NODE: appendComment(result, static_cast<const Comment*>(node)->data()); @@ -444,7 +444,6 @@ void MarkupAccumulator::appendStartMarkup(StringBuilder& result, const Node* nod case Node::ENTITY_REFERENCE_NODE: case Node::NOTATION_NODE: case Node::XPATH_NAMESPACE_NODE: - case Node::SHADOW_ROOT_NODE: ASSERT_NOT_REACHED(); break; } diff --git a/Source/WebCore/editing/RemoveCSSPropertyCommand.cpp b/Source/WebCore/editing/RemoveCSSPropertyCommand.cpp index cbbba5225..ca5baba4b 100644 --- a/Source/WebCore/editing/RemoveCSSPropertyCommand.cpp +++ b/Source/WebCore/editing/RemoveCSSPropertyCommand.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "RemoveCSSPropertyCommand.h" +#include "CSSStyleDeclaration.h" #include "StylePropertySet.h" #include <wtf/Assertions.h> @@ -45,13 +46,17 @@ void RemoveCSSPropertyCommand::doApply() StylePropertySet* style = m_element->inlineStyleDecl(); m_oldValue = style->getPropertyValue(m_property); m_important = style->propertyIsImportant(m_property); - style->removeProperty(m_property); + + // Mutate using the CSSOM wrapper so we get the same event behavior as a script. + ExceptionCode ec; + // Setting to null string removes the property. We don't have internal version of removeProperty. + m_element->style()->setPropertyInternal(m_property, String(), false, ec); } void RemoveCSSPropertyCommand::doUnapply() { - StylePropertySet* style = m_element->inlineStyleDecl(); - style->setProperty(m_property, m_oldValue, m_important); + ExceptionCode ec; + m_element->style()->setPropertyInternal(m_property, m_oldValue, m_important, ec); } #ifndef NDEBUG diff --git a/Source/WebCore/editing/ReplaceSelectionCommand.cpp b/Source/WebCore/editing/ReplaceSelectionCommand.cpp index 8ce9446a9..95fdaf060 100644 --- a/Source/WebCore/editing/ReplaceSelectionCommand.cpp +++ b/Source/WebCore/editing/ReplaceSelectionCommand.cpp @@ -30,8 +30,8 @@ #include "ApplyStyleCommand.h" #include "BeforeTextInsertedEvent.h" #include "BreakBlockquoteCommand.h" -#include "CSSComputedStyleDeclaration.h" #include "CSSPropertyNames.h" +#include "CSSStyleDeclaration.h" #include "CSSValueKeywords.h" #include "Document.h" #include "DocumentFragment.h" @@ -293,6 +293,9 @@ void ReplacementFragment::removeUnrenderedNodes(Node* holder) void ReplacementFragment::removeInterchangeNodes(Node* container) { + m_hasInterchangeNewlineAtStart = false; + m_hasInterchangeNewlineAtEnd = false; + // Interchange newlines at the "start" of the incoming fragment must be // either the first node in the fragment or the first leaf in the fragment. Node* node = container->firstChild(); @@ -531,10 +534,13 @@ void ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(Insert // FIXME: Hyatt is concerned that selectively using display:inline will give inconsistent // results. We already know one issue because td elements ignore their display property // in quirks mode (which Mail.app is always in). We should look for an alternative. + + // Mutate using the CSSOM wrapper so we get the same event behavior as a script. + ExceptionCode ec; if (isBlock(element)) - element->ensureInlineStyleDecl()->setProperty(CSSPropertyDisplay, CSSValueInline); + element->style()->setPropertyInternal(CSSPropertyDisplay, "inline", false, ec); if (element->renderer() && element->renderer()->style()->isFloating()) - element->ensureInlineStyleDecl()->setProperty(CSSPropertyFloat, CSSValueNone); + element->style()->setPropertyInternal(CSSPropertyFloat, "none", false, ec); } } } @@ -597,7 +603,7 @@ void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds(InsertedNodes& ins document()->updateLayoutIgnorePendingStylesheets(); Node* lastLeafInserted = insertedNodes.lastLeafInserted(); - if (lastLeafInserted && lastLeafInserted->isTextNode() && !nodeHasVisibleRenderText(static_cast<Text*>(lastLeafInserted)) + if (lastLeafInserted && lastLeafInserted->isTextNode() && !nodeHasVisibleRenderText(toText(lastLeafInserted)) && !enclosingNodeWithTag(firstPositionInOrBeforeNode(lastLeafInserted), selectTag) && !enclosingNodeWithTag(firstPositionInOrBeforeNode(lastLeafInserted), scriptTag)) { insertedNodes.willRemoveNode(lastLeafInserted); @@ -608,7 +614,7 @@ void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds(InsertedNodes& ins // it is a top level node in the fragment and the user can't insert into those elements. Node* firstNodeInserted = insertedNodes.firstNodeInserted(); lastLeafInserted = insertedNodes.lastLeafInserted(); - if (firstNodeInserted && firstNodeInserted->isTextNode() && !nodeHasVisibleRenderText(static_cast<Text*>(firstNodeInserted))) { + if (firstNodeInserted && firstNodeInserted->isTextNode() && !nodeHasVisibleRenderText(toText(firstNodeInserted))) { insertedNodes.willRemoveNode(firstNodeInserted); removeNode(firstNodeInserted); } @@ -1189,7 +1195,7 @@ void ReplaceSelectionCommand::addSpacesForSmartReplace() if (needsTrailingSpace && endNode) { bool collapseWhiteSpace = !endNode->renderer() || endNode->renderer()->style()->collapseWhiteSpace(); if (endNode->isTextNode()) { - Text* text = static_cast<Text*>(endNode); + Text* text = toText(endNode); // FIXME: we shouldn't always be inserting the space at the end insertTextIntoNode(text, text->length(), collapseWhiteSpace ? nonBreakingSpaceString() : " "); if (m_endOfInsertedContent.containerNode() == text) @@ -1213,7 +1219,7 @@ void ReplaceSelectionCommand::addSpacesForSmartReplace() if (needsLeadingSpace && startNode) { bool collapseWhiteSpace = !startNode->renderer() || startNode->renderer()->style()->collapseWhiteSpace(); if (startNode->isTextNode()) { - insertTextIntoNode(static_cast<Text*>(startNode), startOffset, collapseWhiteSpace ? nonBreakingSpaceString() : " "); + insertTextIntoNode(toText(startNode), startOffset, collapseWhiteSpace ? nonBreakingSpaceString() : " "); if (m_endOfInsertedContent.containerNode() == startNode && m_endOfInsertedContent.offsetInContainerNode()) m_endOfInsertedContent.moveToOffset(m_endOfInsertedContent.offsetInContainerNode() + 1); } else { @@ -1279,7 +1285,7 @@ Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtr<Node> prpListElement if (isMiddle) { int textNodeOffset = insertPos.offsetInContainerNode(); if (insertPos.deprecatedNode()->isTextNode() && textNodeOffset > 0) - splitTextNode(static_cast<Text*>(insertPos.deprecatedNode()), textNodeOffset); + splitTextNode(toText(insertPos.deprecatedNode()), textNodeOffset); splitTreeToNode(insertPos.deprecatedNode(), lastNode, true); } @@ -1333,7 +1339,7 @@ bool ReplaceSelectionCommand::performTrivialReplace(const ReplacementFragment& f return false; Node* nodeAfterInsertionPos = endingSelection().end().downstream().anchorNode(); - Text* textNode = static_cast<Text*>(fragment.firstChild()); + Text* textNode = toText(fragment.firstChild()); // Our fragment creation code handles tabs, spaces, and newlines, so we don't have to worry about those here. Position start = endingSelection().start(); diff --git a/Source/WebCore/editing/SpellChecker.cpp b/Source/WebCore/editing/SpellChecker.cpp index 683644c6d..e1243b14d 100644 --- a/Source/WebCore/editing/SpellChecker.cpp +++ b/Source/WebCore/editing/SpellChecker.cpp @@ -47,12 +47,13 @@ namespace WebCore { static const int unrequestedSequence = -1; -SpellCheckRequest::SpellCheckRequest(int sequence, PassRefPtr<Range> checkingRange, PassRefPtr<Range> paragraphRange, const String& text, TextCheckingTypeMask mask) +SpellCheckRequest::SpellCheckRequest(int sequence, PassRefPtr<Range> checkingRange, PassRefPtr<Range> paragraphRange, const String& text, TextCheckingTypeMask mask, TextCheckingProcessType processType) : m_sequence(sequence) - , m_checkingRange(checkingRange) - , m_paragraphRange(paragraphRange) , m_text(text) , m_mask(mask) + , m_processType(processType) + , m_checkingRange(checkingRange) + , m_paragraphRange(paragraphRange) , m_rootEditableElement(m_checkingRange->startContainer()->rootEditableElement()) { } @@ -62,7 +63,7 @@ SpellCheckRequest::~SpellCheckRequest() } // static -PassRefPtr<SpellCheckRequest> SpellCheckRequest::create(TextCheckingTypeMask textCheckingOptions, PassRefPtr<Range> checkingRange, PassRefPtr<Range> paragraphRange) +PassRefPtr<SpellCheckRequest> SpellCheckRequest::create(TextCheckingTypeMask textCheckingOptions, TextCheckingProcessType processType, PassRefPtr<Range> checkingRange, PassRefPtr<Range> paragraphRange) { ASSERT(checkingRange); ASSERT(paragraphRange); @@ -71,7 +72,7 @@ PassRefPtr<SpellCheckRequest> SpellCheckRequest::create(TextCheckingTypeMask tex if (!text.length()) return PassRefPtr<SpellCheckRequest>(); - return adoptRef(new SpellCheckRequest(unrequestedSequence, checkingRange, paragraphRange, text, textCheckingOptions)); + return adoptRef(new SpellCheckRequest(unrequestedSequence, checkingRange, paragraphRange, text, textCheckingOptions, processType)); } @@ -145,7 +146,7 @@ void SpellChecker::invokeRequest(PassRefPtr<SpellCheckRequest> request) ASSERT(!m_processingRequest); m_processingRequest = request; - client()->requestCheckingOfString(this, m_processingRequest->sequence(), m_processingRequest->mask(), m_processingRequest->text()); + client()->requestCheckingOfString(this, m_processingRequest->textCheckingRequest()); } void SpellChecker::enqueueRequest(PassRefPtr<SpellCheckRequest> request) diff --git a/Source/WebCore/editing/SpellChecker.h b/Source/WebCore/editing/SpellChecker.h index 20306da1a..07f51e431 100644 --- a/Source/WebCore/editing/SpellChecker.h +++ b/Source/WebCore/editing/SpellChecker.h @@ -46,10 +46,12 @@ struct TextCheckingResult; class SpellCheckRequest : public RefCounted<SpellCheckRequest> { public: - SpellCheckRequest(int sequence, PassRefPtr<Range> checkingRange, PassRefPtr<Range> paragraphRange, const String&, TextCheckingTypeMask); + SpellCheckRequest(int sequence, PassRefPtr<Range> checkingRange, PassRefPtr<Range> paragraphRange, const String&, TextCheckingTypeMask, TextCheckingProcessType); ~SpellCheckRequest(); - static PassRefPtr<SpellCheckRequest> create(TextCheckingTypeMask, PassRefPtr<Range> checkingRange, PassRefPtr<Range> paragraphRange); + static PassRefPtr<SpellCheckRequest> create(TextCheckingTypeMask, TextCheckingProcessType, PassRefPtr<Range> checkingRange, PassRefPtr<Range> paragraphRange); + + TextCheckingRequest textCheckingRequest() const; void setSequence(int sequence) { m_sequence = sequence; } int sequence() const { return m_sequence; } @@ -57,14 +59,15 @@ public: PassRefPtr<Range> paragraphRange() const { return m_paragraphRange; } const String& text() const { return m_text; } TextCheckingTypeMask mask() const { return m_mask; } + TextCheckingProcessType processType() const { return m_processType; } PassRefPtr<Element> rootEditableElement() const { return m_rootEditableElement; } private: - int m_sequence; - RefPtr<Range> m_checkingRange; - RefPtr<Range> m_paragraphRange; String m_text; TextCheckingTypeMask m_mask; + TextCheckingProcessType m_processType; + RefPtr<Range> m_checkingRange; + RefPtr<Range> m_paragraphRange; RefPtr<Element> m_rootEditableElement; }; @@ -109,6 +112,11 @@ private: RequestQueue m_requestQueue; }; +inline TextCheckingRequest SpellCheckRequest::textCheckingRequest() const +{ + return TextCheckingRequest(m_sequence, m_text, m_mask, m_processType); +} + } // namespace WebCore #endif // SpellChecker_h diff --git a/Source/WebCore/editing/TextIterator.cpp b/Source/WebCore/editing/TextIterator.cpp index c1c79f28a..aaeca4f9a 100644 --- a/Source/WebCore/editing/TextIterator.cpp +++ b/Source/WebCore/editing/TextIterator.cpp @@ -487,25 +487,20 @@ bool TextIterator::handleTextNode() return true; } - if (!renderer->firstTextBox() && str.length() > 0) { - if (!m_handledFirstLetter && renderer->isTextFragment()) { - handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); - if (m_firstLetterText) { - handleTextBox(); - return false; - } - } + if (renderer->firstTextBox()) + m_textBox = renderer->firstTextBox(); + + bool shouldHandleFirstLetter = !m_handledFirstLetter && renderer->isTextFragment() && !m_offset; + if (shouldHandleFirstLetter) + handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); + + if (!renderer->firstTextBox() && str.length() > 0 && !shouldHandleFirstLetter) { if (renderer->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) return false; m_lastTextNodeEndedWithCollapsedSpace = true; // entire block is collapsed space return true; } - - m_textBox = renderer->firstTextBox(); - if (!m_handledFirstLetter && renderer->isTextFragment() && !m_offset) - handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); - if (m_firstLetterText) renderer = m_firstLetterText; @@ -562,6 +557,7 @@ void TextIterator::handleTextBox() nextTextBox = m_sortedTextBoxes[m_sortedTextBoxesPosition + 1]; } else nextTextBox = m_textBox->nextTextBox(); + ASSERT(!nextTextBox || nextTextBox->renderer() == renderer); if (runStart < runEnd) { // Handle either a single newline character (which becomes a space), @@ -630,6 +626,7 @@ void TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer) m_handledFirstLetter = true; m_remainingTextBox = m_textBox; m_textBox = firstLetter->firstTextBox(); + m_sortedTextBoxes.clear(); m_firstLetterText = firstLetter; } } diff --git a/Source/WebCore/editing/htmlediting.cpp b/Source/WebCore/editing/htmlediting.cpp index 28cc029d0..07046100e 100644 --- a/Source/WebCore/editing/htmlediting.cpp +++ b/Source/WebCore/editing/htmlediting.cpp @@ -1033,7 +1033,7 @@ bool lineBreakExistsAtPosition(const Position& position) if (!position.anchorNode()->isTextNode() || !position.anchorNode()->renderer()->style()->preserveNewline()) return false; - Text* textNode = static_cast<Text*>(position.anchorNode()); + Text* textNode = toText(position.anchorNode()); unsigned offset = position.offsetInContainerNode(); return offset < textNode->length() && textNode->data()[offset] == '\n'; } @@ -1072,31 +1072,24 @@ VisibleSelection selectionForParagraphIteration(const VisibleSelection& original // opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllVisiblePositions mode needs to be fixed, // or these functions need to be changed to iterate using actual VisiblePositions. // FIXME: Deploy these functions everywhere that TextIterators are used to convert between VisiblePositions and indices. -int indexForVisiblePosition(const VisiblePosition& visiblePosition, Element **scope) +int indexForVisiblePosition(const VisiblePosition& visiblePosition, RefPtr<Element>& scope) { if (visiblePosition.isNull()) return 0; - + Position p(visiblePosition.deepEquivalent()); Document* document = p.anchorNode()->document(); - - Element* root; Node* shadowRoot = p.anchorNode()->shadowTreeRootNode(); - + if (shadowRoot) { // Use the shadow root for form elements, since TextIterators will not enter shadow content. ASSERT(shadowRoot->isElementNode()); - root = static_cast<Element*>(shadowRoot); + scope = static_cast<Element*>(shadowRoot); } else - root = document->documentElement(); - - if (scope) { - ASSERT(!*scope); - *scope = root; - } - - RefPtr<Range> range = Range::create(document, firstPositionInNode(root), p.parentAnchoredEquivalent()); - + scope = document->documentElement(); + + RefPtr<Range> range = Range::create(document, firstPositionInNode(scope.get()), p.parentAnchoredEquivalent()); + return TextIterator::rangeLength(range.get(), true); } diff --git a/Source/WebCore/editing/htmlediting.h b/Source/WebCore/editing/htmlediting.h index 0f2d1bdc0..abb49e312 100644 --- a/Source/WebCore/editing/htmlediting.h +++ b/Source/WebCore/editing/htmlediting.h @@ -180,7 +180,7 @@ bool lineBreakExistsAtVisiblePosition(const VisiblePosition&); int comparePositions(const VisiblePosition&, const VisiblePosition&); -int indexForVisiblePosition(const VisiblePosition&, Element **scope); +int indexForVisiblePosition(const VisiblePosition&, RefPtr<Element>& scope); VisiblePosition visiblePositionForIndex(int index, Element *scope); // ------------------------------------------------------------------------- diff --git a/Source/WebCore/editing/mac/EditorMac.mm b/Source/WebCore/editing/mac/EditorMac.mm index 423924fa4..2f5833674 100644 --- a/Source/WebCore/editing/mac/EditorMac.mm +++ b/Source/WebCore/editing/mac/EditorMac.mm @@ -37,6 +37,8 @@ #import "FrameView.h" #import "HTMLNames.h" #import "Pasteboard.h" +#import "PasteboardStrategy.h" +#import "PlatformStrategies.h" #import "RenderBlock.h" #import "RuntimeApplicationChecks.h" #import "Sound.h" @@ -49,7 +51,7 @@ using namespace HTMLNames; PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy, Frame* frame) { return ClipboardMac::create(Clipboard::CopyAndPaste, - policy == ClipboardWritable ? [NSPasteboard pasteboardWithUniqueName] : [NSPasteboard generalPasteboard], policy, frame); + policy == ClipboardWritable ? platformStrategies()->pasteboardStrategy()->uniqueName() : String(NSGeneralPboard), policy, frame); } void Editor::showFontPanel() @@ -289,11 +291,8 @@ void Editor::takeFindStringFromSelection() void Editor::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes) { - RetainPtr<NSMutableArray> types(AdoptNS, [[NSMutableArray alloc] init]); - for (size_t i = 0; i < pasteboardTypes.size(); ++i) - [types.get() addObject:pasteboardTypes[i]]; Pasteboard pasteboard(pasteboardName); - pasteboard.writeSelectionForTypes(types.get(), selectedRange().get(), true, m_frame); + pasteboard.writeSelectionForTypes(pasteboardTypes, selectedRange().get(), true, m_frame); } void Editor::readSelectionFromPasteboard(const String& pasteboardName) diff --git a/Source/WebCore/editing/markup.cpp b/Source/WebCore/editing/markup.cpp index c9a0e78dd..c0c0bf4db 100644 --- a/Source/WebCore/editing/markup.cpp +++ b/Source/WebCore/editing/markup.cpp @@ -30,7 +30,6 @@ #include "markup.h" #include "CDATASection.h" -#include "CSSComputedStyleDeclaration.h" #include "CSSPrimitiveValue.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" diff --git a/Source/WebCore/editing/visible_units.cpp b/Source/WebCore/editing/visible_units.cpp index ece6f233f..db8925946 100644 --- a/Source/WebCore/editing/visible_units.cpp +++ b/Source/WebCore/editing/visible_units.cpp @@ -361,7 +361,7 @@ static VisiblePosition startPositionForLine(const VisiblePosition& c, LineEndpoi } } - return startNode->isTextNode() ? Position(static_cast<Text*>(startNode), toInlineTextBox(startBox)->start()) + return startNode->isTextNode() ? Position(toText(startNode), toInlineTextBox(startBox)->start()) : positionBeforeNode(startNode); } @@ -441,7 +441,7 @@ static VisiblePosition endPositionForLine(const VisiblePosition& c, LineEndpoint int endOffset = endTextBox->start(); if (!endTextBox->isLineBreak()) endOffset += endTextBox->len(); - pos = Position(static_cast<Text*>(endNode), endOffset); + pos = Position(toText(endNode), endOffset); } else pos = positionAfterNode(endNode); @@ -545,7 +545,7 @@ static inline IntPoint absoluteLineDirectionPointToLocalPointInBlock(RootInlineB RenderBlock* containingBlock = root->block(); FloatPoint absoluteBlockPoint = containingBlock->localToAbsolute(FloatPoint()); if (containingBlock->hasOverflowClip()) - absoluteBlockPoint -= containingBlock->layer()->scrolledContentOffset(); + absoluteBlockPoint -= containingBlock->scrolledContentOffset(); if (root->block()->isHorizontalWritingMode()) return IntPoint(lineDirectionPoint - absoluteBlockPoint.x(), root->blockDirectionPointInLine()); @@ -834,7 +834,7 @@ VisiblePosition startOfParagraph(const VisiblePosition& c, EditingBoundaryCrossi i = max(0, o); while (--i >= 0) { if (chars[i] == '\n') - return VisiblePosition(Position(static_cast<Text*>(n), i + 1), DOWNSTREAM); + return VisiblePosition(Position(toText(n), i + 1), DOWNSTREAM); } } node = n; @@ -910,7 +910,7 @@ VisiblePosition endOfParagraph(const VisiblePosition &c, EditingBoundaryCrossing int o = n == startNode ? offset : 0; for (int i = o; i < length; ++i) { if (chars[i] == '\n') - return VisiblePosition(Position(static_cast<Text*>(n), i), DOWNSTREAM); + return VisiblePosition(Position(toText(n), i), DOWNSTREAM); } } node = n; |