bool IndentOutdentCommand::tryIndentingAsListItem(const VisiblePosition& endOfCurrentParagraph) { // If our selection is not inside a list, bail out. Node* lastNodeInSelectedParagraph = endOfCurrentParagraph.deepEquivalent().node(); RefPtr<Element> listNode = enclosingList(lastNodeInSelectedParagraph); if (!listNode) return false; // Find the list item enclosing the current paragraph Element* selectedListItem = static_cast<Element*>(enclosingBlock(lastNodeInSelectedParagraph)); // FIXME: enclosingBlock shouldn't return the passed in element. See the // comment on the function about how to fix rather than having to adjust here. if (selectedListItem == lastNodeInSelectedParagraph) selectedListItem = static_cast<Element*>(enclosingBlock(lastNodeInSelectedParagraph->parentNode())); // FIXME: we need to deal with the case where there is no li (malformed HTML) if (!selectedListItem->hasTagName(liTag)) return false; // FIXME: previousElementSibling does not ignore non-rendered content like <span></span>. Should we? Element* previousList = selectedListItem->previousElementSibling(); Element* nextList = selectedListItem->nextElementSibling(); RefPtr<Element> newList = document()->createElement(listNode->tagQName(), false); insertNodeBefore(newList, selectedListItem); moveParagraphWithClones(startOfParagraph(endOfCurrentParagraph), endOfCurrentParagraph, newList.get(), selectedListItem); if (canMergeLists(previousList, newList.get())) mergeIdenticalElements(previousList, newList); if (canMergeLists(newList.get(), nextList)) mergeIdenticalElements(newList, nextList); return true; }
int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const { if (enclosingTextFormControl(pos.deepEquivalent()) != this) return 0; bool forSelectionPreservation = false; return WebCore::indexForVisiblePosition(innerTextElement(), pos, forSelectionPreservation); }
void AXObjectCache::textMarkerDataForVisiblePosition(TextMarkerData& textMarkerData, const VisiblePosition& visiblePos) { // This memory must be bzero'd so instances of TextMarkerData can be tested for byte-equivalence. // This also allows callers to check for failure by looking at textMarkerData upon return. memset(&textMarkerData, 0, sizeof(TextMarkerData)); if (visiblePos.isNull()) return; Position deepPos = visiblePos.deepEquivalent(); Node* domNode = deepPos.node(); ASSERT(domNode); if (!domNode) return; if (domNode->isHTMLElement()) { InputElement* inputElement = toInputElement(static_cast<Element*>(domNode)); if (inputElement && inputElement->isPasswordField()) return; } // locate the renderer, which must exist for a visible dom node RenderObject* renderer = domNode->renderer(); ASSERT(renderer); // find or create an accessibility object for this renderer AXObjectCache* cache = renderer->document()->axObjectCache(); RefPtr<AccessibilityObject> obj = cache->getOrCreate(renderer); textMarkerData.axID = obj.get()->axObjectID(); textMarkerData.node = domNode; textMarkerData.offset = deepPos.deprecatedEditingOffset(); textMarkerData.affinity = visiblePos.affinity(); }
void IndentOutdentCommand::indentIntoBlockquote(const VisiblePosition& endOfCurrentParagraph, const VisiblePosition& endOfNextParagraph, RefPtr<Element>& targetBlockquote) { Node* enclosingCell = 0; Position start = startOfParagraph(endOfCurrentParagraph).deepEquivalent(); enclosingCell = enclosingNodeOfType(start, &isTableCell); Node* nodeToSplitTo; if (enclosingCell) nodeToSplitTo = enclosingCell; else if (enclosingList(start.node())) nodeToSplitTo = enclosingBlock(start.node()); else nodeToSplitTo = editableRootForPosition(start); RefPtr<Node> outerBlock = splitTreeToNode(start.node(), nodeToSplitTo); if (!targetBlockquote) { // Create a new blockquote and insert it as a child of the root editable element. We accomplish // this by splitting all parents of the current paragraph up to that point. targetBlockquote = createIndentBlockquoteElement(document()); insertNodeBefore(targetBlockquote, outerBlock); } moveParagraphWithClones(startOfParagraph(endOfCurrentParagraph), endOfCurrentParagraph, targetBlockquote.get(), outerBlock.get()); // Don't put the next paragraph in the blockquote we just created for this paragraph unless // the next paragraph is in the same cell. if (enclosingCell && enclosingCell != enclosingNodeOfType(endOfNextParagraph.deepEquivalent(), &isTableCell)) targetBlockquote = 0; }
VisiblePosition endOfParagraph(const VisiblePosition &c) { if (c.isNull()) return VisiblePosition(); Position p = c.deepEquivalent(); Node* startNode = p.node(); if (isRenderedAsNonInlineTableImageOrHR(startNode)) return lastDeepEditingPositionForNode(startNode); Node* startBlock = enclosingBlock(startNode); Node *stayInsideBlock = startBlock; Node *node = startNode; int offset = p.deprecatedEditingOffset(); Node *n = startNode; while (n) { if (n->isContentEditable() != startNode->isContentEditable()) break; RenderObject *r = n->renderer(); if (!r) { n = n->traverseNextNode(stayInsideBlock); continue; } RenderStyle *style = r->style(); if (style->visibility() != VISIBLE) { n = n->traverseNextNode(stayInsideBlock); continue; } if (r->isBR() || isBlock(n)) break; // FIXME: We avoid returning a position where the renderer can't accept the caret. // We should probably do this in other cases such as startOfParagraph. if (r->isText() && r->caretMaxRenderedOffset() > 0) { int length = toRenderText(r)->textLength(); if (style->preserveNewline()) { const UChar* chars = toRenderText(r)->characters(); int o = n == startNode ? offset : 0; for (int i = o; i < length; ++i) if (chars[i] == '\n') return VisiblePosition(n, i, DOWNSTREAM); } node = n; offset = r->caretMaxOffset(); n = n->traverseNextNode(stayInsideBlock); } else if (editingIgnoresContent(n) || isTableElement(n)) { node = n; offset = lastOffsetForEditing(n); n = n->traverseNextSibling(stayInsideBlock); } else n = n->traverseNextNode(stayInsideBlock); } return VisiblePosition(node, offset, DOWNSTREAM); }
VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition) { Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent()); if (!highestRoot) return VisiblePosition(); return VisiblePosition(highestRoot, maxDeepOffset(highestRoot), DOWNSTREAM); }
bool isLastVisiblePositionInNode(const VisiblePosition &pos, const NodeImpl *node) { if (pos.isNull()) return false; VisiblePosition next = pos.next(); return next.isNull() || !next.deepEquivalent().node()->isAncestor(node); }
VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition) { Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent()); if (!highestRoot) return VisiblePosition(); return lastDeepEditingPositionForNode(highestRoot); }
VisiblePosition startOfBlock(const VisiblePosition &c) { Position p = c.deepEquivalent(); Node *startNode = p.node(); if (!startNode) return VisiblePosition(); return VisiblePosition(Position(startNode->enclosingBlockFlowElement(), 0), DOWNSTREAM); }
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)); return TextIterator::rangeLength(range.get(), true); }
void VisibleSelection::setBase(const VisiblePosition& visiblePosition) { Position oldBase = m_base; m_base = visiblePosition.deepEquivalent(); validate(); if (m_base != oldBase) didChange(); }
bool InsertListCommand::selectionHasListOfType(const VisibleSelection& selection, const HTMLQualifiedName& listTag) { VisiblePosition start = selection.visibleStart(); if (!enclosingList(start.deepEquivalent().deprecatedNode())) return false; VisiblePosition end = startOfParagraph(selection.visibleEnd()); while (start.isNotNull() && start != end) { HTMLElement* listElement = enclosingList(start.deepEquivalent().deprecatedNode()); if (!listElement || !listElement->hasTagName(listTag)) return false; start = startOfNextParagraph(start); } return true; }
bool visiblePositionsOnDifferentLines(const VisiblePosition &pos1, const VisiblePosition &pos2) { if (pos1.isNull() || pos2.isNull()) return false; if (pos1 == pos2) return false; Position p1 = pos1.deepEquivalent(); Position p2 = pos2.deepEquivalent(); RenderObject *r1 = p1.node()->renderer(); RenderObject *r2 = p2.node()->renderer(); if (r1->isBlockFlow() || r2->isBlockFlow()) return r1 == r2 ? false : true; InlineBox *b1 = r1 ? r1->inlineBox(p1.offset(), pos1.affinity()) : 0; InlineBox *b2 = r2 ? r2->inlineBox(p2.offset(), pos2.affinity()) : 0; return (b1 && b2 && b1->root() != b2->root()); }
bool isFirstVisiblePositionInBlock(const VisiblePosition &pos) { if (pos.isNull()) return false; Position upstream = pos.deepEquivalent().upstream(StayInBlock); return upstream.node()->isBlockFlow() && upstream.offset() == 0; }
bool isFirstVisiblePositionInNode(const VisiblePosition &pos, const NodeImpl *node) { if (pos.isNull()) return false; VisiblePosition previous = pos.previous(); return previous.isNull() || !previous.deepEquivalent().node()->isAncestor(node); }
void VisibleSelection::setExtent(const VisiblePosition& visiblePosition) { Position oldExtent = m_extent; m_extent = visiblePosition.deepEquivalent(); validate(); if (m_extent != oldExtent) didChange(); }
VisiblePosition startOfParagraph(const VisiblePosition& c) { Position p = c.deepEquivalent(); Node *startNode = p.node(); if (!startNode) return VisiblePosition(); if (isRenderedAsNonInlineTableImageOrHR(startNode)) return firstDeepEditingPositionForNode(startNode); Node* startBlock = enclosingBlock(startNode); Node *node = startNode; int offset = p.deprecatedEditingOffset(); Node *n = startNode; while (n) { if (n->isContentEditable() != startNode->isContentEditable()) break; RenderObject *r = n->renderer(); if (!r) { n = n->traversePreviousNodePostOrder(startBlock); continue; } RenderStyle *style = r->style(); if (style->visibility() != VISIBLE) { n = n->traversePreviousNodePostOrder(startBlock); continue; } if (r->isBR() || isBlock(n)) break; if (r->isText()) { if (style->preserveNewline()) { const UChar* chars = toRenderText(r)->characters(); int i = toRenderText(r)->textLength(); int o = offset; if (n == startNode && o < i) i = max(0, o); while (--i >= 0) if (chars[i] == '\n') return VisiblePosition(n, i + 1, DOWNSTREAM); } node = n; offset = 0; n = n->traversePreviousNodePostOrder(startBlock); } else if (editingIgnoresContent(n) || isTableElement(n)) { node = n; offset = 0; n = n->previousSibling() ? n->previousSibling() : n->traversePreviousNodePostOrder(startBlock); } else n = n->traversePreviousNodePostOrder(startBlock); } return VisiblePosition(node, offset, DOWNSTREAM); }
void ApplyBlockElementCommand::rangeForParagraphSplittingTextNodesIfNeeded(const VisiblePosition& endOfCurrentParagraph, Position& start, Position& end) { start = startOfParagraph(endOfCurrentParagraph).deepEquivalent(); end = endOfCurrentParagraph.deepEquivalent(); bool isStartAndEndOnSameNode = false; if (RenderStyle* startStyle = renderStyleOfEnclosingTextNode(start)) { isStartAndEndOnSameNode = renderStyleOfEnclosingTextNode(end) && start.containerNode() == end.containerNode(); bool isStartAndEndOfLastParagraphOnSameNode = renderStyleOfEnclosingTextNode(m_endOfLastParagraph) && start.containerNode() == m_endOfLastParagraph.containerNode(); // Avoid obtanining the start of next paragraph for start if (startStyle->preserveNewline() && isNewLineAtPosition(start) && !isNewLineAtPosition(start.previous()) && start.offsetInContainerNode() > 0) start = startOfParagraph(end.previous()).deepEquivalent(); // If start is in the middle of a text node, split. if (!startStyle->collapseWhiteSpace() && start.offsetInContainerNode() > 0) { int startOffset = start.offsetInContainerNode(); Text* startText = start.containerText(); splitTextNode(startText, startOffset); start = firstPositionInNode(startText); if (isStartAndEndOnSameNode) { ASSERT(end.offsetInContainerNode() >= startOffset); end = Position(startText, end.offsetInContainerNode() - startOffset); } if (isStartAndEndOfLastParagraphOnSameNode) { ASSERT(m_endOfLastParagraph.offsetInContainerNode() >= startOffset); m_endOfLastParagraph = Position(startText, m_endOfLastParagraph.offsetInContainerNode() - startOffset); } } } if (RenderStyle* endStyle = renderStyleOfEnclosingTextNode(end)) { bool isEndAndEndOfLastParagraphOnSameNode = renderStyleOfEnclosingTextNode(m_endOfLastParagraph) && end.deprecatedNode() == m_endOfLastParagraph.deprecatedNode(); // Include \n at the end of line if we're at an empty paragraph if (endStyle->preserveNewline() && start == end && end.offsetInContainerNode() < end.containerNode()->maxCharacterOffset()) { int endOffset = end.offsetInContainerNode(); if (!isNewLineAtPosition(end.previous()) && isNewLineAtPosition(end)) end = Position(end.containerText(), endOffset + 1); if (isEndAndEndOfLastParagraphOnSameNode && end.offsetInContainerNode() >= m_endOfLastParagraph.offsetInContainerNode()) m_endOfLastParagraph = end; } // If end is in the middle of a text node and the text node is editable, split. if (endStyle->userModify() != READ_ONLY && !endStyle->collapseWhiteSpace() && end.offsetInContainerNode() && end.offsetInContainerNode() < end.containerNode()->maxCharacterOffset()) { RefPtr<Text> endContainer = end.containerText(); splitTextNode(endContainer, end.offsetInContainerNode()); if (isStartAndEndOnSameNode) start = firstPositionInOrBeforeNode(endContainer->previousSibling()); if (isEndAndEndOfLastParagraphOnSameNode) { if (m_endOfLastParagraph.offsetInContainerNode() == end.offsetInContainerNode()) m_endOfLastParagraph = lastPositionInOrAfterNode(endContainer->previousSibling()); else m_endOfLastParagraph = Position(endContainer, m_endOfLastParagraph.offsetInContainerNode() - end.offsetInContainerNode()); } end = lastPositionInNode(endContainer->previousSibling()); } } }
int indexForVisiblePosition(const VisiblePosition& visiblePosition) { if (visiblePosition.isNull()) return 0; Position p(visiblePosition.deepEquivalent()); RefPtr<Range> range = Range::create(p.anchorNode()->document(), firstPositionInNode(p.anchorNode()->document()->documentElement()), p.parentAnchoredEquivalent()); return TextIterator::rangeLength(range.get(), true); }
bool setEnd(Range *r, const VisiblePosition &visiblePosition) { if (!r) return false; Position p = visiblePosition.deepEquivalent().parentAnchoredEquivalent(); int code = 0; r->setEnd(p.containerNode(), p.offsetInContainerNode(), code); return code == 0; }
bool setEnd(Range *r, const VisiblePosition &visiblePosition) { if (!r) return false; Position p = visiblePosition.deepEquivalent().parentAnchoredEquivalent(); TrackExceptionState exceptionState; r->setEnd(p.containerNode(), p.offsetInContainerNode(), exceptionState); return !exceptionState.hadException(); }
bool InsertListCommand::modifyRange() { VisibleSelection selection = selectionForParagraphIteration(endingSelection()); ASSERT(selection.isRange()); VisiblePosition startOfSelection = selection.visibleStart(); VisiblePosition endOfSelection = selection.visibleEnd(); VisiblePosition startOfLastParagraph = startOfParagraph(endOfSelection); if (startOfParagraph(startOfSelection) == startOfLastParagraph) return false; Node* startList = enclosingList(startOfSelection.deepEquivalent().node()); Node* endList = enclosingList(endOfSelection.deepEquivalent().node()); if (!startList || startList != endList) m_forceCreateList = true; setEndingSelection(startOfSelection); doApply(); // Fetch the start of the selection after moving the first paragraph, // because moving the paragraph will invalidate the original start. // We'll use the new start to restore the original selection after // we modified all selected paragraphs. startOfSelection = endingSelection().visibleStart(); VisiblePosition startOfCurrentParagraph = startOfNextParagraph(startOfSelection); while (startOfCurrentParagraph != startOfLastParagraph) { // doApply() may operate on and remove the last paragraph of the selection from the document // if it's in the same list item as startOfCurrentParagraph. Return early to avoid an // infinite loop and because there is no more work to be done. // FIXME(<rdar://problem/5983974>): The endingSelection() may be incorrect here. Compute // the new location of endOfSelection and use it as the end of the new selection. if (!startOfLastParagraph.deepEquivalent().node()->inDocument()) return true; setEndingSelection(startOfCurrentParagraph); doApply(); startOfCurrentParagraph = startOfNextParagraph(endingSelection().visibleStart()); } setEndingSelection(endOfSelection); doApply(); // Fetch the end of the selection, for the reason mentioned above. endOfSelection = endingSelection().visibleEnd(); setEndingSelection(VisibleSelection(startOfSelection, endOfSelection)); m_forceCreateList = false; return true; }
void IndentOutdentCommand::outdentParagraph() { VisiblePosition visibleStartOfParagraph = startOfParagraph(endingSelection().visibleStart()); VisiblePosition visibleEndOfParagraph = endOfParagraph(visibleStartOfParagraph); Node* enclosingNode = enclosingNodeOfType(visibleStartOfParagraph.deepEquivalent(), &isListOrIndentBlockquote); if (!enclosingNode) return; // Use InsertListCommand to remove the selection from the list if (enclosingNode->hasTagName(olTag)) { applyCommandToComposite(InsertListCommand::create(document(), InsertListCommand::OrderedList, "")); return; } if (enclosingNode->hasTagName(ulTag)) { applyCommandToComposite(InsertListCommand::create(document(), InsertListCommand::UnorderedList, "")); return; } // The selection is inside a blockquote VisiblePosition positionInEnclosingBlock = VisiblePosition(Position(enclosingNode, 0)); VisiblePosition startOfEnclosingBlock = startOfBlock(positionInEnclosingBlock); VisiblePosition endOfEnclosingBlock = endOfBlock(positionInEnclosingBlock); if (visibleStartOfParagraph == startOfEnclosingBlock && visibleEndOfParagraph == endOfEnclosingBlock) { // The blockquote doesn't contain anything outside the paragraph, so it can be totally removed. removeNodePreservingChildren(enclosingNode); updateLayout(); visibleStartOfParagraph = VisiblePosition(visibleStartOfParagraph.deepEquivalent()); visibleEndOfParagraph = VisiblePosition(visibleEndOfParagraph.deepEquivalent()); if (visibleStartOfParagraph.isNotNull() && !isStartOfParagraph(visibleStartOfParagraph)) insertNodeAt(createBreakElement(document()), visibleStartOfParagraph.deepEquivalent()); if (visibleEndOfParagraph.isNotNull() && !isEndOfParagraph(visibleEndOfParagraph)) insertNodeAt(createBreakElement(document()), visibleEndOfParagraph.deepEquivalent()); return; } Node* enclosingBlockFlow = enclosingBlockFlowElement(visibleStartOfParagraph); RefPtr<Node> splitBlockquoteNode = enclosingNode; if (enclosingBlockFlow != enclosingNode) splitBlockquoteNode = splitTreeToNode(enclosingBlockFlowElement(visibleStartOfParagraph), enclosingNode, true); RefPtr<Node> placeholder = createBreakElement(document()); insertNodeBefore(placeholder, splitBlockquoteNode); moveParagraph(startOfParagraph(visibleStartOfParagraph), endOfParagraph(visibleEndOfParagraph), VisiblePosition(Position(placeholder.get(), 0)), true); }
// TODO(yosin) We should move |HitTestResult::isMisspelled()| to // "SelectionController.cpp" as static function. bool HitTestResult::isMisspelled() const { if (!innerNode() || !innerNode()->layoutObject()) return false; VisiblePosition pos = createVisiblePosition(innerNode()->layoutObject()->positionForPoint(localPoint())); if (pos.isNull()) return false; return m_innerNode->document().markers().markersInRange( EphemeralRange(pos.deepEquivalent().parentAnchoredEquivalent()), DocumentMarker::MisspellingMarkers()).size() > 0; }
int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const { Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent(); if (enclosingTextFormControl(indexPosition) != this) return 0; RefPtr<Range> range = Range::create(indexPosition.document()); range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION); range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainerNode(), ASSERT_NO_EXCEPTION); return TextIterator::rangeLength(range.get()); }
VisiblePosition VisiblePosition::skipToStartOfEditingBoundary(const VisiblePosition &pos) const { if (pos.isNull()) return pos; ContainerNode* highestRoot = highestEditableRoot(deepEquivalent()); ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); // Return pos itself if the two are from the very same editable region, or both are non-editable. if (highestRootOfPos == highestRoot) return pos; // If this is not editable but |pos| has an editable root, skip to the start if (!highestRoot && highestRootOfPos) return VisiblePosition(previousVisuallyDistinctCandidate(Position(highestRootOfPos, PositionAnchorType::BeforeAnchor).parentAnchoredEquivalent())); // That must mean that |pos| is not editable. Return the last position before pos that is in the same editable region as this position return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(), highestRoot); }
VisiblePosition VisiblePosition::skipToEndOfEditingBoundary(const VisiblePosition &pos) const { if (pos.isNull()) return pos; ContainerNode* highestRoot = highestEditableRoot(deepEquivalent()); ContainerNode* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); // Return pos itself if the two are from the very same editable region, or both are non-editable. if (highestRootOfPos == highestRoot) return pos; // If this is not editable but |pos| has an editable root, skip to the end if (!highestRoot && highestRootOfPos) return VisiblePosition(Position(highestRootOfPos, PositionAnchorType::AfterAnchor).parentAnchoredEquivalent()); // That must mean that |pos| is not editable. Return the next position after pos that is in the same editable region as this position return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot); }
VisiblePosition SelectionEditor::nextWordPositionForPlatform(const VisiblePosition &originalPosition) { VisiblePosition positionAfterCurrentWord = nextWordPosition(originalPosition); if (frame() && frame()->editor().behavior().shouldSkipSpaceWhenMovingRight()) { // In order to skip spaces when moving right, we advance one // word further and then move one word back. Given the // semantics of previousWordPosition() this will put us at the // beginning of the word following. VisiblePosition positionAfterSpacingAndFollowingWord = nextWordPosition(positionAfterCurrentWord); if (positionAfterSpacingAndFollowingWord.isNotNull() && positionAfterSpacingAndFollowingWord.deepEquivalent() != positionAfterCurrentWord.deepEquivalent()) positionAfterCurrentWord = previousWordPosition(positionAfterSpacingAndFollowingWord); bool movingBackwardsMovedPositionToStartOfCurrentWord = positionAfterCurrentWord.deepEquivalent() == previousWordPosition(nextWordPosition(originalPosition)).deepEquivalent(); if (movingBackwardsMovedPositionToStartOfCurrentWord) positionAfterCurrentWord = positionAfterSpacingAndFollowingWord; } return positionAfterCurrentWord; }
VisiblePosition SelectionModifier::modifyMovingForward( TextGranularity granularity) { VisiblePosition pos; // FIXME: Stay in editable content for the less common granularities. switch (granularity) { case CharacterGranularity: if (m_selection.isRange()) pos = createVisiblePosition(m_selection.end(), m_selection.affinity()); else pos = nextPositionOf( createVisiblePosition(m_selection.extent(), m_selection.affinity()), CanSkipOverEditingBoundary); break; case WordGranularity: pos = nextWordPositionForPlatform( createVisiblePosition(m_selection.extent(), m_selection.affinity())); break; case SentenceGranularity: pos = nextSentencePosition( createVisiblePosition(m_selection.extent(), m_selection.affinity())); break; case LineGranularity: { // down-arrowing from a range selection that ends at the start of a line // needs to leave the selection at that line start (no need to call // nextLinePosition!) pos = endForPlatform(); if (!m_selection.isRange() || !isStartOfLine(pos)) pos = nextLinePosition( pos, lineDirectionPointForBlockDirectionNavigation(START)); break; } case ParagraphGranularity: pos = nextParagraphPosition( endForPlatform(), lineDirectionPointForBlockDirectionNavigation(START)); break; case SentenceBoundary: pos = endOfSentence(endForPlatform()); break; case LineBoundary: pos = logicalEndOfLine(endForPlatform()); break; case ParagraphBoundary: pos = endOfParagraph(endForPlatform()); break; case DocumentBoundary: pos = endForPlatform(); if (isEditablePosition(pos.deepEquivalent())) pos = endOfEditableContent(pos); else pos = endOfDocument(pos); break; } return pos; }
static void adjustPositionForUserSelectAll(VisiblePosition& pos, bool isForward) { if (Node* rootUserSelectAll = EditingStrategy::rootUserSelectAllForNode( pos.deepEquivalent().anchorNode())) pos = createVisiblePosition( isForward ? mostForwardCaretPosition(Position::afterNode(rootUserSelectAll), CanCrossEditingBoundary) : mostBackwardCaretPosition(Position::beforeNode(rootUserSelectAll), CanCrossEditingBoundary)); }