static Position previousIfPositionIsAfterLineBreak(const Position& position, HTMLElement* innerEditor) { if (position.isNull()) return Position(); // Move back if position is just after line break. if (isHTMLBRElement(*position.anchorNode())) { if (position.isAfterAnchor()) return Position(position.anchorNode(), PositionAnchorType::BeforeAnchor); if (position.isBeforeAnchor()) return previousIfPositionIsAfterLineBreak(endOfPrevious(*position.anchorNode(), innerEditor), innerEditor); // We don't place caret into BR element, since well-formed BR element // doesn't have child nodes. ASSERT_NOT_REACHED(); return position; } if (!position.anchorNode()->isTextNode()) return position; Text* textNode = toText(position.anchorNode()); unsigned offset = position.offsetInContainerNode(); if (textNode->length() == 0 || offset == 0) return previousIfPositionIsAfterLineBreak(endOfPrevious(*position.anchorNode(), innerEditor), innerEditor); if (offset <= textNode->length() && textNode->data()[offset - 1] == '\n') return Position(textNode, offset - 1); return position; }
static Position previousIfPositionIsAfterLineBreak(const Position& position, HTMLElement* innerEditor) { if (position.isNull()) return Position(); // Move back if position is just after line break. if (isHTMLBRElement(*position.anchorNode())) { switch (position.anchorType()) { case Position::PositionIsAfterAnchor: return Position(position.anchorNode(), Position::PositionIsBeforeAnchor); case Position::PositionIsBeforeAnchor: return previousIfPositionIsAfterLineBreak(endOfPrevious(*position.anchorNode(), innerEditor), innerEditor); default: ASSERT_NOT_REACHED(); } } else if (position.anchorNode()->isTextNode()) { Text* textNode = toText(position.anchorNode()); unsigned offset = position.offsetInContainerNode(); if (textNode->length() == 0 || offset == 0) { return previousIfPositionIsAfterLineBreak(endOfPrevious(*position.anchorNode(), innerEditor), innerEditor); } if (offset <= textNode->length() && textNode->data()[offset - 1] == '\n') { return Position(textNode, offset - 1); } } return position; }
Position HTMLTextFormControlElement::startOfSentence(const Position& position) { HTMLTextFormControlElement* textFormControl = enclosingTextFormControl(position); ASSERT(textFormControl); HTMLElement* innerEditor = textFormControl->innerEditorElement(); if (!innerEditor->childNodes()->length()) return startOfInnerText(textFormControl); const Position innerPosition = position.anchorNode() == innerEditor ? innerNodePosition(position) : position; const Position pivotPosition = previousIfPositionIsAfterLineBreak(innerPosition, innerEditor); if (pivotPosition.isNull()) return startOfInnerText(textFormControl); for (Node* node = pivotPosition.anchorNode(); node; node = NodeTraversal::previous(*node, innerEditor)) { bool isPivotNode = (node == pivotPosition.anchorNode()); if (isHTMLBRElement(node) && (!isPivotNode || pivotPosition.isAfterAnchor())) return Position(node, PositionAnchorType::AfterAnchor); if (node->isTextNode()) { Text* textNode = toText(node); size_t lastLineBreak = textNode->data().substring(0, isPivotNode ? pivotPosition.offsetInContainerNode() : textNode->length()).reverseFind('\n'); if (lastLineBreak != kNotFound) return Position(textNode, lastLineBreak + 1); } } return startOfInnerText(textFormControl); }