diff options
author | Ben Murdoch <benm@google.com> | 2011-05-16 16:25:10 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-23 18:54:14 +0100 |
commit | ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb (patch) | |
tree | db769fadd053248f85db67434a5b275224defef7 /Source/WebCore/editing | |
parent | 52e2557aeb8477967e97fd24f20f8f407a10fa15 (diff) | |
download | external_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')
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; |