本文整理汇总了C++中VisibleSelection::visibleStart方法的典型用法代码示例。如果您正苦于以下问题:C++ VisibleSelection::visibleStart方法的具体用法?C++ VisibleSelection::visibleStart怎么用?C++ VisibleSelection::visibleStart使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类VisibleSelection
的用法示例。
在下文中一共展示了VisibleSelection::visibleStart方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: webkitAccessibleTextGetWordForBoundary
static char* webkitAccessibleTextGetWordForBoundary(AtkText* text, int offset, AtkTextBoundary boundaryType, GetTextRelativePosition textPosition, int* startOffset, int* endOffset)
{
AccessibilityObject* coreObject = core(text);
Document* document = coreObject->document();
if (!document)
return emptyTextSelectionAtOffset(0, startOffset, endOffset);
Node* node = getNodeForAccessibilityObject(coreObject);
if (!node)
return emptyTextSelectionAtOffset(0, startOffset, endOffset);
int actualOffset = atkOffsetToWebCoreOffset(text, offset);
// Besides of the usual conversion from ATK offsets to WebCore offsets,
// we need to consider the potential embedded objects that might have been
// inserted in the text exposed through AtkText when calculating the offset.
actualOffset -= numberOfReplacedElementsBeforeOffset(text, actualOffset);
VisiblePosition caretPosition = coreObject->visiblePositionForIndex(actualOffset);
VisibleSelection currentWord = wordAtPositionForAtkBoundary(coreObject, caretPosition, boundaryType);
// Take into account other relative positions, if needed, by
// calculating the new position that we would need to consider.
VisiblePosition newPosition = caretPosition;
switch (textPosition) {
case GetTextPositionAt:
break;
case GetTextPositionBefore:
// Early return if asking for the previous word while already at the beginning.
if (isFirstVisiblePositionInNode(currentWord.visibleStart(), node))
return emptyTextSelectionAtOffset(0, startOffset, endOffset);
if (isStartOfLine(currentWord.end()))
newPosition = currentWord.visibleStart().previous();
else
newPosition = startOfWord(currentWord.start(), LeftWordIfOnBoundary);
break;
case GetTextPositionAfter:
// Early return if asking for the following word while already at the end.
if (isLastVisiblePositionInNode(currentWord.visibleEnd(), node))
return emptyTextSelectionAtOffset(accessibilityObjectLength(coreObject), startOffset, endOffset);
if (isEndOfLine(currentWord.end()))
newPosition = currentWord.visibleEnd().next();
else
newPosition = endOfWord(currentWord.end(), RightWordIfOnBoundary);
break;
default:
ASSERT_NOT_REACHED();
}
// Determine the relevant word we are actually interested in
// and calculate the ATK offsets for it, then return everything.
VisibleSelection selectedWord = newPosition != caretPosition ? wordAtPositionForAtkBoundary(coreObject, newPosition, boundaryType) : currentWord;
getSelectionOffsetsForObject(coreObject, selectedWord, *startOffset, *endOffset);
return webkitAccessibleTextGetText(text, *startOffset, *endOffset);
}
示例2: visibleSelectionForClosestActualWordStart
VisibleSelection visibleSelectionForClosestActualWordStart(const VisibleSelection& selection)
{
// VisibleSelection validation has a special case when the caret is at the end of a paragraph where
// it selects the paragraph marker. As well, if the position is at the end of a word, it will select
// only the space between words. We want to select an actual word so we move the selection to
// the start of the leftmost word if the character after the selection point is whitespace.
if (selection.selectionType() != VisibleSelection::RangeSelection) {
int leftDistance = 0;
int rightDistance = 0;
VisibleSelection leftSelection(previousWordPosition(selection.start()));
bool leftSelectionIsOnWord = !isWhitespace(leftSelection.visibleStart().characterAfter()) && leftSelection.start().containerNode() == selection.start().containerNode();
if (leftSelectionIsOnWord) {
VisibleSelection rangeSelection(endOfWord(leftSelection.start()), selection.visibleStart());
leftDistance = TextIterator::rangeLength(rangeSelection.toNormalizedRange().get());
}
VisibleSelection rightSelection = previousWordPosition(nextWordPosition(selection.start()));
bool rightSelectionIsOnWord = !isWhitespace(rightSelection.visibleStart().characterAfter()) && rightSelection.start().containerNode() == selection.start().containerNode();
if (rightSelectionIsOnWord) {
VisibleSelection rangeSelection = VisibleSelection(rightSelection.visibleStart(), selection.visibleStart());
rightDistance = TextIterator::rangeLength(rangeSelection.toNormalizedRange().get());
}
// Make sure we found an actual word. If not, return the original selection.
if (!leftSelectionIsOnWord && !rightSelectionIsOnWord)
return selection;
if (!rightSelectionIsOnWord || (leftSelectionIsOnWord && leftDistance <= rightDistance)) {
// Left is closer or right is invalid.
return leftSelection;
}
// Right is closer or equal, or left was invalid.
return rightSelection;
}
// No adjustment required.
return selection;
}
示例3: spellCheckOldSelection
void SpellChecker::spellCheckOldSelection(const VisibleSelection& oldSelection, const VisibleSelection& newAdjacentWords)
{
VisiblePosition oldStart(oldSelection.visibleStart());
VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
if (oldAdjacentWords != newAdjacentWords) {
if (isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled()) {
VisibleSelection selectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart));
markMisspellingsAndBadGrammar(oldAdjacentWords, true, selectedSentence);
} else {
markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords);
}
}
}
示例4: respondToChangedSelection
void SpellChecker::respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
{
bool closeTyping = options & FrameSelection::CloseTyping;
bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabled();
bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && isGrammarCheckingEnabled();
if (isContinuousSpellCheckingEnabled) {
VisibleSelection newAdjacentWords;
VisibleSelection newSelectedSentence;
const VisibleSelection newSelection = m_frame.selection().selection();
VisiblePosition newStart(newSelection.visibleStart());
newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
if (isContinuousGrammarCheckingEnabled)
newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart));
// Don't check spelling and grammar if the change of selection is triggered by spelling correction itself.
bool shouldCheckSpellingAndGrammar = !(options & FrameSelection::SpellCorrectionTriggered);
// When typing we check spelling elsewhere, so don't redo it here.
// If this is a change in selection resulting from a delete operation,
// oldSelection may no longer be in the document.
// FIXME(http://crbug.com/382809): if oldSelection is on a textarea
// element, we cause synchronous layout.
if (shouldCheckSpellingAndGrammar
&& closeTyping
&& !isSelectionInTextField(oldSelection)
&& (isSelectionInTextArea(oldSelection) || oldSelection.isContentEditable())
&& oldSelection.start().inDocument()) {
spellCheckOldSelection(oldSelection, newAdjacentWords);
}
// FIXME(http://crbug.com/382809):
// shouldEraseMarkersAfterChangeSelection is true, we cause synchronous
// layout.
if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)) {
if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange())
m_frame.document()->markers().removeMarkers(wordRange.get(), DocumentMarker::Spelling);
}
if (textChecker().shouldEraseMarkersAfterChangeSelection(TextCheckingTypeGrammar)) {
if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange())
m_frame.document()->markers().removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
}
}
// When continuous spell checking is off, existing markers disappear after the selection changes.
if (!isContinuousSpellCheckingEnabled)
m_frame.document()->markers().removeMarkers(DocumentMarker::Spelling);
if (!isContinuousGrammarCheckingEnabled)
m_frame.document()->markers().removeMarkers(DocumentMarker::Grammar);
}
示例5: indentRegion
void IndentOutdentCommand::indentRegion()
{
VisibleSelection selection = selectionForParagraphIteration(endingSelection());
VisiblePosition startOfSelection = selection.visibleStart();
VisiblePosition endOfSelection = selection.visibleEnd();
int startIndex = indexForVisiblePosition(startOfSelection);
int endIndex = indexForVisiblePosition(endOfSelection);
ASSERT(!startOfSelection.isNull());
ASSERT(!endOfSelection.isNull());
// Special case empty unsplittable elements because there's nothing to split
// and there's nothing to move.
Position start = startOfSelection.deepEquivalent().downstream();
if (isAtUnsplittableElement(start)) {
RefPtr<Element> blockquote = createIndentBlockquoteElement(document());
insertNodeAt(blockquote, start);
RefPtr<Element> placeholder = createBreakElement(document());
appendNode(placeholder, blockquote);
setEndingSelection(VisibleSelection(Position(placeholder.get(), 0), DOWNSTREAM));
return;
}
RefPtr<Element> blockquoteForNextIndent;
VisiblePosition endOfCurrentParagraph = endOfParagraph(startOfSelection);
VisiblePosition endAfterSelection = endOfParagraph(endOfParagraph(endOfSelection).next());
while (endOfCurrentParagraph != endAfterSelection) {
// Iterate across the selected paragraphs...
VisiblePosition endOfNextParagraph = endOfParagraph(endOfCurrentParagraph.next());
if (tryIndentingAsListItem(endOfCurrentParagraph))
blockquoteForNextIndent = 0;
else
indentIntoBlockquote(endOfCurrentParagraph, endOfNextParagraph, blockquoteForNextIndent);
// blockquoteForNextIndent maybe updated
// this is due to the way prepareBlockquoteLevelForInsertion was designed.
// Sanity check: Make sure our moveParagraph calls didn't remove endOfNextParagraph.deepEquivalent().node()
// If somehow we did, return to prevent crashes.
if (endOfNextParagraph.isNotNull() && !endOfNextParagraph.deepEquivalent().node()->inDocument()) {
ASSERT_NOT_REACHED();
return;
}
endOfCurrentParagraph = endOfNextParagraph;
}
RefPtr<Range> startRange = TextIterator::rangeFromLocationAndLength(document()->documentElement(), startIndex, 0, true);
RefPtr<Range> endRange = TextIterator::rangeFromLocationAndLength(document()->documentElement(), endIndex, 0, true);
if (startRange && endRange)
setEndingSelection(VisibleSelection(startRange->startPosition(), endRange->startPosition(), DOWNSTREAM));
}
示例6: doApply
void ApplyBlockElementCommand::doApply()
{
if (!endingSelection().rootEditableElement())
return;
VisiblePosition visibleEnd = endingSelection().visibleEnd();
VisiblePosition visibleStart = endingSelection().visibleStart();
if (visibleStart.isNull() || visibleStart.isOrphan() || visibleEnd.isNull() || visibleEnd.isOrphan())
return;
// When a selection ends at the start of a paragraph, we rarely paint
// the selection gap before that paragraph, because there often is no gap.
// In a case like this, it's not obvious to the user that the selection
// ends "inside" that paragraph, so it would be confusing if Indent/Outdent
// operated on that paragraph.
// FIXME: We paint the gap before some paragraphs that are indented with left
// margin/padding, but not others. We should make the gap painting more consistent and
// then use a left margin/padding rule here.
if (visibleEnd != visibleStart && isStartOfParagraph(visibleEnd)) {
VisibleSelection newSelection(visibleStart, visibleEnd.previous(CannotCrossEditingBoundary), endingSelection().isDirectional());
if (newSelection.isNone())
return;
setEndingSelection(newSelection);
}
VisibleSelection selection = selectionForParagraphIteration(endingSelection());
VisiblePosition startOfSelection = selection.visibleStart();
VisiblePosition endOfSelection = selection.visibleEnd();
ASSERT(!startOfSelection.isNull());
ASSERT(!endOfSelection.isNull());
RefPtrWillBeRawPtr<ContainerNode> startScope = nullptr;
int startIndex = indexForVisiblePosition(startOfSelection, startScope);
RefPtrWillBeRawPtr<ContainerNode> endScope = nullptr;
int endIndex = indexForVisiblePosition(endOfSelection, endScope);
formatSelection(startOfSelection, endOfSelection);
document().updateLayoutIgnorePendingStylesheets();
ASSERT(startScope == endScope);
ASSERT(startIndex >= 0);
ASSERT(startIndex <= endIndex);
if (startScope == endScope && startIndex >= 0 && startIndex <= endIndex) {
VisiblePosition start(visiblePositionForIndex(startIndex, startScope.get()));
VisiblePosition end(visiblePositionForIndex(endIndex, endScope.get()));
if (start.isNotNull() && end.isNotNull())
setEndingSelection(VisibleSelection(start, end, endingSelection().isDirectional()));
}
}
示例7: selectionHasListOfType
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;
}
示例8: modifyRange
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;
}
示例9: doApply
void IndentOutdentCommand::doApply()
{
if (!endingSelection().isNonOrphanedCaretOrRange())
return;
if (!endingSelection().rootEditableElement())
return;
VisiblePosition visibleEnd = endingSelection().visibleEnd();
VisiblePosition visibleStart = endingSelection().visibleStart();
// When a selection ends at the start of a paragraph, we rarely paint
// the selection gap before that paragraph, because there often is no gap.
// In a case like this, it's not obvious to the user that the selection
// ends "inside" that paragraph, so it would be confusing if Indent/Outdent
// operated on that paragraph.
// FIXME: We paint the gap before some paragraphs that are indented with left
// margin/padding, but not others. We should make the gap painting more consistent and
// then use a left margin/padding rule here.
if (visibleEnd != visibleStart && isStartOfParagraph(visibleEnd))
setEndingSelection(VisibleSelection(visibleStart, visibleEnd.previous(true)));
VisibleSelection selection = selectionForParagraphIteration(endingSelection());
VisiblePosition startOfSelection = selection.visibleStart();
VisiblePosition endOfSelection = selection.visibleEnd();
int startIndex = indexForVisiblePosition(startOfSelection);
int endIndex = indexForVisiblePosition(endOfSelection);
ASSERT(!startOfSelection.isNull());
ASSERT(!endOfSelection.isNull());
if (m_typeOfAction == Indent)
indentRegion(startOfSelection, endOfSelection);
else
outdentRegion(startOfSelection, endOfSelection);
updateLayout();
RefPtr<Range> startRange = TextIterator::rangeFromLocationAndLength(document()->documentElement(), startIndex, 0, true);
RefPtr<Range> endRange = TextIterator::rangeFromLocationAndLength(document()->documentElement(), endIndex, 0, true);
if (startRange && endRange)
setEndingSelection(VisibleSelection(startRange->startPosition(), endRange->startPosition(), DOWNSTREAM));
}
示例10: markMisspellingsAfterLineBreak
void SpellChecker::markMisspellingsAfterLineBreak(const VisibleSelection& wordSelection)
{
if (unifiedTextCheckerEnabled()) {
TextCheckingTypeMask textCheckingOptions = 0;
if (isContinuousSpellCheckingEnabled())
textCheckingOptions |= TextCheckingTypeSpelling;
if (isGrammarCheckingEnabled())
textCheckingOptions |= TextCheckingTypeGrammar;
VisibleSelection wholeParagraph(
startOfParagraph(wordSelection.visibleStart()),
endOfParagraph(wordSelection.visibleEnd()));
markAllMisspellingsAndBadGrammarInRanges(
textCheckingOptions, wordSelection.toNormalizedRange().get(),
wholeParagraph.toNormalizedRange().get());
} else {
RefPtr<Range> misspellingRange = wordSelection.firstRange();
markMisspellings(wordSelection, misspellingRange);
}
}
示例11: selectionHasListOfType
bool InsertListCommand::selectionHasListOfType(
const VisibleSelection& selection,
const HTMLQualifiedName& listTag) {
DCHECK(!document().needsLayoutTreeUpdate());
DocumentLifecycle::DisallowTransitionScope disallowTransition(
document().lifecycle());
VisiblePosition start = selection.visibleStart();
if (!enclosingList(start.deepEquivalent().anchorNode()))
return false;
VisiblePosition end = startOfParagraph(selection.visibleEnd());
while (start.isNotNull() && start.deepEquivalent() != end.deepEquivalent()) {
HTMLElement* listElement =
enclosingList(start.deepEquivalent().anchorNode());
if (!listElement || !listElement->hasTagName(listTag))
return false;
start = startOfNextParagraph(start);
}
return true;
}
示例12: transpose
void Editor::transpose()
{
if (!canEdit())
return;
VisibleSelection selection = m_frame.selection().selection();
if (!selection.isCaret())
return;
// Make a selection that goes back one character and forward two characters.
VisiblePosition caret = selection.visibleStart();
VisiblePosition next = isEndOfParagraph(caret) ? caret : caret.next();
VisiblePosition previous = next.previous();
if (next == previous)
return;
previous = previous.previous();
if (!inSameParagraph(next, previous))
return;
RefPtr<Range> range = makeRange(previous, next);
if (!range)
return;
VisibleSelection newSelection(range.get(), DOWNSTREAM);
// Transpose the two characters.
String text = plainText(range.get());
if (text.length() != 2)
return;
String transposed = text.right(1) + text.left(1);
// Select the two characters.
if (newSelection != m_frame.selection().selection())
m_frame.selection().setSelection(newSelection);
// Insert the transposed characters.
replaceSelectionWithText(transposed, false, false);
}
示例13: doApply
void InsertLineBreakCommand::doApply()
{
deleteSelection();
VisibleSelection selection = endingSelection();
if (!selection.isNonOrphanedCaretOrRange())
return;
VisiblePosition caret(selection.visibleStart());
// FIXME: If the node is hidden, we should still be able to insert text.
// For now, we return to avoid a crash. https://bugs.webkit.org/show_bug.cgi?id=40342
if (caret.isNull())
return;
Position pos(caret.deepEquivalent());
pos = positionAvoidingSpecialElementBoundary(pos);
pos = positionOutsideTabSpan(pos);
RefPtrWillBeRawPtr<Node> nodeToInsert = nullptr;
if (shouldUseBreakElement(pos))
nodeToInsert = HTMLBRElement::create(document());
else
nodeToInsert = document().createTextNode("\n");
// FIXME: Need to merge text nodes when inserting just after or before text.
if (isEndOfParagraph(caret) && !lineBreakExistsAtVisiblePosition(caret)) {
bool needExtraLineBreak = !isHTMLHRElement(*pos.anchorNode()) && !isHTMLTableElement(*pos.anchorNode());
insertNodeAt(nodeToInsert.get(), pos);
if (needExtraLineBreak)
insertNodeBefore(nodeToInsert->cloneNode(false), nodeToInsert);
VisiblePosition endingPosition = createVisiblePosition(positionBeforeNode(nodeToInsert.get()));
setEndingSelection(VisibleSelection(endingPosition, endingSelection().isDirectional()));
} else if (pos.computeEditingOffset() <= caretMinOffset(pos.anchorNode())) {
insertNodeAt(nodeToInsert.get(), pos);
// Insert an extra br or '\n' if the just inserted one collapsed.
if (!isStartOfParagraph(createVisiblePosition(positionBeforeNode(nodeToInsert.get()))))
insertNodeBefore(nodeToInsert->cloneNode(false).get(), nodeToInsert.get());
setEndingSelection(VisibleSelection(positionInParentAfterNode(*nodeToInsert), TextAffinity::Downstream, endingSelection().isDirectional()));
// If we're inserting after all of the rendered text in a text node, or into a non-text node,
// a simple insertion is sufficient.
} else if (!pos.anchorNode()->isTextNode() || pos.computeOffsetInContainerNode() >= caretMaxOffset(pos.anchorNode())) {
insertNodeAt(nodeToInsert.get(), pos);
setEndingSelection(VisibleSelection(positionInParentAfterNode(*nodeToInsert), TextAffinity::Downstream, endingSelection().isDirectional()));
} else if (pos.anchorNode()->isTextNode()) {
// Split a text node
Text* textNode = toText(pos.anchorNode());
splitTextNode(textNode, pos.computeOffsetInContainerNode());
insertNodeBefore(nodeToInsert, textNode);
Position endingPosition = firstPositionInNode(textNode);
// Handle whitespace that occurs after the split
document().updateLayoutIgnorePendingStylesheets();
// TODO(yosin) |isRenderedCharacter()| should be removed, and we should
// use |VisiblePosition::characterAfter()|.
if (!isRenderedCharacter(endingPosition)) {
Position positionBeforeTextNode(positionInParentBeforeNode(*textNode));
// Clear out all whitespace and insert one non-breaking space
deleteInsignificantTextDownstream(endingPosition);
ASSERT(!textNode->layoutObject() || textNode->layoutObject()->style()->collapseWhiteSpace());
// Deleting insignificant whitespace will remove textNode if it contains nothing but insignificant whitespace.
if (textNode->inDocument()) {
insertTextIntoNode(textNode, 0, nonBreakingSpaceString());
} else {
RefPtrWillBeRawPtr<Text> nbspNode = document().createTextNode(nonBreakingSpaceString());
insertNodeAt(nbspNode.get(), positionBeforeTextNode);
endingPosition = firstPositionInNode(nbspNode.get());
}
}
setEndingSelection(VisibleSelection(endingPosition, TextAffinity::Downstream, endingSelection().isDirectional()));
}
// Handle the case where there is a typing style.
RefPtrWillBeRawPtr<EditingStyle> typingStyle = document().frame()->selection().typingStyle();
if (typingStyle && !typingStyle->isEmpty()) {
// Apply the typing style to the inserted line break, so that if the selection
// leaves and then comes back, new input will have the right style.
// FIXME: We shouldn't always apply the typing style to the line break here,
// see <rdar://problem/5794462>.
applyStyle(typingStyle.get(), firstPositionInOrBeforeNode(nodeToInsert.get()), lastPositionInOrAfterNode(nodeToInsert.get()));
// Even though this applyStyle operates on a Range, it still sets an endingSelection().
// It tries to set a VisibleSelection around the content it operated on. So, that VisibleSelection
// will either (a) select the line break we inserted, or it will (b) be a caret just
// before the line break (if the line break is at the end of a block it isn't selectable).
// So, this next call sets the endingSelection() to a caret just after the line break
// that we inserted, or just before it if it's at the end of a block.
setEndingSelection(endingSelection().visibleEnd());
}
rebalanceWhitespace();
}
示例14: doApply
void InsertLineBreakCommand::doApply(EditingState* editingState) {
deleteSelection(editingState);
if (editingState->isAborted())
return;
document().updateStyleAndLayoutIgnorePendingStylesheets();
VisibleSelection selection = endingSelection();
if (!selection.isNonOrphanedCaretOrRange())
return;
// TODO(xiaochengh): Stop storing VisiblePositions through mutations.
VisiblePosition caret(selection.visibleStart());
// FIXME: If the node is hidden, we should still be able to insert text. For
// now, we return to avoid a crash.
// https://bugs.webkit.org/show_bug.cgi?id=40342
if (caret.isNull())
return;
Position pos(caret.deepEquivalent());
pos = positionAvoidingSpecialElementBoundary(pos, editingState);
if (editingState->isAborted())
return;
pos = positionOutsideTabSpan(pos);
Node* nodeToInsert = nullptr;
if (shouldUseBreakElement(pos))
nodeToInsert = HTMLBRElement::create(document());
else
nodeToInsert = document().createTextNode("\n");
document().updateStyleAndLayoutIgnorePendingStylesheets();
// FIXME: Need to merge text nodes when inserting just after or before text.
if (isEndOfParagraph(createVisiblePosition(caret.toPositionWithAffinity())) &&
!lineBreakExistsAtVisiblePosition(caret)) {
bool needExtraLineBreak = !isHTMLHRElement(*pos.anchorNode()) &&
!isHTMLTableElement(*pos.anchorNode());
insertNodeAt(nodeToInsert, pos, editingState);
if (editingState->isAborted())
return;
if (needExtraLineBreak) {
Node* extraNode;
// TODO(tkent): Can we remove HTMLTextFormControlElement dependency?
if (HTMLTextFormControlElement* textControl =
enclosingTextFormControl(nodeToInsert)) {
extraNode = textControl->createPlaceholderBreakElement();
// The placeholder BR should be the last child. There might be
// empty Text nodes at |pos|.
appendNode(extraNode, nodeToInsert->parentNode(), editingState);
} else {
extraNode = nodeToInsert->cloneNode(false);
insertNodeAfter(extraNode, nodeToInsert, editingState);
}
if (editingState->isAborted())
return;
nodeToInsert = extraNode;
}
setEndingSelection(SelectionInDOMTree::Builder()
.collapse(Position::beforeNode(nodeToInsert))
.setIsDirectional(endingSelection().isDirectional())
.build());
} else if (pos.computeEditingOffset() <= caretMinOffset(pos.anchorNode())) {
insertNodeAt(nodeToInsert, pos, editingState);
if (editingState->isAborted())
return;
document().updateStyleAndLayoutIgnorePendingStylesheets();
// Insert an extra br or '\n' if the just inserted one collapsed.
if (!isStartOfParagraph(VisiblePosition::beforeNode(nodeToInsert))) {
insertNodeBefore(nodeToInsert->cloneNode(false), nodeToInsert,
editingState);
if (editingState->isAborted())
return;
}
setEndingSelection(SelectionInDOMTree::Builder()
.collapse(Position::inParentAfterNode(*nodeToInsert))
.setIsDirectional(endingSelection().isDirectional())
.build());
// If we're inserting after all of the rendered text in a text node, or into
// a non-text node, a simple insertion is sufficient.
} else if (!pos.anchorNode()->isTextNode() ||
pos.computeOffsetInContainerNode() >=
caretMaxOffset(pos.anchorNode())) {
insertNodeAt(nodeToInsert, pos, editingState);
if (editingState->isAborted())
return;
setEndingSelection(SelectionInDOMTree::Builder()
.collapse(Position::inParentAfterNode(*nodeToInsert))
.setIsDirectional(endingSelection().isDirectional())
.build());
} else if (pos.anchorNode()->isTextNode()) {
// Split a text node
//.........这里部分代码省略.........
示例15: doApply
void InsertListCommand::doApply()
{
if (!endingSelection().isNonOrphanedCaretOrRange())
return;
if (!endingSelection().rootEditableElement())
return;
VisiblePosition visibleEnd = endingSelection().visibleEnd();
VisiblePosition visibleStart = endingSelection().visibleStart();
// When a selection ends at the start of a paragraph, we rarely paint
// the selection gap before that paragraph, because there often is no gap.
// In a case like this, it's not obvious to the user that the selection
// ends "inside" that paragraph, so it would be confusing if InsertUn{Ordered}List
// operated on that paragraph.
// FIXME: We paint the gap before some paragraphs that are indented with left
// margin/padding, but not others. We should make the gap painting more consistent and
// then use a left margin/padding rule here.
if (visibleEnd != visibleStart && isStartOfParagraph(visibleEnd, CanSkipOverEditingBoundary)) {
setEndingSelection(VisibleSelection(visibleStart, visibleEnd.previous(CannotCrossEditingBoundary), endingSelection().isDirectional()));
if (!endingSelection().rootEditableElement())
return;
}
const HTMLQualifiedName& listTag = (m_type == OrderedList) ? olTag : ulTag;
if (endingSelection().isRange()) {
bool forceListCreation = false;
VisibleSelection selection = selectionForParagraphIteration(endingSelection());
ASSERT(selection.isRange());
VisiblePosition startOfSelection = selection.visibleStart();
VisiblePosition endOfSelection = selection.visibleEnd();
VisiblePosition startOfLastParagraph = startOfParagraph(endOfSelection, CanSkipOverEditingBoundary);
RefPtrWillBeRawPtr<Range> currentSelection = endingSelection().firstRange();
RefPtrWillBeRawPtr<ContainerNode> scopeForStartOfSelection = nullptr;
RefPtrWillBeRawPtr<ContainerNode> scopeForEndOfSelection = nullptr;
// FIXME: This is an inefficient way to keep selection alive because
// indexForVisiblePosition walks from the beginning of the document to the
// endOfSelection everytime this code is executed. But not using index is hard
// because there are so many ways we can los eselection inside doApplyForSingleParagraph.
int indexForStartOfSelection = indexForVisiblePosition(startOfSelection, scopeForStartOfSelection);
int indexForEndOfSelection = indexForVisiblePosition(endOfSelection, scopeForEndOfSelection);
if (startOfParagraph(startOfSelection, CanSkipOverEditingBoundary) != startOfLastParagraph) {
forceListCreation = !selectionHasListOfType(selection, listTag);
VisiblePosition startOfCurrentParagraph = startOfSelection;
while (startOfCurrentParagraph.isNotNull() && !inSameParagraph(startOfCurrentParagraph, startOfLastParagraph, CanCrossEditingBoundary)) {
// 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().inDocument())
return;
setEndingSelection(startOfCurrentParagraph);
// Save and restore endOfSelection and startOfLastParagraph when necessary
// since moveParagraph and movePragraphWithClones can remove nodes.
doApplyForSingleParagraph(forceListCreation, listTag, *currentSelection);
if (endOfSelection.isNull() || endOfSelection.isOrphan() || startOfLastParagraph.isNull() || startOfLastParagraph.isOrphan()) {
endOfSelection = visiblePositionForIndex(indexForEndOfSelection, scopeForEndOfSelection.get());
// If endOfSelection is null, then some contents have been deleted from the document.
// This should never happen and if it did, exit early immediately because we've lost the loop invariant.
ASSERT(endOfSelection.isNotNull());
if (endOfSelection.isNull() || !endOfSelection.rootEditableElement())
return;
startOfLastParagraph = startOfParagraph(endOfSelection, CanSkipOverEditingBoundary);
}
startOfCurrentParagraph = startOfNextParagraph(endingSelection().visibleStart());
}
setEndingSelection(endOfSelection);
}
doApplyForSingleParagraph(forceListCreation, listTag, *currentSelection);
// Fetch the end of the selection, for the reason mentioned above.
if (endOfSelection.isNull() || endOfSelection.isOrphan()) {
endOfSelection = visiblePositionForIndex(indexForEndOfSelection, scopeForEndOfSelection.get());
if (endOfSelection.isNull())
return;
}
if (startOfSelection.isNull() || startOfSelection.isOrphan()) {
startOfSelection = visiblePositionForIndex(indexForStartOfSelection, scopeForStartOfSelection.get());
if (startOfSelection.isNull())
return;
}
setEndingSelection(VisibleSelection(startOfSelection, endOfSelection, endingSelection().isDirectional()));
return;
}
ASSERT(endingSelection().firstRange());
doApplyForSingleParagraph(false, listTag, *endingSelection().firstRange());
}