diff options
author | Iain Merrick <husky@google.com> | 2010-08-19 17:55:56 +0100 |
---|---|---|
committer | Iain Merrick <husky@google.com> | 2010-08-23 11:05:40 +0100 |
commit | f486d19d62f1bc33246748b14b14a9dfa617b57f (patch) | |
tree | 195485454c93125455a30e553a73981c3816144d /WebCore/editing | |
parent | 6ba0b43722d16bc295606bec39f396f596e4fef1 (diff) | |
download | external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.zip external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.tar.gz external_webkit-f486d19d62f1bc33246748b14b14a9dfa617b57f.tar.bz2 |
Merge WebKit at r65615 : Initial merge by git.
Change-Id: Ifbf384f4531e3b58475a662e38195c2d9152ae79
Diffstat (limited to 'WebCore/editing')
-rw-r--r-- | WebCore/editing/ApplyStyleCommand.cpp | 142 | ||||
-rw-r--r-- | WebCore/editing/ApplyStyleCommand.h | 7 | ||||
-rw-r--r-- | WebCore/editing/CompositeEditCommand.cpp | 35 | ||||
-rw-r--r-- | WebCore/editing/DeleteSelectionCommand.cpp | 3 | ||||
-rw-r--r-- | WebCore/editing/Editor.cpp | 26 | ||||
-rw-r--r-- | WebCore/editing/Editor.h | 1 | ||||
-rw-r--r-- | WebCore/editing/EditorCommand.cpp | 2 | ||||
-rw-r--r-- | WebCore/editing/InsertTextCommand.cpp | 2 | ||||
-rw-r--r-- | WebCore/editing/TextIterator.cpp | 27 | ||||
-rw-r--r-- | WebCore/editing/TypingCommand.cpp | 8 | ||||
-rw-r--r-- | WebCore/editing/markup.cpp | 108 |
11 files changed, 201 insertions, 160 deletions
diff --git a/WebCore/editing/ApplyStyleCommand.cpp b/WebCore/editing/ApplyStyleCommand.cpp index a9d1509..bfbfab8 100644 --- a/WebCore/editing/ApplyStyleCommand.cpp +++ b/WebCore/editing/ApplyStyleCommand.cpp @@ -1311,6 +1311,9 @@ bool ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration* style, HTMLEl } } + if (mode == RemoveNone) + return removed; + // No need to serialize <foo style=""> if we just removed the last css property if (decl->isEmpty()) removeNodeAttribute(elem, styleAttr); @@ -1321,24 +1324,17 @@ bool ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclaration* style, HTMLEl return removed; } -static bool hasTextDecorationProperty(Node *node) +HTMLElement* ApplyStyleCommand::highestAncestorWithConflictingInlineStyle(CSSMutableStyleDeclaration* style, Node* node) { - if (!node->isElementNode()) - return false; - - RefPtr<CSSValue> value = computedStyle(node)->getPropertyCSSValue(CSSPropertyTextDecoration, DoNotUpdateLayout); - return value && !equalIgnoringCase(value->cssText(), "none"); -} + if (!node) + return 0; -static Node* highestAncestorWithTextDecoration(Node *node) -{ - ASSERT(node); - Node* result = 0; + HTMLElement* result = 0; Node* unsplittableElement = unsplittableElementForPosition(Position(node, 0)); for (Node *n = node; n; n = n->parentNode()) { - if (hasTextDecorationProperty(n)) - result = n; + if (n->isHTMLElement() && shouldRemoveInlineStyleFromElement(style, static_cast<HTMLElement*>(n))) + result = static_cast<HTMLElement*>(n); // Should stop at the editable root (cannot cross editing boundary) and // also stop at the unsplittable element to be consistent with other UAs if (n == unsplittableElement) @@ -1348,7 +1344,7 @@ static Node* highestAncestorWithTextDecoration(Node *node) return result; } -PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::extractTextDecorationStyle(Node* node) +PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::extractInlineStyleToPushDown(Node* node, const Vector<int>& properties) { ASSERT(node); ASSERT(node->isElementNode()); @@ -1362,72 +1358,108 @@ PassRefPtr<CSSMutableStyleDeclaration> ApplyStyleCommand::extractTextDecorationS if (!style) return 0; - int properties[1] = { CSSPropertyTextDecoration }; - RefPtr<CSSMutableStyleDeclaration> textDecorationStyle = style->copyPropertiesInSet(properties, 1); + style = style->copyPropertiesInSet(properties.data(), properties.size()); + + for (size_t i = 0; i < properties.size(); i++) { + RefPtr<CSSValue> property = style->getPropertyCSSValue(properties[i]); + if (property) + removeCSSProperty(element, static_cast<CSSPropertyID>(properties[i])); + } - RefPtr<CSSValue> property = style->getPropertyCSSValue(CSSPropertyTextDecoration); - if (property && !equalIgnoringCase(property->cssText(), "none")) - removeCSSProperty(element, CSSPropertyTextDecoration); + if (element->inlineStyleDecl() && element->inlineStyleDecl()->isEmpty()) + removeNodeAttribute(element, styleAttr); - return textDecorationStyle.release(); + if (isSpanWithoutAttributesOrUnstyleStyleSpan(element)) + removeNodePreservingChildren(element); + + return style.release(); } -void ApplyStyleCommand::applyTextDecorationStyle(Node *node, CSSMutableStyleDeclaration *style) +void ApplyStyleCommand::applyInlineStyleToPushDown(Node* node, CSSMutableStyleDeclaration* style) { ASSERT(node); - if (!style || style->cssText().isEmpty()) + if (!style || !style->length() || !node->renderer()) return; - StyleChange styleChange(style, Position(node, 0)); - if (styleChange.cssStyle().length()) { - if (node->isTextNode()) { - RefPtr<HTMLElement> styleSpan = createStyleSpanElement(document()); - surroundNodeRangeWithElement(node, node, styleSpan.get()); - node = styleSpan.get(); - } + // Since addInlineStyleIfNeeded can't add styles to block-flow render objects, add style attribute instead. + // FIXME: applyInlineStyleToRange should be used here instead. + if ((node->renderer()->isBlockFlow() || node->childNodeCount()) && node->isHTMLElement()) { + HTMLElement* element = static_cast<HTMLElement*>(node); + CSSMutableStyleDeclaration* existingInlineStyle = element->inlineStyleDecl(); + + // Avoid overriding existing styles of node + if (existingInlineStyle) { + RefPtr<CSSMutableStyleDeclaration> newInlineStyle = existingInlineStyle->copy(); + CSSMutableStyleDeclaration::const_iterator end = style->end(); + for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) { + ExceptionCode ec; + if (!existingInlineStyle->getPropertyCSSValue(it->id())) + newInlineStyle->setProperty(it->id(), it->value()->cssText(), it->isImportant(), ec); + + // text-decorations adds up + if (it->id() == CSSPropertyTextDecoration) { + ASSERT(it->value()->isValueList()); + RefPtr<CSSValue> textDecoration = newInlineStyle->getPropertyCSSValue(CSSPropertyTextDecoration); + if (textDecoration) { + ASSERT(textDecoration->isValueList()); + CSSValueList* textDecorationOfInlineStyle = static_cast<CSSValueList*>(textDecoration.get()); + CSSValueList* textDecorationOfStyleApplied = static_cast<CSSValueList*>(it->value()); + + DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, underline, (CSSPrimitiveValue::createIdentifier(CSSValueUnderline))); + DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, lineThrough, (CSSPrimitiveValue::createIdentifier(CSSValueLineThrough))); + + if (textDecorationOfStyleApplied->hasValue(underline.get()) && !textDecorationOfInlineStyle->hasValue(underline.get())) + textDecorationOfInlineStyle->append(underline.get()); + + if (textDecorationOfStyleApplied->hasValue(lineThrough.get()) && !textDecorationOfInlineStyle->hasValue(lineThrough.get())) + textDecorationOfInlineStyle->append(lineThrough.get()); + } + } + } - if (!node->isElementNode()) - return; + setNodeAttribute(element, styleAttr, newInlineStyle->cssText()); + } else + setNodeAttribute(element, styleAttr, style->cssText()); - HTMLElement *element = static_cast<HTMLElement *>(node); - String cssText = styleChange.cssStyle(); - CSSMutableStyleDeclaration *decl = element->inlineStyleDecl(); - if (decl) - cssText += decl->cssText(); - setNodeAttribute(element, styleAttr, cssText); + return; } - if (styleChange.applyUnderline()) - surroundNodeRangeWithElement(node, node, createHTMLElement(document(), uTag)); + if (node->renderer()->isText() && static_cast<RenderText*>(node->renderer())->isAllCollapsibleWhitespace()) + return; - if (styleChange.applyLineThrough()) - surroundNodeRangeWithElement(node, node, createHTMLElement(document(), sTag)); + // FIXME: addInlineStyleIfNeeded may override the style of node + addInlineStyleIfNeeded(style, node, node); } -void ApplyStyleCommand::pushDownTextDecorationStyleAroundNode(Node* targetNode) +void ApplyStyleCommand::pushDownInlineStyleAroundNode(CSSMutableStyleDeclaration* style, Node* targetNode) { - ASSERT(targetNode); - Node* highestAncestor = highestAncestorWithTextDecoration(targetNode); + HTMLElement* highestAncestor = highestAncestorWithConflictingInlineStyle(style, targetNode); if (!highestAncestor) return; + Vector<int> properties; + CSSMutableStyleDeclaration::const_iterator end = style->end(); + for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) + properties.append(it->id()); + // The outer loop is traversing the tree vertically from highestAncestor to targetNode Node* current = highestAncestor; while (current != targetNode) { ASSERT(current); + ASSERT(current->isHTMLElement()); ASSERT(current->contains(targetNode)); - RefPtr<CSSMutableStyleDeclaration> decoration = extractTextDecorationStyle(current); + Node* child = current->firstChild(); + RefPtr<CSSMutableStyleDeclaration> styleToPushDown = extractInlineStyleToPushDown(current, properties); // The inner loop will go through children on each level - Node* child = current->firstChild(); while (child) { Node* nextChild = child->nextSibling(); // Apply text decoration to all nodes containing targetNode and their siblings but NOT to targetNode if (child != targetNode) - applyTextDecorationStyle(child, decoration.get()); - + applyInlineStyleToPushDown(child, styleToPushDown.get()); + // We found the next node for the outer loop (contains targetNode) // When reached targetNode, stop the outer loop upon the completion of the current inner loop if (child == targetNode || child->contains(targetNode)) @@ -1447,19 +1479,23 @@ void ApplyStyleCommand::removeInlineStyle(PassRefPtr<CSSMutableStyleDeclaration> ASSERT(comparePositions(start, end) <= 0); RefPtr<CSSValue> textDecorationSpecialProperty = style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect); - if (textDecorationSpecialProperty) { - pushDownTextDecorationStyleAroundNode(start.downstream().node()); - pushDownTextDecorationStyleAroundNode(end.upstream().node()); style = style->copy(); style->setProperty(CSSPropertyTextDecoration, textDecorationSpecialProperty->cssText(), style->getPropertyPriority(CSSPropertyWebkitTextDecorationsInEffect)); } + Position pushDownStart = start.downstream(); + Position pushDownEnd = end.upstream(); + pushDownInlineStyleAroundNode(style.get(), pushDownStart.node()); + pushDownInlineStyleAroundNode(style.get(), pushDownEnd.node()); + // The s and e variables store the positions used to set the ending selection after style removal // takes place. This will help callers to recognize when either the start node or the end node // are removed from the document during the work of this function. - Position s = start; - Position e = end; + // If pushDownInlineStyleAroundNode has pruned start.node() or end.node(), + // use pushDownStart or pushDownEnd instead, which pushDownInlineStyleAroundNode won't prune. + Position s = start.isNull() || start.isOrphan() ? pushDownStart : start; + Position e = end.isNull() || end.isOrphan() ? pushDownEnd : end; Node* node = start.node(); while (node) { diff --git a/WebCore/editing/ApplyStyleCommand.h b/WebCore/editing/ApplyStyleCommand.h index 86c24da..f4ecc7c 100644 --- a/WebCore/editing/ApplyStyleCommand.h +++ b/WebCore/editing/ApplyStyleCommand.h @@ -78,12 +78,13 @@ private: bool removeHTMLFontStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveAttributesAndElements); bool removeHTMLBidiEmbeddingStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveAttributesAndElements); bool removeCSSStyle(CSSMutableStyleDeclaration*, HTMLElement*, InlineStyleRemovalMode = RemoveAttributesAndElements); + HTMLElement* highestAncestorWithConflictingInlineStyle(CSSMutableStyleDeclaration*, Node*); + PassRefPtr<CSSMutableStyleDeclaration> extractInlineStyleToPushDown(Node*, const Vector<int>&); + void applyInlineStyleToPushDown(Node*, CSSMutableStyleDeclaration *style); + void pushDownInlineStyleAroundNode(CSSMutableStyleDeclaration*, Node*); void removeInlineStyle(PassRefPtr<CSSMutableStyleDeclaration>, const Position& start, const Position& end); bool nodeFullySelected(Node*, const Position& start, const Position& end) const; bool nodeFullyUnselected(Node*, const Position& start, const Position& end) const; - PassRefPtr<CSSMutableStyleDeclaration> extractTextDecorationStyle(Node*); - void applyTextDecorationStyle(Node*, CSSMutableStyleDeclaration *style); - void pushDownTextDecorationStyleAroundNode(Node*); // style-application helpers void applyBlockStyle(CSSMutableStyleDeclaration*); diff --git a/WebCore/editing/CompositeEditCommand.cpp b/WebCore/editing/CompositeEditCommand.cpp index 5ec87d6..f50929a 100644 --- a/WebCore/editing/CompositeEditCommand.cpp +++ b/WebCore/editing/CompositeEditCommand.cpp @@ -294,24 +294,24 @@ void CompositeEditCommand::joinTextNodes(PassRefPtr<Text> text1, PassRefPtr<Text void CompositeEditCommand::inputText(const String& text, bool selectInsertedText) { - int offset = 0; - int length = text.length(); + unsigned offset = 0; + unsigned length = text.length(); RefPtr<Range> startRange = Range::create(document(), Position(document()->documentElement(), 0), endingSelection().start()); - int startIndex = TextIterator::rangeLength(startRange.get()); - int newline; + unsigned startIndex = TextIterator::rangeLength(startRange.get()); + size_t newline; do { newline = text.find('\n', offset); if (newline != offset) { RefPtr<InsertTextCommand> command = InsertTextCommand::create(document()); applyCommandToComposite(command); - int substringLength = newline == -1 ? length - offset : newline - offset; + int substringLength = newline == notFound ? length - offset : newline - offset; command->input(text.substring(offset, substringLength), false); } - if (newline != -1) + if (newline != notFound) insertLineBreak(); offset = newline + 1; - } while (newline != -1 && offset != length); + } while (newline != notFound && offset != length); if (selectInsertedText) { RefPtr<Range> selectedRange = TextIterator::rangeFromLocationAndLength(document()->documentElement(), startIndex, length); @@ -489,7 +489,18 @@ void CompositeEditCommand::deleteInsignificantText(PassRefPtr<Text> textNode, un if (!textRenderer) return; - InlineTextBox* box = textRenderer->firstTextBox(); + Vector<InlineTextBox*> sortedTextBoxes; + size_t sortedTextBoxesPosition = 0; + + for (InlineTextBox* textBox = textRenderer->firstTextBox(); textBox; textBox = textBox->nextTextBox()) + sortedTextBoxes.append(textBox); + + // If there is mixed directionality text, the boxes can be out of order, + // (like Arabic with embedded LTR), so sort them first. + if (textRenderer->containsReversedText()) + std::sort(sortedTextBoxes.begin(), sortedTextBoxes.end(), InlineTextBox::compareByStart); + InlineTextBox* box = sortedTextBoxes.isEmpty() ? 0 : sortedTextBoxes[sortedTextBoxesPosition]; + if (!box) { // whole text node is empty removeNode(textNode); @@ -526,8 +537,12 @@ void CompositeEditCommand::deleteInsignificantText(PassRefPtr<Text> textNode, un } prevBox = box; - if (box) - box = box->nextTextBox(); + if (box) { + if (++sortedTextBoxesPosition < sortedTextBoxes.size()) + box = sortedTextBoxes[sortedTextBoxesPosition]; + else + box = 0; + } } if (!str.isNull()) { diff --git a/WebCore/editing/DeleteSelectionCommand.cpp b/WebCore/editing/DeleteSelectionCommand.cpp index c37b0fc..5e025eb 100644 --- a/WebCore/editing/DeleteSelectionCommand.cpp +++ b/WebCore/editing/DeleteSelectionCommand.cpp @@ -630,7 +630,8 @@ void DeleteSelectionCommand::mergeParagraphs() // moveParagraphs will insert placeholders if it removes blocks that would require their use, don't let block // removals that it does cause the insertion of *another* placeholder. bool needPlaceholder = m_needPlaceholder; - moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination); + bool paragraphToMergeIsEmpty = (startOfParagraphToMove == endOfParagraphToMove); + moveParagraph(startOfParagraphToMove, endOfParagraphToMove, mergeDestination, false, !paragraphToMergeIsEmpty); m_needPlaceholder = needPlaceholder; // The endingPosition was likely clobbered by the move, so recompute it (moveParagraph selects the moved paragraph). m_endingPosition = endingSelection().start(); diff --git a/WebCore/editing/Editor.cpp b/WebCore/editing/Editor.cpp index 7a1ad4d..196384a 100644 --- a/WebCore/editing/Editor.cpp +++ b/WebCore/editing/Editor.cpp @@ -130,6 +130,11 @@ void Editor::handleInputMethodKeydown(KeyboardEvent* event) bool Editor::handleTextEvent(TextEvent* event) { + // Default event handling for Drag and Drop will be handled by DragController + // so we leave the event for it. + if (event->isDrop()) + return false; + if (event->isPaste()) { if (event->pastingFragment()) replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle()); @@ -762,14 +767,20 @@ bool Editor::dispatchCPPEvent(const AtomicString &eventType, ClipboardAccessPoli return !noDefaultProcessing; } -Node* Editor::findEventTargetFromSelection() const +Node* Editor::findEventTargetFrom(const VisibleSelection& selection) const { - Node* target = m_frame->selection()->start().element(); + Node* target = selection.start().element(); if (!target) target = m_frame->document()->body(); if (!target) return 0; return target->shadowAncestorNode(); + +} + +Node* Editor::findEventTargetFromSelection() const +{ + return findEventTargetFrom(m_frame->selection()->selection()); } void Editor::applyStyle(CSSStyleDeclaration* style, EditAction editingAction) @@ -1514,10 +1525,13 @@ void Editor::setComposition(const String& text, const Vector<CompositionUnderlin if (!text.isEmpty()) { TypingCommand::insertText(m_frame->document(), text, true, true); - Node* baseNode = m_frame->selection()->base().node(); - unsigned baseOffset = m_frame->selection()->base().deprecatedEditingOffset(); - Node* extentNode = m_frame->selection()->extent().node(); - unsigned extentOffset = m_frame->selection()->extent().deprecatedEditingOffset(); + // Find out what node has the composition now. + Position base = m_frame->selection()->base().downstream(); + Position extent = m_frame->selection()->extent(); + Node* baseNode = base.node(); + unsigned baseOffset = base.deprecatedEditingOffset(); + Node* extentNode = extent.node(); + unsigned extentOffset = extent.deprecatedEditingOffset(); if (baseNode && baseNode == extentNode && baseNode->isTextNode() && baseOffset + text.length() == extentOffset) { m_compositionNode = static_cast<Text*>(baseNode); diff --git a/WebCore/editing/Editor.h b/WebCore/editing/Editor.h index 13e6df5..06e7513 100644 --- a/WebCore/editing/Editor.h +++ b/WebCore/editing/Editor.h @@ -299,6 +299,7 @@ public: void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle); void pasteAsPlainText(const String&, bool smartReplace); + Node* findEventTargetFrom(const VisibleSelection& selection) const; private: Frame* m_frame; OwnPtr<DeleteButtonController> m_deleteButtonController; diff --git a/WebCore/editing/EditorCommand.cpp b/WebCore/editing/EditorCommand.cpp index 1a77642..eb89593 100644 --- a/WebCore/editing/EditorCommand.cpp +++ b/WebCore/editing/EditorCommand.cpp @@ -28,7 +28,6 @@ #include "config.h" #include "Editor.h" -#include "AtomicString.h" #include "CSSComputedStyleDeclaration.h" #include "CSSMutableStyleDeclaration.h" #include "CSSPropertyNames.h" @@ -58,6 +57,7 @@ #include "UnlinkCommand.h" #include "htmlediting.h" #include "markup.h" +#include <wtf/text/AtomicString.h> namespace WebCore { diff --git a/WebCore/editing/InsertTextCommand.cpp b/WebCore/editing/InsertTextCommand.cpp index f10d71b..52eb12f 100644 --- a/WebCore/editing/InsertTextCommand.cpp +++ b/WebCore/editing/InsertTextCommand.cpp @@ -109,7 +109,7 @@ bool InsertTextCommand::performTrivialReplace(const String& text, bool selectIns void InsertTextCommand::input(const String& text, bool selectInsertedText) { - ASSERT(text.find('\n') == -1); + ASSERT(text.find('\n') == notFound); if (endingSelection().isNone()) return; diff --git a/WebCore/editing/TextIterator.cpp b/WebCore/editing/TextIterator.cpp index 9589bff..39013c1 100644 --- a/WebCore/editing/TextIterator.cpp +++ b/WebCore/editing/TextIterator.cpp @@ -442,11 +442,6 @@ void TextIterator::advance() } } -static inline bool compareBoxStart(const InlineTextBox* first, const InlineTextBox* second) -{ - return first->start() < second->start(); -} - bool TextIterator::handleTextNode() { if (m_fullyClippedStack.top()) @@ -507,7 +502,7 @@ bool TextIterator::handleTextNode() for (InlineTextBox* textBox = renderer->firstTextBox(); textBox; textBox = textBox->nextTextBox()) { m_sortedTextBoxes.append(textBox); } - std::sort(m_sortedTextBoxes.begin(), m_sortedTextBoxes.end(), compareBoxStart); + std::sort(m_sortedTextBoxes.begin(), m_sortedTextBoxes.end(), InlineTextBox::compareByStart); m_sortedTextBoxesPosition = 0; } @@ -526,11 +521,11 @@ void TextIterator::handleTextBox() return; } String str = renderer->text(); - int start = m_offset; - int end = (m_node == m_endContainer) ? m_endOffset : INT_MAX; + unsigned start = m_offset; + unsigned end = (m_node == m_endContainer) ? m_endOffset : UINT_MAX; while (m_textBox) { - int textBoxStart = m_textBox->start(); - int runStart = max(textBoxStart, start); + unsigned textBoxStart = m_textBox->start(); + unsigned runStart = max(textBoxStart, start); // Check for collapsed space at the start of this run. InlineTextBox* firstTextBox = renderer->containsReversedText() ? m_sortedTextBoxes[0] : renderer->firstTextBox(); @@ -546,8 +541,8 @@ void TextIterator::handleTextBox() emitCharacter(' ', m_node, 0, runStart, runStart); return; } - int textBoxEnd = textBoxStart + m_textBox->len(); - int runEnd = min(textBoxEnd, end); + unsigned textBoxEnd = textBoxStart + m_textBox->len(); + unsigned runEnd = min(textBoxEnd, end); // Determine what the next text box will be, but don't advance yet InlineTextBox* nextTextBox = 0; @@ -565,8 +560,8 @@ void TextIterator::handleTextBox() emitCharacter(' ', m_node, 0, runStart, runStart + 1); m_offset = runStart + 1; } else { - int subrunEnd = str.find('\n', runStart); - if (subrunEnd == -1 || subrunEnd > runEnd) + size_t subrunEnd = str.find('\n', runStart); + if (subrunEnd == notFound || subrunEnd > runEnd) subrunEnd = runEnd; m_offset = subrunEnd; @@ -575,11 +570,11 @@ void TextIterator::handleTextBox() // If we are doing a subrun that doesn't go to the end of the text box, // come back again to finish handling this text box; don't advance to the next one. - if (m_positionEndOffset < textBoxEnd) + if (static_cast<unsigned>(m_positionEndOffset) < textBoxEnd) return; // Advance and return - int nextRunStart = nextTextBox ? nextTextBox->start() : str.length(); + unsigned nextRunStart = nextTextBox ? nextTextBox->start() : str.length(); if (nextRunStart > runEnd) m_lastTextNodeEndedWithCollapsedSpace = true; // collapsed space between runs or at the end m_textBox = nextTextBox; diff --git a/WebCore/editing/TypingCommand.cpp b/WebCore/editing/TypingCommand.cpp index 7680084..bab3111 100644 --- a/WebCore/editing/TypingCommand.cpp +++ b/WebCore/editing/TypingCommand.cpp @@ -332,9 +332,9 @@ void TypingCommand::insertText(const String &text, bool selectInsertedText) // an existing selection; at the moment they can either put the caret after what's inserted or // select what's inserted, but there's no way to "extend selection" to include both an old selection // that ends just before where we want to insert text and the newly inserted text. - int offset = 0; - int newline; - while ((newline = text.find('\n', offset)) != -1) { + unsigned offset = 0; + size_t newline; + while ((newline = text.find('\n', offset)) != notFound) { if (newline != offset) insertTextRunWithoutNewlines(text.substring(offset, newline - offset), false); insertParagraphSeparator(); @@ -343,7 +343,7 @@ void TypingCommand::insertText(const String &text, bool selectInsertedText) if (!offset) insertTextRunWithoutNewlines(text, selectInsertedText); else { - int length = text.length(); + unsigned length = text.length(); if (length != offset) insertTextRunWithoutNewlines(text.substring(offset, length - offset), selectInsertedText); } diff --git a/WebCore/editing/markup.cpp b/WebCore/editing/markup.cpp index 26989c3..b1ec07c 100644 --- a/WebCore/editing/markup.cpp +++ b/WebCore/editing/markup.cpp @@ -591,52 +591,6 @@ static void appendEndMarkup(Vector<UChar>& result, const Node* node) result.append('>'); } -class MarkupAccumulator { -public: - MarkupAccumulator(Node* nodeToSkip, Vector<Node*>* nodes) - : m_nodeToSkip(nodeToSkip) - , m_nodes(nodes) - { - } - - void appendMarkup(Node* startNode, EChildrenOnly, EAbsoluteURLs, const HashMap<AtomicStringImpl*, AtomicStringImpl*>* namespaces = 0); - - String takeResult() { return String::adopt(m_result); } - -private: - Vector<UChar> m_result; - Node* m_nodeToSkip; - Vector<Node*>* m_nodes; -}; - -// FIXME: Would be nice to do this in a non-recursive way. -void MarkupAccumulator::appendMarkup(Node* startNode, EChildrenOnly childrenOnly, EAbsoluteURLs absoluteURLs, const HashMap<AtomicStringImpl*, AtomicStringImpl*>* namespaces) -{ - if (startNode == m_nodeToSkip) - return; - - HashMap<AtomicStringImpl*, AtomicStringImpl*> namespaceHash; - if (namespaces) - namespaceHash = *namespaces; - - // start tag - if (!childrenOnly) { - if (m_nodes) - m_nodes->append(startNode); - appendStartMarkup(m_result, startNode, 0, DoNotAnnotateForInterchange, absoluteURLs, false, &namespaceHash); - } - - // children - if (!(startNode->document()->isHTMLDocument() && doesHTMLForbidEndTag(startNode))) { - for (Node* current = startNode->firstChild(); current; current = current->nextSibling()) - appendMarkup(current, IncludeNode, absoluteURLs, &namespaceHash); - } - - // end tag - if (!childrenOnly) - appendEndMarkup(m_result, startNode); -} - static void completeURLs(Node* node, const String& baseURL) { Vector<AttributeChange> changes; @@ -737,7 +691,8 @@ static bool shouldIncludeWrapperForFullySelectedRoot(Node* fullySelectedRoot, CS class MarkupAccumulatorWrapper { public: - MarkupAccumulatorWrapper() + MarkupAccumulatorWrapper(Vector<Node*>* nodes) + : m_nodes(nodes) { } @@ -746,11 +701,13 @@ public: postMarkups.append(s); } - void insertOpenTag(const Node* node, const Range* range, EAnnotateForInterchange annotate, EAbsoluteURLs absoluteURLs, bool convertBlocksToInlines = false, RangeFullySelectsNode rangeFullySelectsNode = DoesFullySelectNode) + void insertOpenTag(const Node* node, const Range* range, EAnnotateForInterchange annotate, EAbsoluteURLs absoluteURLs, bool convertBlocksToInlines = false, HashMap<AtomicStringImpl*, AtomicStringImpl*>* namespaces = 0, RangeFullySelectsNode rangeFullySelectsNode = DoesFullySelectNode) { Vector<UChar> result; - appendStartMarkup(result, node, range, annotate, absoluteURLs, convertBlocksToInlines, 0, rangeFullySelectsNode); + appendStartMarkup(result, node, range, annotate, absoluteURLs, convertBlocksToInlines, namespaces, rangeFullySelectsNode); postMarkups.append(String::adopt(result)); + if (m_nodes) + m_nodes->append(const_cast<Node*>(node)); } void insertEndTag(const Node* node) @@ -760,12 +717,14 @@ public: postMarkups.append(String::adopt(result)); } - void wrapWithNode(const Node* node, const Range* range, EAnnotateForInterchange annotate, EAbsoluteURLs absoluteURLs, bool convertBlocksToInlines = false, RangeFullySelectsNode rangeFullySelectsNode = DoesFullySelectNode) + void wrapWithNode(const Node* node, const Range* range, EAnnotateForInterchange annotate, EAbsoluteURLs absoluteURLs, bool convertBlocksToInlines = false, HashMap<AtomicStringImpl*, AtomicStringImpl*>* namespaces = 0, RangeFullySelectsNode rangeFullySelectsNode = DoesFullySelectNode) { Vector<UChar> result; - appendStartMarkup(result, node, range, annotate, absoluteURLs, convertBlocksToInlines, 0, rangeFullySelectsNode); + appendStartMarkup(result, node, range, annotate, absoluteURLs, convertBlocksToInlines, namespaces, rangeFullySelectsNode); preMarkups.append(String::adopt(result)); insertEndTag(node); + if (m_nodes) + m_nodes->append(const_cast<Node*>(node)); } void wrapWithStyleNode(CSSStyleDeclaration* style, Document* document, bool isBlock = false) @@ -814,11 +773,12 @@ public: } private: + Vector<Node*>* m_nodes; Vector<String> preMarkups; Vector<String> postMarkups; }; -static Node* serializeNodes(MarkupAccumulatorWrapper& accumulator, Node* startNode, Node* pastEnd, Vector<Node*>* nodes, const Range* range, EAnnotateForInterchange annotate, EAbsoluteURLs absoluteURLs) +static Node* serializeNodes(MarkupAccumulatorWrapper& accumulator, Node* startNode, Node* pastEnd, const Range* range, EAnnotateForInterchange annotate, EAbsoluteURLs absoluteURLs) { Vector<Node*> ancestorsToClose; Node* next; @@ -847,8 +807,6 @@ static Node* serializeNodes(MarkupAccumulatorWrapper& accumulator, Node* startNo } else { // Add the node to the markup if we're not skipping the descendants accumulator.insertOpenTag(n, range, annotate, absoluteURLs); - if (nodes) - nodes->append(n); // If node has no children, close the tag now. if (!n->childNodeCount()) { @@ -885,8 +843,6 @@ static Node* serializeNodes(MarkupAccumulatorWrapper& accumulator, Node* startNo // or b) ancestors that we never encountered during a pre-order traversal starting at startNode: ASSERT(startNode->isDescendantOf(parent)); accumulator.wrapWithNode(parent, range, annotate, absoluteURLs); - if (nodes) - nodes->append(parent); lastClosed = parent; } } @@ -932,7 +888,7 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc document->updateLayoutIgnorePendingStylesheets(); - MarkupAccumulatorWrapper accumulator; + MarkupAccumulatorWrapper accumulator(nodes); Node* pastEnd = updatedRange->pastLastNode(); Node* startNode = updatedRange->firstNode(); @@ -955,7 +911,7 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc } } - Node* lastClosed = serializeNodes(accumulator, startNode, pastEnd, nodes, range, annotate, absoluteURLs); + Node* lastClosed = serializeNodes(accumulator, startNode, pastEnd, range, annotate, absoluteURLs); // Include ancestors that aren't completely inside the range but are required to retain // the structure and appearance of the copied markup. @@ -1030,7 +986,7 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc } else { // Since this node and all the other ancestors are not in the selection we want to set RangeFullySelectsNode to DoesNotFullySelectNode // so that styles that affect the exterior of the node are not included. - accumulator.wrapWithNode(ancestor, updatedRange.get(), annotate, absoluteURLs, convertBlocksToInlines, DoesNotFullySelectNode); + accumulator.wrapWithNode(ancestor, updatedRange.get(), annotate, absoluteURLs, convertBlocksToInlines, 0, DoesNotFullySelectNode); } if (nodes) nodes->append(ancestor); @@ -1087,7 +1043,8 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc PassRefPtr<DocumentFragment> createFragmentFromMarkup(Document* document, const String& markup, const String& baseURL, FragmentScriptingPermission scriptingPermission) { - RefPtr<DocumentFragment> fragment = document->documentElement()->createContextualFragment(markup, scriptingPermission); + // FIXME: This should not use deprecatedCreateContextualFragment + RefPtr<DocumentFragment> fragment = document->documentElement()->deprecatedCreateContextualFragment(markup, scriptingPermission); if (fragment && !baseURL.isEmpty() && baseURL != blankURL() && baseURL != document->baseURL()) completeURLs(fragment.get(), baseURL); @@ -1095,6 +1052,27 @@ PassRefPtr<DocumentFragment> createFragmentFromMarkup(Document* document, const return fragment.release(); } +static void serializeNodesWithNamespaces(MarkupAccumulatorWrapper& accumulator, const Node* node, Node* nodeToSkip, EChildrenOnly childrenOnly, EAbsoluteURLs absoluteURLs, const HashMap<AtomicStringImpl*, AtomicStringImpl*>* namespaces) +{ + if (node == nodeToSkip) + return; + + HashMap<AtomicStringImpl*, AtomicStringImpl*> namespaceHash; + if (namespaces) + namespaceHash = *namespaces; + + if (!childrenOnly) + accumulator.insertOpenTag(node, 0, DoNotAnnotateForInterchange, absoluteURLs, false, &namespaceHash); + + if (!(node->document()->isHTMLDocument() && doesHTMLForbidEndTag(node))) { + for (Node* current = node->firstChild(); current; current = current->nextSibling()) + serializeNodesWithNamespaces(accumulator, current, nodeToSkip, IncludeNode, absoluteURLs, &namespaceHash); + } + + if (!childrenOnly) + accumulator.insertEndTag(node); +} + String createMarkup(const Node* node, EChildrenOnly childrenOnly, Vector<Node*>* nodes, EAbsoluteURLs absoluteURLs) { if (!node) @@ -1107,9 +1085,9 @@ String createMarkup(const Node* node, EChildrenOnly childrenOnly, Vector<Node*>* return ""; } - MarkupAccumulator accumulator(deleteButtonContainerElement, nodes); - accumulator.appendMarkup(const_cast<Node*>(node), childrenOnly, absoluteURLs); - return accumulator.takeResult(); + MarkupAccumulatorWrapper accumulator(nodes); + serializeNodesWithNamespaces(accumulator, node, deleteButtonContainerElement, childrenOnly, absoluteURLs, 0); + return accumulator.takeResults(); } static void fillContainerFromString(ContainerNode* paragraph, const String& string) @@ -1123,7 +1101,7 @@ static void fillContainerFromString(ContainerNode* paragraph, const String& stri return; } - ASSERT(string.find('\n') == -1); + ASSERT(string.find('\n') == notFound); Vector<String> tabList; string.split('\t', true, tabList); @@ -1206,7 +1184,7 @@ PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String } // A string with no newlines gets added inline, rather than being put into a paragraph. - if (string.find('\n') == -1) { + if (string.find('\n') == notFound) { fillContainerFromString(fragment.get(), string); return fragment.release(); } |