summaryrefslogtreecommitdiffstats
path: root/WebCore/editing
diff options
context:
space:
mode:
authorIain Merrick <husky@google.com>2010-08-19 17:55:56 +0100
committerIain Merrick <husky@google.com>2010-08-23 11:05:40 +0100
commitf486d19d62f1bc33246748b14b14a9dfa617b57f (patch)
tree195485454c93125455a30e553a73981c3816144d /WebCore/editing
parent6ba0b43722d16bc295606bec39f396f596e4fef1 (diff)
downloadexternal_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.cpp142
-rw-r--r--WebCore/editing/ApplyStyleCommand.h7
-rw-r--r--WebCore/editing/CompositeEditCommand.cpp35
-rw-r--r--WebCore/editing/DeleteSelectionCommand.cpp3
-rw-r--r--WebCore/editing/Editor.cpp26
-rw-r--r--WebCore/editing/Editor.h1
-rw-r--r--WebCore/editing/EditorCommand.cpp2
-rw-r--r--WebCore/editing/InsertTextCommand.cpp2
-rw-r--r--WebCore/editing/TextIterator.cpp27
-rw-r--r--WebCore/editing/TypingCommand.cpp8
-rw-r--r--WebCore/editing/markup.cpp108
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();
}