summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/editing
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-16 16:25:10 +0100
committerBen Murdoch <benm@google.com>2011-05-23 18:54:14 +0100
commitab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb (patch)
treedb769fadd053248f85db67434a5b275224defef7 /Source/WebCore/editing
parent52e2557aeb8477967e97fd24f20f8f407a10fa15 (diff)
downloadexternal_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.zip
external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.tar.gz
external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.tar.bz2
Merge WebKit at r76408: Initial merge by git.
Change-Id: I5b91decbd693ccbf5c1b8354b37cd68cc9a1ea53
Diffstat (limited to 'Source/WebCore/editing')
-rw-r--r--Source/WebCore/editing/ApplyStyleCommand.cpp4
-rw-r--r--Source/WebCore/editing/CompositeEditCommand.cpp12
-rw-r--r--Source/WebCore/editing/DeleteButtonController.h3
-rw-r--r--Source/WebCore/editing/DeleteSelectionCommand.cpp58
-rw-r--r--Source/WebCore/editing/Editor.cpp4
-rw-r--r--Source/WebCore/editing/EditorCommand.cpp8
-rw-r--r--Source/WebCore/editing/IndentOutdentCommand.cpp6
-rw-r--r--Source/WebCore/editing/InsertLineBreakCommand.cpp10
-rw-r--r--Source/WebCore/editing/InsertListCommand.cpp10
-rw-r--r--Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp11
-rw-r--r--Source/WebCore/editing/ReplaceSelectionCommand.cpp5
-rw-r--r--Source/WebCore/editing/SelectionController.cpp51
-rw-r--r--Source/WebCore/editing/SelectionController.h3
-rw-r--r--Source/WebCore/editing/SpellChecker.h3
-rw-r--r--Source/WebCore/editing/TextCheckingHelper.h3
-rw-r--r--Source/WebCore/editing/TextIterator.cpp11
-rw-r--r--Source/WebCore/editing/VisiblePosition.cpp8
-rw-r--r--Source/WebCore/editing/VisibleSelection.cpp12
-rw-r--r--Source/WebCore/editing/htmlediting.cpp75
-rw-r--r--Source/WebCore/editing/htmlediting.h3
-rw-r--r--Source/WebCore/editing/visible_units.cpp32
21 files changed, 159 insertions, 173 deletions
diff --git a/Source/WebCore/editing/ApplyStyleCommand.cpp b/Source/WebCore/editing/ApplyStyleCommand.cpp
index 7227d7b..39350b9 100644
--- a/Source/WebCore/editing/ApplyStyleCommand.cpp
+++ b/Source/WebCore/editing/ApplyStyleCommand.cpp
@@ -569,8 +569,8 @@ void ApplyStyleCommand::applyBlockStyle(CSSMutableStyleDeclaration *style)
// addBlockStyleIfNeeded may moveParagraphs, which can remove these endpoints.
// Calculate start and end indices from the start of the tree that they're in.
Node* scope = highestAncestor(visibleStart.deepEquivalent().node());
- RefPtr<Range> startRange = Range::create(document(), firstPositionInNode(scope), rangeCompliantEquivalent(visibleStart.deepEquivalent()));
- RefPtr<Range> endRange = Range::create(document(), firstPositionInNode(scope), rangeCompliantEquivalent(visibleEnd.deepEquivalent()));
+ RefPtr<Range> startRange = Range::create(document(), firstPositionInNode(scope), visibleStart.deepEquivalent().parentAnchoredEquivalent());
+ RefPtr<Range> endRange = Range::create(document(), firstPositionInNode(scope), visibleEnd.deepEquivalent().parentAnchoredEquivalent());
int startIndex = TextIterator::rangeLength(startRange.get(), true);
int endIndex = TextIterator::rangeLength(endRange.get(), true);
diff --git a/Source/WebCore/editing/CompositeEditCommand.cpp b/Source/WebCore/editing/CompositeEditCommand.cpp
index 9e1dfca..552ed79 100644
--- a/Source/WebCore/editing/CompositeEditCommand.cpp
+++ b/Source/WebCore/editing/CompositeEditCommand.cpp
@@ -159,7 +159,7 @@ void CompositeEditCommand::insertNodeAt(PassRefPtr<Node> insertChild, const Posi
ASSERT(isEditablePosition(editingPosition));
// For editing positions like [table, 0], insert before the table,
// likewise for replaced elements, brs, etc.
- Position p = rangeCompliantEquivalent(editingPosition);
+ Position p = editingPosition.parentAnchoredEquivalent();
Node* refChild = p.node();
int offset = p.deprecatedEditingOffset();
@@ -905,13 +905,13 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
startIndex = 0;
if (startInParagraph) {
- RefPtr<Range> startRange = Range::create(document(), rangeCompliantEquivalent(startOfParagraphToMove.deepEquivalent()), rangeCompliantEquivalent(visibleStart.deepEquivalent()));
+ RefPtr<Range> startRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleStart.deepEquivalent().parentAnchoredEquivalent());
startIndex = TextIterator::rangeLength(startRange.get(), true);
}
endIndex = 0;
if (endInParagraph) {
- RefPtr<Range> endRange = Range::create(document(), rangeCompliantEquivalent(startOfParagraphToMove.deepEquivalent()), rangeCompliantEquivalent(visibleEnd.deepEquivalent()));
+ RefPtr<Range> endRange = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), visibleEnd.deepEquivalent().parentAnchoredEquivalent());
endIndex = TextIterator::rangeLength(endRange.get(), true);
}
}
@@ -926,8 +926,8 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
Position end = endOfParagraphToMove.deepEquivalent().upstream();
// start and end can't be used directly to create a Range; they are "editing positions"
- Position startRangeCompliant = rangeCompliantEquivalent(start);
- Position endRangeCompliant = rangeCompliantEquivalent(end);
+ Position startRangeCompliant = start.parentAnchoredEquivalent();
+ Position endRangeCompliant = end.parentAnchoredEquivalent();
RefPtr<Range> range = Range::create(document(), startRangeCompliant.node(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.node(), endRangeCompliant.deprecatedEditingOffset());
// FIXME: This is an inefficient way to preserve style on nodes in the paragraph to move. It
@@ -974,7 +974,7 @@ void CompositeEditCommand::moveParagraphs(const VisiblePosition& startOfParagrap
updateLayout();
}
- RefPtr<Range> startToDestinationRange(Range::create(document(), firstPositionInNode(document()->documentElement()), rangeCompliantEquivalent(destination.deepEquivalent())));
+ RefPtr<Range> startToDestinationRange(Range::create(document(), firstPositionInNode(document()->documentElement()), destination.deepEquivalent().parentAnchoredEquivalent()));
destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(), true);
setEndingSelection(destination);
diff --git a/Source/WebCore/editing/DeleteButtonController.h b/Source/WebCore/editing/DeleteButtonController.h
index 1286c07..4d928c7 100644
--- a/Source/WebCore/editing/DeleteButtonController.h
+++ b/Source/WebCore/editing/DeleteButtonController.h
@@ -36,7 +36,8 @@ class HTMLElement;
class RenderObject;
class VisibleSelection;
-class DeleteButtonController : public Noncopyable {
+class DeleteButtonController {
+ WTF_MAKE_NONCOPYABLE(DeleteButtonController); WTF_MAKE_FAST_ALLOCATED;
public:
DeleteButtonController(Frame*);
diff --git a/Source/WebCore/editing/DeleteSelectionCommand.cpp b/Source/WebCore/editing/DeleteSelectionCommand.cpp
index 24c1968..3ba5ae9 100644
--- a/Source/WebCore/editing/DeleteSelectionCommand.cpp
+++ b/Source/WebCore/editing/DeleteSelectionCommand.cpp
@@ -111,9 +111,9 @@ void DeleteSelectionCommand::initializeStartEnd(Position& start, Position& end)
// For HRs, we'll get a position at (HR,1) when hitting delete from the beginning of the previous line, or (HR,0) when forward deleting,
// but in these cases, we want to delete it, so manually expand the selection
if (start.node()->hasTagName(hrTag))
- start = Position(start.node(), 0);
+ start = positionBeforeNode(start.node());
else if (end.node()->hasTagName(hrTag))
- end = Position(end.node(), 1);
+ end = positionAfterNode(end.node());
// FIXME: This is only used so that moveParagraphs can avoid the bugs in special element expansion.
if (!m_expandForSpecialElements)
@@ -256,14 +256,14 @@ void DeleteSelectionCommand::initializePositionData()
}
}
- // We must pass the positions through rangeCompliantEquivalent, since some editing positions
+ // We must pass call parentAnchoredEquivalent on the positions since some editing positions
// that appear inside their nodes aren't really inside them. [hr, 0] is one example.
- // FIXME: rangeComplaintEquivalent should eventually be moved into enclosing element getters
+ // FIXME: parentAnchoredEquivalent should eventually be moved into enclosing element getters
// like the one below, since editing functions should obviously accept editing positions.
// FIXME: Passing false to enclosingNodeOfType tells it that it's OK to return a non-editable
// node. This was done to match existing behavior, but it seems wrong.
- m_startBlock = enclosingNodeOfType(rangeCompliantEquivalent(m_downstreamStart), &isBlock, false);
- m_endBlock = enclosingNodeOfType(rangeCompliantEquivalent(m_upstreamEnd), &isBlock, false);
+ m_startBlock = enclosingNodeOfType(m_downstreamStart.parentAnchoredEquivalent(), &isBlock, false);
+ m_endBlock = enclosingNodeOfType(m_upstreamEnd.parentAnchoredEquivalent(), &isBlock, false);
}
void DeleteSelectionCommand::saveTypingStyleState()
@@ -315,10 +315,22 @@ static void updatePositionForNodeRemoval(Node* node, Position& position)
{
if (position.isNull())
return;
- if (node->parentNode() == position.node() && node->nodeIndex() < (unsigned)position.deprecatedEditingOffset())
- position = Position(position.node(), position.deprecatedEditingOffset() - 1);
- if (position.node() == node || position.node()->isDescendantOf(node))
- position = positionInParentBeforeNode(node);
+ switch (position.anchorType()) {
+ case Position::PositionIsOffsetInAnchor:
+ if (position.containerNode() == node->parentNode() && static_cast<unsigned>(position.offsetInContainerNode()) > node->nodeIndex())
+ position.moveToOffset(position.offsetInContainerNode() - 1);
+ else if (node->contains(position.containerNode()))
+ position = positionInParentBeforeNode(node);
+ break;
+ case Position::PositionIsAfterAnchor:
+ if (node->contains(position.anchorNode()))
+ position = positionInParentAfterNode(node);
+ break;
+ case Position::PositionIsBeforeAnchor:
+ if (node->contains(position.anchorNode()))
+ position = positionInParentBeforeNode(node);
+ break;
+ }
}
void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node)
@@ -362,7 +374,7 @@ void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node)
updateLayout();
RenderObject *r = node->renderer();
if (r && r->isTableCell() && toRenderTableCell(r)->contentHeight() <= 0)
- insertBlockPlaceholder(Position(node, 0));
+ insertBlockPlaceholder(firstPositionInNode(node.get()));
return;
}
@@ -381,12 +393,13 @@ void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node)
static void updatePositionForTextRemoval(Node* node, int offset, int count, Position& position)
{
- if (position.node() == node) {
- if (position.deprecatedEditingOffset() > offset + count)
- position = Position(position.node(), position.deprecatedEditingOffset() - count);
- else if (position.deprecatedEditingOffset() > offset)
- position = Position(position.node(), offset);
- }
+ if (position.anchorType() != Position::PositionIsOffsetInAnchor || position.containerNode() != node)
+ return;
+
+ if (position.offsetInContainerNode() > offset + count)
+ position.moveToOffset(position.offsetInContainerNode() - count);
+ else if (position.offsetInContainerNode() > offset)
+ position.moveToOffset(offset);
}
void DeleteSelectionCommand::deleteTextFromNode(PassRefPtr<Text> node, unsigned offset, unsigned count)
@@ -463,7 +476,7 @@ void DeleteSelectionCommand::handleGeneralDelete()
// handle deleting all nodes that are completely selected
while (node && node != m_downstreamEnd.node()) {
- if (comparePositions(Position(node.get(), 0), m_downstreamEnd) >= 0) {
+ if (comparePositions(firstPositionInOrBeforeNode(node.get()), m_downstreamEnd) >= 0) {
// traverseNextSibling just blew past the end position, so stop deleting
node = 0;
} else if (!m_downstreamEnd.node()->isDescendantOf(node.get())) {
@@ -471,8 +484,9 @@ void DeleteSelectionCommand::handleGeneralDelete()
// if we just removed a node from the end container, update end position so the
// check above will work
if (node->parentNode() == m_downstreamEnd.node()) {
+ ASSERT(m_downstreamEnd.deprecatedEditingOffset());
ASSERT(node->nodeIndex() < (unsigned)m_downstreamEnd.deprecatedEditingOffset());
- m_downstreamEnd = Position(m_downstreamEnd.node(), m_downstreamEnd.deprecatedEditingOffset() - 1);
+ m_downstreamEnd.moveToOffset(m_downstreamEnd.deprecatedEditingOffset() - 1);
}
removeNode(node.get());
node = nextNode.get();
@@ -513,7 +527,7 @@ void DeleteSelectionCommand::handleGeneralDelete()
offset = n->nodeIndex() + 1;
}
removeChildrenInRange(m_downstreamEnd.node(), offset, m_downstreamEnd.deprecatedEditingOffset());
- m_downstreamEnd = Position(m_downstreamEnd.node(), offset);
+ m_downstreamEnd.moveToOffset(offset);
}
}
}
@@ -609,8 +623,8 @@ void DeleteSelectionCommand::mergeParagraphs()
return;
}
- RefPtr<Range> range = Range::create(document(), rangeCompliantEquivalent(startOfParagraphToMove.deepEquivalent()), rangeCompliantEquivalent(endOfParagraphToMove.deepEquivalent()));
- RefPtr<Range> rangeToBeReplaced = Range::create(document(), rangeCompliantEquivalent(mergeDestination.deepEquivalent()), rangeCompliantEquivalent(mergeDestination.deepEquivalent()));
+ RefPtr<Range> range = Range::create(document(), startOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent(), endOfParagraphToMove.deepEquivalent().parentAnchoredEquivalent());
+ RefPtr<Range> rangeToBeReplaced = Range::create(document(), mergeDestination.deepEquivalent().parentAnchoredEquivalent(), mergeDestination.deepEquivalent().parentAnchoredEquivalent());
if (!document()->frame()->editor()->client()->shouldMoveRangeAfterDelete(range.get(), rangeToBeReplaced.get()))
return;
diff --git a/Source/WebCore/editing/Editor.cpp b/Source/WebCore/editing/Editor.cpp
index bea74d9..23b41ce 100644
--- a/Source/WebCore/editing/Editor.cpp
+++ b/Source/WebCore/editing/Editor.cpp
@@ -643,7 +643,7 @@ WritingDirection Editor::textDirectionForSelection(bool& hasNestedOrMultipleEmbe
if (m_frame->selection()->isRange()) {
end = m_frame->selection()->selection().end().upstream();
- Node* pastLast = Range::create(m_frame->document(), rangeCompliantEquivalent(position), rangeCompliantEquivalent(end))->pastLastNode();
+ 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;
@@ -1783,7 +1783,7 @@ void Editor::advanceToNextMisspelling(bool startBeforeSelection)
if (position.isNull())
return;
- Position rangeCompliantPosition = rangeCompliantEquivalent(position);
+ Position rangeCompliantPosition = position.parentAnchoredEquivalent();
spellingSearchRange->setStart(rangeCompliantPosition.node(), rangeCompliantPosition.deprecatedEditingOffset(), ec);
startedWithSelection = false; // won't need to wrap
}
diff --git a/Source/WebCore/editing/EditorCommand.cpp b/Source/WebCore/editing/EditorCommand.cpp
index 64993d5..9e5bf9f 100644
--- a/Source/WebCore/editing/EditorCommand.cpp
+++ b/Source/WebCore/editing/EditorCommand.cpp
@@ -477,7 +477,7 @@ static bool executeIndent(Frame* frame, Event*, EditorCommandSource, const Strin
static bool executeInsertBacktab(Frame* frame, Event* event, EditorCommandSource, const String&)
{
- return targetFrame(frame, event)->eventHandler()->handleTextInputEvent("\t", event, false, true);
+ return targetFrame(frame, event)->eventHandler()->handleTextInputEvent("\t", event, TextEventInputBackTab);
}
static bool executeInsertHorizontalRule(Frame* frame, Event*, EditorCommandSource, const String& value)
@@ -505,7 +505,7 @@ static bool executeInsertLineBreak(Frame* frame, Event* event, EditorCommandSour
{
switch (source) {
case CommandFromMenuOrKeyBinding:
- return targetFrame(frame, event)->eventHandler()->handleTextInputEvent("\n", event, true);
+ return targetFrame(frame, event)->eventHandler()->handleTextInputEvent("\n", event, TextEventInputLineBreak);
case CommandFromDOM:
case CommandFromDOMWithUserInterface:
// Doesn't scroll to make the selection visible, or modify the kill ring.
@@ -521,7 +521,7 @@ static bool executeInsertLineBreak(Frame* frame, Event* event, EditorCommandSour
static bool executeInsertNewline(Frame* frame, Event* event, EditorCommandSource, const String&)
{
Frame* targetFrame = WebCore::targetFrame(frame, event);
- return targetFrame->eventHandler()->handleTextInputEvent("\n", event, !targetFrame->editor()->canEditRichly());
+ return targetFrame->eventHandler()->handleTextInputEvent("\n", event, targetFrame->editor()->canEditRichly() ? TextEventInputKeyboard : TextEventInputLineBreak);
}
static bool executeInsertNewlineInQuotedContent(Frame* frame, Event*, EditorCommandSource, const String&)
@@ -544,7 +544,7 @@ static bool executeInsertParagraph(Frame* frame, Event*, EditorCommandSource, co
static bool executeInsertTab(Frame* frame, Event* event, EditorCommandSource, const String&)
{
- return targetFrame(frame, event)->eventHandler()->handleTextInputEvent("\t", event, false, false);
+ return targetFrame(frame, event)->eventHandler()->handleTextInputEvent("\t", event);
}
static bool executeInsertText(Frame* frame, Event*, EditorCommandSource, const String& value)
diff --git a/Source/WebCore/editing/IndentOutdentCommand.cpp b/Source/WebCore/editing/IndentOutdentCommand.cpp
index 13d0f88..9d1adc1 100644
--- a/Source/WebCore/editing/IndentOutdentCommand.cpp
+++ b/Source/WebCore/editing/IndentOutdentCommand.cpp
@@ -134,11 +134,11 @@ void IndentOutdentCommand::outdentParagraph()
}
// The selection is inside a blockquote i.e. enclosingNode is a blockquote
- VisiblePosition positionInEnclosingBlock = VisiblePosition(Position(enclosingNode, 0));
+ VisiblePosition positionInEnclosingBlock = VisiblePosition(firstPositionInNode(enclosingNode));
// If the blockquote is inline, the start of the enclosing block coincides with
// positionInEnclosingBlock.
VisiblePosition startOfEnclosingBlock = (enclosingNode->renderer() && enclosingNode->renderer()->isInline()) ? positionInEnclosingBlock : startOfBlock(positionInEnclosingBlock);
- VisiblePosition lastPositionInEnclosingBlock = VisiblePosition(Position(enclosingNode, enclosingNode->childNodeCount()));
+ VisiblePosition lastPositionInEnclosingBlock = VisiblePosition(lastPositionInNode(enclosingNode));
VisiblePosition endOfEnclosingBlock = endOfBlock(lastPositionInEnclosingBlock);
if (visibleStartOfParagraph == startOfEnclosingBlock &&
visibleEndOfParagraph == endOfEnclosingBlock) {
@@ -176,7 +176,7 @@ void IndentOutdentCommand::outdentParagraph()
}
RefPtr<Node> placeholder = createBreakElement(document());
insertNodeBefore(placeholder, splitBlockquoteNode);
- moveParagraph(startOfParagraph(visibleStartOfParagraph), endOfParagraph(visibleEndOfParagraph), VisiblePosition(Position(placeholder.get(), 0)), true);
+ moveParagraph(startOfParagraph(visibleStartOfParagraph), endOfParagraph(visibleEndOfParagraph), positionBeforeNode(placeholder.get()), true);
}
// FIXME: We should merge this function with ApplyBlockElementCommand::formatSelection
diff --git a/Source/WebCore/editing/InsertLineBreakCommand.cpp b/Source/WebCore/editing/InsertLineBreakCommand.cpp
index 3070edf..af8f2fc 100644
--- a/Source/WebCore/editing/InsertLineBreakCommand.cpp
+++ b/Source/WebCore/editing/InsertLineBreakCommand.cpp
@@ -82,7 +82,7 @@ bool InsertLineBreakCommand::shouldUseBreakElement(const Position& insertionPos)
// An editing position like [input, 0] actually refers to the position before
// the input element, and in that case we need to check the input element's
// parent's renderer.
- Position p(rangeCompliantEquivalent(insertionPos));
+ Position p(insertionPos.parentAnchoredEquivalent());
return p.node()->renderer() && !p.node()->renderer()->style()->preserveNewline();
}
@@ -121,13 +121,13 @@ void InsertLineBreakCommand::doApply()
if (needExtraLineBreak)
insertNodeBefore(nodeToInsert->cloneNode(false), nodeToInsert);
- VisiblePosition endingPosition(Position(nodeToInsert.get(), 0));
+ VisiblePosition endingPosition(positionBeforeNode(nodeToInsert.get()));
setEndingSelection(VisibleSelection(endingPosition));
} else if (pos.deprecatedEditingOffset() <= caretMinOffset(pos.node())) {
insertNodeAt(nodeToInsert.get(), pos);
// Insert an extra br or '\n' if the just inserted one collapsed.
- if (!isStartOfParagraph(VisiblePosition(Position(nodeToInsert.get(), 0))))
+ if (!isStartOfParagraph(positionBeforeNode(nodeToInsert.get())))
insertNodeBefore(nodeToInsert->cloneNode(false).get(), nodeToInsert.get());
setEndingSelection(VisibleSelection(positionInParentAfterNode(nodeToInsert.get()), DOWNSTREAM));
@@ -141,7 +141,7 @@ void InsertLineBreakCommand::doApply()
Text* textNode = static_cast<Text*>(pos.node());
splitTextNode(textNode, pos.deprecatedEditingOffset());
insertNodeBefore(nodeToInsert, textNode);
- Position endingPosition = Position(textNode, 0);
+ Position endingPosition = firstPositionInNode(textNode);
// Handle whitespace that occurs after the split
updateLayout();
@@ -156,7 +156,7 @@ void InsertLineBreakCommand::doApply()
else {
RefPtr<Text> nbspNode = document()->createTextNode(nonBreakingSpaceString());
insertNodeAt(nbspNode.get(), positionBeforeTextNode);
- endingPosition = Position(nbspNode.get(), 0);
+ endingPosition = firstPositionInNode(nbspNode.get());
}
}
diff --git a/Source/WebCore/editing/InsertListCommand.cpp b/Source/WebCore/editing/InsertListCommand.cpp
index bb3cd93..9348786 100644
--- a/Source/WebCore/editing/InsertListCommand.cpp
+++ b/Source/WebCore/editing/InsertListCommand.cpp
@@ -217,7 +217,7 @@ void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const Qu
RefPtr<HTMLElement> newList = createHTMLElement(document(), listTag);
insertNodeBefore(newList, listNode);
- Node* firstChildInList = enclosingListChild(VisiblePosition(Position(listNode, 0)).deepEquivalent().node(), listNode.get());
+ Node* firstChildInList = enclosingListChild(VisiblePosition(firstPositionInNode(listNode.get())).deepEquivalent().node(), listNode.get());
Node* outerBlock = firstChildInList->isBlockFlow() ? firstChildInList : listNode.get();
moveParagraphWithClones(firstPositionInNode(listNode.get()), lastPositionInNode(listNode.get()), newList.get(), outerBlock);
@@ -302,7 +302,7 @@ void InsertListCommand::unlistifyParagraph(const VisiblePosition& originalStart,
} else
insertNodeAfter(nodeToInsert, listNode);
- VisiblePosition insertionPoint = VisiblePosition(Position(placeholder.get(), 0));
+ VisiblePosition insertionPoint = VisiblePosition(positionBeforeNode(placeholder.get()));
moveParagraphs(start, end, insertionPoint, true);
}
@@ -345,7 +345,7 @@ PassRefPtr<HTMLElement> InsertListCommand::listifyParagraph(const VisiblePositio
if (previousList)
appendNode(listItemElement, previousList);
else if (nextList)
- insertNodeAt(listItemElement, Position(nextList, 0));
+ insertNodeAt(listItemElement, positionBeforeNode(nextList));
else {
// Create the list.
listElement = createHTMLElement(document(), listTag);
@@ -356,7 +356,7 @@ PassRefPtr<HTMLElement> InsertListCommand::listifyParagraph(const VisiblePositio
// by a br or a '\n', will invalidate start and end. Insert
// a placeholder and then recompute start and end.
RefPtr<Node> placeholder = insertBlockPlaceholder(start.deepEquivalent());
- start = VisiblePosition(Position(placeholder.get(), 0));
+ start = positionBeforeNode(placeholder.get());
end = start;
}
@@ -379,7 +379,7 @@ PassRefPtr<HTMLElement> InsertListCommand::listifyParagraph(const VisiblePositio
start = startOfParagraph(originalStart);
}
- moveParagraph(start, end, VisiblePosition(Position(placeholder.get(), 0)), true);
+ moveParagraph(start, end, positionBeforeNode(placeholder.get()), true);
if (listElement)
return mergeWithNeighboringLists(listElement);
diff --git a/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp b/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp
index 1838382..1d50851 100644
--- a/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp
+++ b/Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp
@@ -159,8 +159,8 @@ void InsertParagraphSeparatorCommand::doApply()
affinity = endingSelection().affinity();
}
- // FIXME: The rangeCompliantEquivalent conversion needs to be moved into enclosingBlock.
- Node* startBlockNode = enclosingBlock(rangeCompliantEquivalent(insertionPosition).node());
+ // FIXME: The parentAnchoredEquivalent conversion needs to be moved into enclosingBlock.
+ Node* startBlockNode = enclosingBlock(insertionPosition.parentAnchoredEquivalent().containerNode());
Position canonicalPos = VisiblePosition(insertionPosition).deepEquivalent();
Element* startBlock = static_cast<Element*>(startBlockNode);
if (!startBlockNode
@@ -242,7 +242,7 @@ void InsertParagraphSeparatorCommand::doApply()
appendBlockPlaceholder(parent);
- setEndingSelection(VisibleSelection(Position(parent.get(), 0), DOWNSTREAM));
+ setEndingSelection(VisibleSelection(firstPositionInNode(parent.get()), DOWNSTREAM));
return;
}
@@ -378,7 +378,8 @@ void InsertParagraphSeparatorCommand::doApply()
// Handle whitespace that occurs after the split
if (splitText) {
updateLayout();
- insertionPosition = Position(insertionPosition.node(), 0);
+ if (insertionPosition.anchorType() == Position::PositionIsOffsetInAnchor)
+ insertionPosition.moveToOffset(0);
if (!insertionPosition.isRenderedCharacter()) {
// Clear out all whitespace and insert one non-breaking space
ASSERT(!insertionPosition.node()->renderer() || insertionPosition.node()->renderer()->style()->collapseWhiteSpace());
@@ -388,7 +389,7 @@ void InsertParagraphSeparatorCommand::doApply()
}
}
- setEndingSelection(VisibleSelection(Position(blockToInsert.get(), 0), DOWNSTREAM));
+ setEndingSelection(VisibleSelection(firstPositionInNode(blockToInsert.get()), DOWNSTREAM));
applyStyleAfterInsertion(startBlock);
}
diff --git a/Source/WebCore/editing/ReplaceSelectionCommand.cpp b/Source/WebCore/editing/ReplaceSelectionCommand.cpp
index 044ce63..f47cb4e 100644
--- a/Source/WebCore/editing/ReplaceSelectionCommand.cpp
+++ b/Source/WebCore/editing/ReplaceSelectionCommand.cpp
@@ -62,7 +62,8 @@ enum EFragmentType { EmptyFragment, SingleTextNodeFragment, TreeFragment };
// --- ReplacementFragment helper class
-class ReplacementFragment : public Noncopyable {
+class ReplacementFragment {
+ WTF_MAKE_NONCOPYABLE(ReplacementFragment);
public:
ReplacementFragment(Document*, DocumentFragment*, bool matchStyle, const VisibleSelection&);
@@ -568,7 +569,7 @@ static bool handleStyleSpansBeforeInsertion(ReplacementFragment& fragment, const
Node* sourceDocumentStyleSpan = topNode;
RefPtr<Node> copiedRangeStyleSpan = sourceDocumentStyleSpan->firstChild();
- RefPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(rangeCompliantEquivalent(insertionPos));
+ RefPtr<EditingStyle> styleAtInsertionPos = EditingStyle::create(insertionPos.parentAnchoredEquivalent());
String styleText = styleAtInsertionPos->style()->cssText();
// FIXME: This string comparison is a naive way of comparing two styles.
diff --git a/Source/WebCore/editing/SelectionController.cpp b/Source/WebCore/editing/SelectionController.cpp
index eca0711..fa0c32d 100644
--- a/Source/WebCore/editing/SelectionController.cpp
+++ b/Source/WebCore/editing/SelectionController.cpp
@@ -316,32 +316,45 @@ void SelectionController::willBeModified(EAlteration alter, SelectionDirection d
Position start = m_selection.start();
Position end = m_selection.end();
+ bool baseIsStart = true;
+
if (m_isDirectional) {
// Make base and extent match start and end so we extend the user-visible selection.
// This only matters for cases where base and extend point to different positions than
// start and end (e.g. after a double-click to select a word).
- if (m_selection.isBaseFirst()) {
- m_selection.setBase(start);
- m_selection.setExtent(end);
- } else {
- m_selection.setBase(end);
- m_selection.setExtent(start);
- }
+ if (m_selection.isBaseFirst())
+ baseIsStart = true;
+ else
+ baseIsStart = false;
} else {
- // FIXME: This is probably not correct for right and left when the direction is RTL.
switch (direction) {
case DirectionRight:
+ if (directionOfEnclosingBlock() == LTR)
+ baseIsStart = true;
+ else
+ baseIsStart = false;
+ break;
case DirectionForward:
- m_selection.setBase(start);
- m_selection.setExtent(end);
+ baseIsStart = true;
break;
case DirectionLeft:
+ if (directionOfEnclosingBlock() == LTR)
+ baseIsStart = false;
+ else
+ baseIsStart = true;
+ break;
case DirectionBackward:
- m_selection.setBase(end);
- m_selection.setExtent(start);
+ baseIsStart = false;
break;
}
}
+ if (baseIsStart) {
+ m_selection.setBase(start);
+ m_selection.setExtent(end);
+ } else {
+ m_selection.setBase(end);
+ m_selection.setExtent(start);
+ }
}
TextDirection SelectionController::directionOfEnclosingBlock()
@@ -458,9 +471,12 @@ VisiblePosition SelectionController::modifyMovingRight(TextGranularity granulari
VisiblePosition pos;
switch (granularity) {
case CharacterGranularity:
- if (isRange())
- pos = VisiblePosition(m_selection.end(), m_selection.affinity());
- else
+ if (isRange()) {
+ if (directionOfEnclosingBlock() == LTR)
+ pos = VisiblePosition(m_selection.end(), m_selection.affinity());
+ else
+ pos = VisiblePosition(m_selection.start(), m_selection.affinity());
+ } else
pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
break;
case WordGranularity:
@@ -612,7 +628,10 @@ VisiblePosition SelectionController::modifyMovingLeft(TextGranularity granularit
switch (granularity) {
case CharacterGranularity:
if (isRange())
- pos = VisiblePosition(m_selection.start(), m_selection.affinity());
+ if (directionOfEnclosingBlock() == LTR)
+ pos = VisiblePosition(m_selection.start(), m_selection.affinity());
+ else
+ pos = VisiblePosition(m_selection.end(), m_selection.affinity());
else
pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
break;
diff --git a/Source/WebCore/editing/SelectionController.h b/Source/WebCore/editing/SelectionController.h
index ee52187..3f805d3 100644
--- a/Source/WebCore/editing/SelectionController.h
+++ b/Source/WebCore/editing/SelectionController.h
@@ -48,7 +48,8 @@ class VisiblePosition;
enum DirectionalityPolicy { MakeNonDirectionalSelection, MakeDirectionalSelection };
-class SelectionController : public Noncopyable {
+class SelectionController {
+ WTF_MAKE_NONCOPYABLE(SelectionController); WTF_MAKE_FAST_ALLOCATED;
public:
enum EAlteration { AlterationMove, AlterationExtend };
enum CursorAlignOnScroll { AlignCursorOnScrollIfNeeded,
diff --git a/Source/WebCore/editing/SpellChecker.h b/Source/WebCore/editing/SpellChecker.h
index f6215d2..81bb519 100644
--- a/Source/WebCore/editing/SpellChecker.h
+++ b/Source/WebCore/editing/SpellChecker.h
@@ -54,7 +54,8 @@ private:
int m_length;
};
-class SpellChecker : public Noncopyable {
+class SpellChecker {
+ WTF_MAKE_NONCOPYABLE(SpellChecker);
public:
explicit SpellChecker(Frame*, EditorClient*);
~SpellChecker();
diff --git a/Source/WebCore/editing/TextCheckingHelper.h b/Source/WebCore/editing/TextCheckingHelper.h
index 227530f..8b5c691 100644
--- a/Source/WebCore/editing/TextCheckingHelper.h
+++ b/Source/WebCore/editing/TextCheckingHelper.h
@@ -72,7 +72,8 @@ private:
mutable int m_checkingLength;
};
-class TextCheckingHelper : public Noncopyable {
+class TextCheckingHelper {
+ WTF_MAKE_NONCOPYABLE(TextCheckingHelper);
public:
TextCheckingHelper(EditorClient*, PassRefPtr<Range>);
~TextCheckingHelper();
diff --git a/Source/WebCore/editing/TextIterator.cpp b/Source/WebCore/editing/TextIterator.cpp
index 7e41420..1fc7606 100644
--- a/Source/WebCore/editing/TextIterator.cpp
+++ b/Source/WebCore/editing/TextIterator.cpp
@@ -61,7 +61,8 @@ using namespace HTMLNames;
// Case folding is also done if the CaseInsensitive option is specified.
// Matches are further filtered if the AtWordStarts option is specified, although some
// matches inside a word are permitted if TreatMedialCapitalAsWordStart is specified as well.
-class SearchBuffer : public Noncopyable {
+class SearchBuffer {
+ WTF_MAKE_NONCOPYABLE(SearchBuffer);
public:
SearchBuffer(const String& target, FindOptions);
~SearchBuffer();
@@ -1128,10 +1129,10 @@ void SimplifiedBackwardsTextIterator::advance()
if (!next) {
// Exit empty containers as we pass over them or containers
// where [container, 0] is where we started iterating.
- if (!m_handledNode &&
- canHaveChildrenForEditing(m_node) &&
- m_node->parentNode() &&
- (!m_node->lastChild() || (m_node == m_endNode && m_endOffset == 0))) {
+ if (!m_handledNode
+ && canHaveChildrenForEditing(m_node)
+ && m_node->parentNode()
+ && (!m_node->lastChild() || (m_node == m_endNode && !m_endOffset))) {
exitNode();
if (m_positionNode) {
m_handledNode = true;
diff --git a/Source/WebCore/editing/VisiblePosition.cpp b/Source/WebCore/editing/VisiblePosition.cpp
index adfead1..5999fa6 100644
--- a/Source/WebCore/editing/VisiblePosition.cpp
+++ b/Source/WebCore/editing/VisiblePosition.cpp
@@ -597,8 +597,8 @@ PassRefPtr<Range> makeRange(const VisiblePosition &start, const VisiblePosition
if (start.isNull() || end.isNull())
return 0;
- Position s = rangeCompliantEquivalent(start);
- Position e = rangeCompliantEquivalent(end);
+ Position s = start.deepEquivalent().parentAnchoredEquivalent();
+ Position e = end.deepEquivalent().parentAnchoredEquivalent();
return Range::create(s.node()->document(), s.node(), s.deprecatedEditingOffset(), e.node(), e.deprecatedEditingOffset());
}
@@ -618,7 +618,7 @@ bool setStart(Range *r, const VisiblePosition &visiblePosition)
{
if (!r)
return false;
- Position p = rangeCompliantEquivalent(visiblePosition);
+ Position p = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
int code = 0;
r->setStart(p.node(), p.deprecatedEditingOffset(), code);
return code == 0;
@@ -628,7 +628,7 @@ bool setEnd(Range *r, const VisiblePosition &visiblePosition)
{
if (!r)
return false;
- Position p = rangeCompliantEquivalent(visiblePosition);
+ Position p = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
int code = 0;
r->setEnd(p.node(), p.deprecatedEditingOffset(), code);
return code == 0;
diff --git a/Source/WebCore/editing/VisibleSelection.cpp b/Source/WebCore/editing/VisibleSelection.cpp
index 4037670..035afb8 100644
--- a/Source/WebCore/editing/VisibleSelection.cpp
+++ b/Source/WebCore/editing/VisibleSelection.cpp
@@ -121,8 +121,8 @@ PassRefPtr<Range> VisibleSelection::firstRange() const
{
if (isNone())
return 0;
- Position start = rangeCompliantEquivalent(m_start);
- Position end = rangeCompliantEquivalent(m_end);
+ Position start = m_start.parentAnchoredEquivalent();
+ Position end = m_end.parentAnchoredEquivalent();
return Range::create(start.node()->document(), start, end);
}
@@ -146,7 +146,7 @@ PassRefPtr<Range> VisibleSelection::toNormalizedRange() const
// If the selection is a caret, move the range start upstream. This helps us match
// the conventions of text editors tested, which make style determinations based
// on the character before the caret, if any.
- s = rangeCompliantEquivalent(m_start.upstream());
+ s = m_start.upstream().parentAnchoredEquivalent();
e = s;
} else {
// If the selection is a range, select the minimum range that encompasses the selection.
@@ -170,8 +170,8 @@ PassRefPtr<Range> VisibleSelection::toNormalizedRange() const
s = e;
e = tmp;
}
- s = rangeCompliantEquivalent(s);
- e = rangeCompliantEquivalent(e);
+ s = s.parentAnchoredEquivalent();
+ e = e.parentAnchoredEquivalent();
}
// VisibleSelections are supposed to always be valid. This constructor will ASSERT
@@ -204,7 +204,7 @@ static PassRefPtr<Range> makeSearchRange(const Position& pos)
RefPtr<Range> searchRange(Range::create(d));
ExceptionCode ec = 0;
- Position start(rangeCompliantEquivalent(pos));
+ Position start(pos.parentAnchoredEquivalent());
searchRange->selectNodeContents(boundary, ec);
searchRange->setStart(start.node(), start.deprecatedEditingOffset(), ec);
diff --git a/Source/WebCore/editing/htmlediting.cpp b/Source/WebCore/editing/htmlediting.cpp
index d08ac2e..90db3ef 100644
--- a/Source/WebCore/editing/htmlediting.cpp
+++ b/Source/WebCore/editing/htmlediting.cpp
@@ -329,60 +329,12 @@ bool isBlock(const Node* node)
// knowing about these kinds of special cases.
Node* enclosingBlock(Node* node)
{
- return static_cast<Element*>(enclosingNodeOfType(Position(node, 0), isBlock));
-}
-
-// Internally editing uses "invalid" positions for historical reasons. For
-// example, in <div><img /></div>, Editing might use (img, 1) for the position
-// after <img>, but we have to convert that to (div, 1) before handing the
-// position to a Range object. Ideally all internal positions should
-// be "range compliant" for simplicity.
-Position rangeCompliantEquivalent(const Position& pos)
-{
- if (pos.isNull())
- return Position();
-
- Node* node = pos.node();
-
- if (pos.deprecatedEditingOffset() <= 0) {
- if (node->parentNode() && (editingIgnoresContent(node) || isTableElement(node)))
- return positionInParentBeforeNode(node);
- return Position(node, 0);
- }
-
- if (node->offsetInCharacters())
- return Position(node, min(node->maxCharacterOffset(), pos.deprecatedEditingOffset()));
-
- int maxCompliantOffset = node->childNodeCount();
- if (pos.deprecatedEditingOffset() > maxCompliantOffset) {
- if (node->parentNode())
- return positionInParentAfterNode(node);
-
- // there is no other option at this point than to
- // use the highest allowed position in the node
- return Position(node, maxCompliantOffset);
- }
-
- // Editing should never generate positions like this.
- if ((pos.deprecatedEditingOffset() < maxCompliantOffset) && editingIgnoresContent(node)) {
- ASSERT_NOT_REACHED();
- return node->parentNode() ? positionInParentBeforeNode(node) : Position(node, 0);
- }
-
- if (pos.deprecatedEditingOffset() == maxCompliantOffset && (editingIgnoresContent(node) || isTableElement(node)))
- return positionInParentAfterNode(node);
-
- return Position(pos);
-}
-
-Position rangeCompliantEquivalent(const VisiblePosition& vpos)
-{
- return rangeCompliantEquivalent(vpos.deepEquivalent());
+ return static_cast<Element*>(enclosingNodeOfType(firstPositionInOrBeforeNode(node), isBlock));
}
// This method is used to create positions in the DOM. It returns the maximum valid offset
// in a node. It returns 1 for some elements even though they do not have children, which
-// creates technically invalid DOM Positions. Be sure to call rangeCompliantEquivalent
+// creates technically invalid DOM Positions. Be sure to call parentAnchoredEquivalent
// on a Position before using it to create a DOM Range, or an exception will be thrown.
int lastOffsetForEditing(const Node* node)
{
@@ -704,7 +656,7 @@ HTMLElement* enclosingList(Node* node)
if (!node)
return 0;
- Node* root = highestEditableRoot(Position(node, 0));
+ Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
for (ContainerNode* n = node->parentNode(); n; n = n->parentNode()) {
if (n->hasTagName(ulTag) || n->hasTagName(olTag))
@@ -722,7 +674,7 @@ HTMLElement* enclosingListChild(Node *node)
return 0;
// Check for a list item element, or for a node whose parent is a list element. Such a node
// will appear visually as a list item (but without a list marker)
- Node* root = highestEditableRoot(Position(node, 0));
+ Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
// FIXME: This function is inappropriately named if it starts with node instead of node->parentNode()
for (Node* n = node; n && n->parentNode(); n = n->parentNode()) {
@@ -1081,7 +1033,8 @@ int indexForVisiblePosition(const VisiblePosition& visiblePosition)
if (visiblePosition.isNull())
return 0;
Position p(visiblePosition.deepEquivalent());
- RefPtr<Range> range = Range::create(p.node()->document(), Position(p.node()->document(), 0), rangeCompliantEquivalent(p));
+ RefPtr<Range> range = Range::create(p.node()->document(), firstPositionInNode(p.anchorNode()->document()->documentElement()),
+ p.parentAnchoredEquivalent());
return TextIterator::rangeLength(range.get(), true);
}
@@ -1104,11 +1057,11 @@ bool isNodeVisiblyContainedWithin(Node* node, const Range* selectedRange)
return true;
bool startIsVisuallySame = visiblePositionBeforeNode(node) == selectedRange->startPosition();
- if (startIsVisuallySame && comparePositions(Position(node->parentNode(), node->nodeIndex()+1), selectedRange->endPosition()) < 0)
+ if (startIsVisuallySame && comparePositions(positionInParentAfterNode(node), selectedRange->endPosition()) < 0)
return true;
bool endIsVisuallySame = visiblePositionAfterNode(node) == selectedRange->endPosition();
- if (endIsVisuallySame && comparePositions(selectedRange->startPosition(), Position(node->parentNode(), node->nodeIndex())) < 0)
+ if (endIsVisuallySame && comparePositions(selectedRange->startPosition(), positionInParentBeforeNode(node)) < 0)
return true;
return startIsVisuallySame && endIsVisuallySame;
@@ -1157,23 +1110,23 @@ VisibleSelection avoidIntersectionWithNode(const VisibleSelection& selection, No
{
if (selection.isNone())
return VisibleSelection(selection);
-
+
VisibleSelection updatedSelection(selection);
Node* base = selection.base().node();
Node* extent = selection.extent().node();
ASSERT(base);
ASSERT(extent);
-
+
if (base == node || base->isDescendantOf(node)) {
ASSERT(node->parentNode());
- updatedSelection.setBase(Position(node->parentNode(), node->nodeIndex()));
+ updatedSelection.setBase(positionInParentBeforeNode(node));
}
-
+
if (extent == node || extent->isDescendantOf(node)) {
ASSERT(node->parentNode());
- updatedSelection.setExtent(Position(node->parentNode(), node->nodeIndex()));
+ updatedSelection.setExtent(positionInParentBeforeNode(node));
}
-
+
return updatedSelection;
}
diff --git a/Source/WebCore/editing/htmlediting.h b/Source/WebCore/editing/htmlediting.h
index 1f6b986..0208dfb 100644
--- a/Source/WebCore/editing/htmlediting.h
+++ b/Source/WebCore/editing/htmlediting.h
@@ -101,9 +101,6 @@ bool isNodeInTextFormControl(Node* node);
// Functions returning Position
-Position rangeCompliantEquivalent(const Position&);
-Position rangeCompliantEquivalent(const VisiblePosition&);
-
Position nextCandidate(const Position&);
Position previousCandidate(const Position&);
diff --git a/Source/WebCore/editing/visible_units.cpp b/Source/WebCore/editing/visible_units.cpp
index 7bb1515..3582aa9 100644
--- a/Source/WebCore/editing/visible_units.cpp
+++ b/Source/WebCore/editing/visible_units.cpp
@@ -57,8 +57,8 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
return VisiblePosition();
Document* d = boundary->document();
- Position start = rangeCompliantEquivalent(Position(boundary, 0));
- Position end = rangeCompliantEquivalent(pos);
+ Position start = Position(boundary, 0).parentAnchoredEquivalent();
+ Position end = pos.parentAnchoredEquivalent();
RefPtr<Range> searchRange = Range::create(d);
Vector<UChar, 1024> string;
@@ -115,22 +115,18 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
ASSERT(!needMoreContext);
}
- if (it.atEnd() && next == 0) {
- pos = it.range()->startPosition();
- } else if (next != 0) {
- Node *node = it.range()->startContainer(ec);
- if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next))
- // The next variable contains a usable index into a text node
- pos = Position(node, next);
- else {
- // Use the character iterator to translate the next value into a DOM position.
- BackwardsCharacterIterator charIt(searchRange.get(), TextIteratorEndsAtEditingBoundary);
- charIt.advance(string.size() - suffixLength - next);
- pos = charIt.range()->endPosition();
- }
- }
+ if (!next)
+ return VisiblePosition(it.atEnd() ? it.range()->startPosition() : pos, DOWNSTREAM);
+
+ Node* node = it.range()->startContainer(ec);
+ if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next))
+ // The next variable contains a usable index into a text node
+ return VisiblePosition(Position(node, next), DOWNSTREAM);
- return VisiblePosition(pos, DOWNSTREAM);
+ // Use the character iterator to translate the next value into a DOM position.
+ BackwardsCharacterIterator charIt(searchRange.get(), TextIteratorEndsAtEditingBoundary);
+ charIt.advance(string.size() - suffixLength - next);
+ return VisiblePosition(charIt.range()->endPosition(), DOWNSTREAM);
}
static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
@@ -142,7 +138,7 @@ static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunc
Document* d = boundary->document();
RefPtr<Range> searchRange(d->createRange());
- Position start(rangeCompliantEquivalent(pos));
+ Position start(pos.parentAnchoredEquivalent());
Vector<UChar, 1024> string;
unsigned prefixLength = 0;