本文整理汇总了C++中VisibleSelection函数的典型用法代码示例。如果您正苦于以下问题:C++ VisibleSelection函数的具体用法?C++ VisibleSelection怎么用?C++ VisibleSelection使用的例子?那么, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了VisibleSelection函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: TEST_F
// Make sure we switch to word granularity right away when starting on a
// word boundary and extending.
TEST_F(GranularityStrategyTest, DirectionSwitchStartOnBoundary)
{
dummyPageHolder().frame().settings()->setDefaultFontSize(12);
String str = "ab cd efghijkl mnopqr iiin, abc";
RawPtr<Text> text = document().createTextNode(str);
document().body()->appendChild(text);
dummyPageHolder().frame().settings()->setSelectionStrategy(SelectionStrategy::Direction);
parseText(text.get());
// "ab cd efghijkl ^mnopqr |>stuvwi inm," (^ means base and | means extent,
// > means end).
selection().setSelection(VisibleSelection(Position(text, 15), Position(text, 22)));
EXPECT_EQ_SELECTED_TEXT("mnopqr ");
selection().moveRangeSelectionExtent(m_wordMiddles[4]);
EXPECT_EQ_SELECTED_TEXT("mnopqr iiin");
}
示例2: toPositionInDOMTree
// TODO(yosin): We should make |adjustSelectionInDOMTree()| to return
// |VisibleSelection| once |VisibleSelection| constructor doesn't call
// |validate()|.
void SelectionAdjuster::adjustSelectionInDOMTree(
VisibleSelection* selection,
const VisibleSelectionInFlatTree& selectionInFlatTree) {
if (selectionInFlatTree.isNone()) {
*selection = VisibleSelection();
return;
}
const Position& base = toPositionInDOMTree(selectionInFlatTree.base());
const Position& extent = toPositionInDOMTree(selectionInFlatTree.extent());
if (isCrossingShadowBoundaries(selectionInFlatTree)) {
DCHECK(base.document());
// TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
// needs to be audited. See http://crbug.com/590369 for more details.
// This layout update call cannot be hoisted out of the |if|, otherwise it's
// going to cause performance regression (http://crbug.com/652301).
// TODO(yosin): Implement and apply lazy visible selection validation so
// that we don't need to update layout here.
base.document()->updateStyleAndLayoutIgnorePendingStylesheets();
*selection = createVisibleSelection(
SelectionInDOMTree::Builder().setBaseAndExtent(base, extent).build());
return;
}
const Position& position1 = toPositionInDOMTree(selectionInFlatTree.start());
const Position& position2 = toPositionInDOMTree(selectionInFlatTree.end());
selection->m_base = base;
selection->m_extent = extent;
selection->m_affinity = selectionInFlatTree.m_affinity;
selection->m_isDirectional = selectionInFlatTree.m_isDirectional;
selection->m_granularity = selectionInFlatTree.m_granularity;
selection->m_hasTrailingWhitespace =
selectionInFlatTree.m_hasTrailingWhitespace;
selection->m_baseIsFirst = base.isNull() || base.compareTo(extent) <= 0;
if (position1.compareTo(position2) <= 0) {
selection->m_start = position1;
selection->m_end = position2;
} else {
selection->m_start = position2;
selection->m_end = position1;
}
selection->updateSelectionType();
}
示例3: applyStyledElement
void CreateLinkCommand::doApply()
{
if (endingSelection().isNone())
return;
RefPtrWillBeRawPtr<HTMLAnchorElement> anchorElement = HTMLAnchorElement::create(document());
anchorElement->setHref(AtomicString(m_url));
if (endingSelection().isRange()) {
applyStyledElement(anchorElement.get());
} else {
insertNodeAt(anchorElement.get(), endingSelection().start());
RefPtrWillBeRawPtr<Text> textNode = Text::create(document(), m_url);
appendNode(textNode.get(), anchorElement.get());
setEndingSelection(VisibleSelection(positionInParentBeforeNode(*anchorElement), positionInParentAfterNode(*anchorElement), TextAffinity::Downstream, endingSelection().isDirectional()));
}
}
示例4: applyStyledElement
void CreateLinkCommand::doApply()
{
if (endingSelection().isNone())
return;
RefPtr<HTMLAnchorElement> anchorElement = HTMLAnchorElement::create(document());
anchorElement->setHref(m_url);
if (endingSelection().isRange())
applyStyledElement(anchorElement.release());
else {
insertNodeAt(anchorElement.get(), endingSelection().start());
RefPtr<Text> textNode = Text::create(document(), m_url);
appendNode(textNode.release(), anchorElement.get());
setEndingSelection(VisibleSelection(positionInParentBeforeNode(anchorElement.get()), positionInParentAfterNode(anchorElement.get()), DOWNSTREAM, endingSelection().isDirectional()));
}
}
示例5: endingSelection
// This avoids the expense of a full fledged delete operation, and avoids a layout that typically results
// from text removal.
bool InsertTextCommand::performTrivialReplace(const String& text, bool selectInsertedText)
{
if (!endingSelection().isRange())
return false;
if (text.contains('\t') || text.contains(' ') || text.contains('\n'))
return false;
Position start = endingSelection().start();
Position endPosition = replaceSelectedTextInNode(text);
if (endPosition.isNull())
return false;
setEndingSelectionWithoutValidation(start, endPosition);
if (!selectInsertedText)
setEndingSelection(VisibleSelection(endingSelection().visibleEnd(), endingSelection().isDirectional()));
return true;
}
示例6: TEST_F
// DirectionGranularityStrategy strategy on rotated text should revert to the
// same behavior as CharacterGranularityStrategy
TEST_F(GranularityStrategyTest, DirectionRotate)
{
RefPtrWillBeRawPtr<Text> text = setupRotate("Foo Bar Baz,");
// "Foo B^a|>r Baz," (^ means base, | means extent, , < means start, and > means end).
selection().setSelection(VisibleSelection(Position(text, 5), Position(text, 6)));
EXPECT_EQ_SELECTED_TEXT("a");
IntPoint p = m_letterPos[9];
// Need to move by one pixel, otherwise this point is not evaluated
// to the same line as the text by hit testing.
p.move(1, 0);
// "Foo B^ar B|>az,"
selection().moveRangeSelectionExtent(p);
EXPECT_EQ_SELECTED_TEXT("ar B");
p = m_letterPos[1];
p.move(1, 0);
// "F<|oo B^ar Baz,"
selection().moveRangeSelectionExtent(p);
EXPECT_EQ_SELECTED_TEXT("oo B");
}
示例7: TEST_F
TEST_F(FrameSelectionTest, MoveRangeSelectionTest)
{
// "Foo Bar Baz,"
RefPtrWillBeRawPtr<Text> text = appendTextNode("Foo Bar Baz,");
// Itinitializes with "Foo B|a>r Baz," (| means start and > means end).
selection().setSelection(VisibleSelection(Position(text, 5), Position(text, 6)));
EXPECT_EQ_SELECTED_TEXT("a");
// "Foo B|ar B>az," with the Character granularity.
selection().moveRangeSelection(VisiblePosition(Position(text, 5)), VisiblePosition(Position(text, 9)), CharacterGranularity);
EXPECT_EQ_SELECTED_TEXT("ar B");
// "Foo B|ar B>az," with the Word granularity.
selection().moveRangeSelection(VisiblePosition(Position(text, 5)), VisiblePosition(Position(text, 9)), WordGranularity);
EXPECT_EQ_SELECTED_TEXT("Bar Baz");
// "Fo<o B|ar Baz," with the Character granularity.
selection().moveRangeSelection(VisiblePosition(Position(text, 5)), VisiblePosition(Position(text, 2)), CharacterGranularity);
EXPECT_EQ_SELECTED_TEXT("o B");
// "Fo<o B|ar Baz," with the Word granularity.
selection().moveRangeSelection(VisiblePosition(Position(text, 5)), VisiblePosition(Position(text, 2)), WordGranularity);
EXPECT_EQ_SELECTED_TEXT("Foo Bar");
}
示例8: firstPositionInNode
PassRefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
{
if (target.isEmpty())
return nullptr;
// Start from an edge of the reference range. Which edge is used depends on whether we're searching forward or
// backward, and whether startInSelection is set.
Position searchStart = firstPositionInNode(m_frame.document());
Position searchEnd = lastPositionInNode(m_frame.document());
bool forward = !(options & Backwards);
bool startInReferenceRange = referenceRange && (options & StartInSelection);
if (referenceRange) {
if (forward)
searchStart = startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition();
else
searchEnd = startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition();
}
RefPtr<Range> resultRange = findStringBetweenPositions(target, searchStart, searchEnd, options);
// If we started in the reference range and the found range exactly matches the reference range, find again.
// Build a selection with the found range to remove collapsed whitespace.
// Compare ranges instead of selection objects to ignore the way that the current selection was made.
if (resultRange && startInReferenceRange && areRangesEqual(VisibleSelection(resultRange.get()).toNormalizedRange().get(), referenceRange)) {
if (forward)
searchStart = resultRange->endPosition();
else
searchEnd = resultRange->startPosition();
resultRange = findStringBetweenPositions(target, searchStart, searchEnd, options);
}
if (!resultRange && options & WrapAround) {
searchStart = firstPositionInNode(m_frame.document());
searchEnd = lastPositionInNode(m_frame.document());
resultRange = findStringBetweenPositions(target, searchStart, searchEnd, options);
}
return resultRange.release();
}
示例9: ASSERT
void MoveSelectionCommand::doApply()
{
ASSERT(endingSelection().isNonOrphanedRange());
Position pos = m_position;
if (pos.isNull())
return;
// Update the position otherwise it may become invalid after the selection is deleted.
Position selectionEnd = endingSelection().end();
if (pos.isOffsetInAnchor() && selectionEnd.isOffsetInAnchor()
&& selectionEnd.computeContainerNode() == pos.computeContainerNode() && selectionEnd.offsetInContainerNode() < pos.offsetInContainerNode()) {
pos = Position(pos.computeContainerNode(), pos.offsetInContainerNode() - selectionEnd.offsetInContainerNode());
Position selectionStart = endingSelection().start();
if (selectionStart.isOffsetInAnchor() && selectionStart.computeContainerNode() == pos.computeContainerNode())
pos = Position(pos.computeContainerNode(), pos.offsetInContainerNode() + selectionStart.offsetInContainerNode());
}
deleteSelection(m_smartDelete);
// If the node for the destination has been removed as a result of the deletion,
// set the destination to the ending point after the deletion.
// Fixes: <rdar://problem/3910425> REGRESSION (Mail): Crash in ReplaceSelectionCommand;
// selection is empty, leading to null deref
if (!pos.inDocument())
pos = endingSelection().start();
cleanupAfterDeletion(VisiblePosition(pos));
setEndingSelection(VisibleSelection(pos, endingSelection().affinity(), endingSelection().isDirectional()));
if (!pos.inDocument()) {
// Document was modified out from under us.
return;
}
ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::PreventNesting;
if (m_smartInsert)
options |= ReplaceSelectionCommand::SmartReplace;
applyCommandToComposite(ReplaceSelectionCommand::create(document(), m_fragment, options));
}
示例10: document
void GranularityStrategyTest::setupTextSpan(String str1, String str2, String str3, size_t selBegin, size_t selEnd)
{
RefPtrWillBeRawPtr<Text> text1 = document().createTextNode(str1);
RefPtrWillBeRawPtr<Text> text2 = document().createTextNode(str2);
RefPtrWillBeRawPtr<Text> text3 = document().createTextNode(str3);
RefPtrWillBeRawPtr<Element> span = HTMLSpanElement::create(document());
Element* div = document().getElementById("mytext");
div->appendChild(text1);
div->appendChild(span);
span->appendChild(text2);
div->appendChild(text3);
document().view()->updateAllLifecyclePhases();
Vector<IntPoint> letterPos;
Vector<IntPoint> wordMiddlePos;
TextNodeVector textNodes;
textNodes.append(text1);
textNodes.append(text2);
textNodes.append(text3);
parseText(textNodes);
Position p1;
Position p2;
if (selBegin < str1.length())
p1 = Position(text1, selBegin);
else if (selBegin < str1.length() + str2.length())
p1 = Position(text2, selBegin - str1.length());
else
p1 = Position(text3, selBegin - str1.length() - str2.length());
if (selEnd < str1.length())
p2 = Position(text1, selEnd);
else if (selEnd < str1.length() + str2.length())
p2 = Position(text2, selEnd - str1.length());
else
p2 = Position(text3, selEnd - str1.length() - str2.length());
selection().setSelection(VisibleSelection(p1, p2));
}
示例11: VisibleSelection
VisibleSelection VisibleSelection::selectionFromContentsOfNode(Node* node)
{
return VisibleSelection(firstDeepEditingPositionForNode(node), lastDeepEditingPositionForNode(node), DOWNSTREAM);
}
示例12: endingSelection
void InsertParagraphSeparatorCommand::doApply()
{
if (!endingSelection().isNonOrphanedCaretOrRange())
return;
Position insertionPosition = endingSelection().start();
EAffinity affinity = endingSelection().affinity();
// Delete the current selection.
if (endingSelection().isRange()) {
calculateStyleBeforeInsertion(insertionPosition);
deleteSelection(false, true);
insertionPosition = endingSelection().start();
affinity = endingSelection().affinity();
}
// FIXME: The parentAnchoredEquivalent conversion needs to be moved into enclosingBlock.
RefPtr<Element> startBlock = enclosingBlock(insertionPosition.parentAnchoredEquivalent().containerNode());
Position canonicalPos = VisiblePosition(insertionPosition).deepEquivalent();
if (!startBlock
|| !startBlock->nonShadowBoundaryParentNode()
// FIXME: If the node is hidden, we don't have a canonical position so we will do the wrong thing for tables and <hr>. https://bugs.webkit.org/show_bug.cgi?id=40342
|| (!canonicalPos.isNull() && isRenderedTableElement(canonicalPos.deprecatedNode()))) {
applyCommandToComposite(InsertLineBreakCommand::create(document()));
return;
}
// Use the leftmost candidate.
insertionPosition = insertionPosition.upstream();
if (!insertionPosition.isCandidate())
insertionPosition = insertionPosition.downstream();
// Adjust the insertion position after the delete
insertionPosition = positionAvoidingSpecialElementBoundary(insertionPosition);
VisiblePosition visiblePos(insertionPosition, affinity);
calculateStyleBeforeInsertion(insertionPosition);
//---------------------------------------------------------------------
// Handle special case of typing return on an empty list item
if (breakOutOfEmptyListItem())
return;
//---------------------------------------------------------------------
// Prepare for more general cases.
bool isFirstInBlock = isStartOfBlock(visiblePos);
bool isLastInBlock = isEndOfBlock(visiblePos);
bool nestNewBlock = false;
// Create block to be inserted.
RefPtr<Element> blockToInsert = nullptr;
if (startBlock->isRootEditableElement()) {
blockToInsert = createDefaultParagraphElement(document());
nestNewBlock = true;
} else if (shouldUseDefaultParagraphElement(startBlock.get())) {
blockToInsert = createDefaultParagraphElement(document());
} else {
blockToInsert = startBlock->cloneElementWithoutChildren();
}
//---------------------------------------------------------------------
// Handle case when position is in the last visible position in its block,
// including when the block is empty.
if (isLastInBlock) {
if (nestNewBlock) {
if (isFirstInBlock && !lineBreakExistsAtVisiblePosition(visiblePos)) {
// The block is empty. Create an empty block to
// represent the paragraph that we're leaving.
RefPtr<HTMLElement> extraBlock = createDefaultParagraphElement(document());
appendNode(extraBlock, startBlock);
}
appendNode(blockToInsert, startBlock);
} else {
// Most of the time we want to stay at the nesting level of the startBlock (e.g., when nesting within lists). However,
// for div nodes, this can result in nested div tags that are hard to break out of.
Element* siblingElement = startBlock.get();
insertNodeAfter(blockToInsert, siblingElement);
}
// Recreate the same structure in the new paragraph.
Vector<RefPtr<Element> > ancestors;
getAncestorsInsideBlock(positionOutsideTabSpan(insertionPosition).deprecatedNode(), startBlock.get(), ancestors);
RefPtr<Element> parent = cloneHierarchyUnderNewBlock(ancestors, blockToInsert);
setEndingSelection(VisibleSelection(firstPositionInNode(parent.get()), DOWNSTREAM, endingSelection().isDirectional()));
return;
}
//---------------------------------------------------------------------
// Handle case when position is in the first visible position in its block, and
// similar case where previous position is in another, presumeably nested, block.
if (isFirstInBlock || !inSameBlock(visiblePos, visiblePos.previous())) {
Node* refNode = 0;
insertionPosition = positionOutsideTabSpan(insertionPosition);
if (isFirstInBlock && !nestNewBlock) {
refNode = startBlock.get();
//.........这里部分代码省略.........
示例13: selection
void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection)
{
// The basic approach is to search in two phases - from the selection end to the end of the doc, and
// then we wrap and search from the doc start to (approximately) where we started.
// Start at the end of the selection, search to edge of document. Starting at the selection end makes
// repeated "check spelling" commands work.
VisibleSelection selection(m_frame.selection().selection());
RefPtr<Range> spellingSearchRange(rangeOfContents(m_frame.document()));
bool startedWithSelection = false;
if (selection.start().deprecatedNode()) {
startedWithSelection = true;
if (startBeforeSelection) {
VisiblePosition start(selection.visibleStart());
// We match AppKit's rule: Start 1 character before the selection.
VisiblePosition oneBeforeStart = start.previous();
setStart(spellingSearchRange.get(), oneBeforeStart.isNotNull() ? oneBeforeStart : start);
} else {
setStart(spellingSearchRange.get(), selection.visibleEnd());
}
}
Position position = spellingSearchRange->startPosition();
if (!isEditablePosition(position)) {
// This shouldn't happen in very often because the Spelling menu items aren't enabled unless the
// selection is editable.
// This can happen in Mail for a mix of non-editable and editable content (like Stationary),
// when spell checking the whole document before sending the message.
// In that case the document might not be editable, but there are editable pockets that need to be spell checked.
position = firstEditableVisiblePositionAfterPositionInRoot(position, m_frame.document()).deepEquivalent();
if (position.isNull())
return;
Position rangeCompliantPosition = position.parentAnchoredEquivalent();
spellingSearchRange->setStart(rangeCompliantPosition.deprecatedNode(), rangeCompliantPosition.deprecatedEditingOffset(), IGNORE_EXCEPTION);
startedWithSelection = false; // won't need to wrap
}
// topNode defines the whole range we want to operate on
ContainerNode* topNode = highestEditableRoot(position);
// FIXME: lastOffsetForEditing() is wrong here if editingIgnoresContent(highestEditableRoot()) returns true (e.g. a <table>)
spellingSearchRange->setEnd(topNode, lastOffsetForEditing(topNode), IGNORE_EXCEPTION);
// If spellingSearchRange starts in the middle of a word, advance to the next word so we start checking
// at a word boundary. Going back by one char and then forward by a word does the trick.
if (startedWithSelection) {
VisiblePosition oneBeforeStart = startVisiblePosition(spellingSearchRange.get(), DOWNSTREAM).previous();
if (oneBeforeStart.isNotNull())
setStart(spellingSearchRange.get(), endOfWord(oneBeforeStart));
// else we were already at the start of the editable node
}
if (spellingSearchRange->collapsed())
return; // nothing to search in
// We go to the end of our first range instead of the start of it, just to be sure
// we don't get foiled by any word boundary problems at the start. It means we might
// do a tiny bit more searching.
Node* searchEndNodeAfterWrap = spellingSearchRange->endContainer();
int searchEndOffsetAfterWrap = spellingSearchRange->endOffset();
int misspellingOffset = 0;
GrammarDetail grammarDetail;
int grammarPhraseOffset = 0;
RefPtr<Range> grammarSearchRange = nullptr;
String badGrammarPhrase;
String misspelledWord;
bool isSpelling = true;
int foundOffset = 0;
String foundItem;
RefPtr<Range> firstMisspellingRange = nullptr;
if (unifiedTextCheckerEnabled()) {
grammarSearchRange = spellingSearchRange->cloneRange();
foundItem = TextCheckingHelper(spellCheckerClient(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
if (isSpelling) {
misspelledWord = foundItem;
misspellingOffset = foundOffset;
} else {
badGrammarPhrase = foundItem;
grammarPhraseOffset = foundOffset;
}
} else {
misspelledWord = TextCheckingHelper(spellCheckerClient(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
grammarSearchRange = spellingSearchRange->cloneRange();
if (!misspelledWord.isEmpty()) {
// Stop looking at start of next misspelled word
CharacterIterator chars(grammarSearchRange.get());
chars.advance(misspellingOffset);
grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset(), IGNORE_EXCEPTION);
}
if (isGrammarCheckingEnabled())
badGrammarPhrase = TextCheckingHelper(spellCheckerClient(), grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
}
// If we found neither bad grammar nor a misspelled word, wrap and try again (but don't bother if we started at the beginning of the
// block rather than at a selection).
//.........这里部分代码省略.........
示例14: ASSERT
void InsertTextCommand::input(const String& text, bool selectInsertedText)
{
ASSERT(text.find('\n') == notFound);
if (!endingSelection().isNonOrphanedCaretOrRange())
return;
// Delete the current selection.
// FIXME: This delete operation blows away the typing style.
if (endingSelection().isRange()) {
if (performTrivialReplace(text, selectInsertedText))
return;
deleteSelection(false, true, true, false);
}
Position startPosition(endingSelection().start());
Position placeholder;
// We want to remove preserved newlines and brs that will collapse (and thus become unnecessary) when content
// is inserted just before them.
// FIXME: We shouldn't really have to do this, but removing placeholders is a workaround for 9661.
// If the caret is just before a placeholder, downstream will normalize the caret to it.
Position downstream(startPosition.downstream());
if (lineBreakExistsAtPosition(downstream)) {
// FIXME: This doesn't handle placeholders at the end of anonymous blocks.
VisiblePosition caret(startPosition);
if (isEndOfBlock(caret) && isStartOfParagraph(caret))
placeholder = downstream;
// Don't remove the placeholder yet, otherwise the block we're inserting into would collapse before
// we get a chance to insert into it. We check for a placeholder now, though, because doing so requires
// the creation of a VisiblePosition, and if we did that post-insertion it would force a layout.
}
// Insert the character at the leftmost candidate.
startPosition = startPosition.upstream();
// It is possible for the node that contains startPosition to contain only unrendered whitespace,
// and so deleteInsignificantText could remove it. Save the position before the node in case that happens.
Position positionBeforeStartNode(positionInParentBeforeNode(startPosition.node()));
deleteInsignificantText(startPosition.upstream(), startPosition.downstream());
if (!startPosition.node()->inDocument())
startPosition = positionBeforeStartNode;
if (!startPosition.isCandidate())
startPosition = startPosition.downstream();
startPosition = positionAvoidingSpecialElementBoundary(startPosition);
Position endPosition;
if (text == "\t") {
endPosition = insertTab(startPosition);
startPosition = endPosition.previous();
if (placeholder.isNotNull())
removePlaceholderAt(placeholder);
m_charactersAdded += 1;
} else {
// Make sure the document is set up to receive text
startPosition = prepareForTextInsertion(startPosition);
if (placeholder.isNotNull())
removePlaceholderAt(placeholder);
Text *textNode = static_cast<Text *>(startPosition.node());
int offset = startPosition.deprecatedEditingOffset();
insertTextIntoNode(textNode, offset, text);
endPosition = Position(textNode, offset + text.length());
// The insertion may require adjusting adjacent whitespace, if it is present.
rebalanceWhitespaceAt(endPosition);
// Rebalancing on both sides isn't necessary if we've inserted a space.
if (text != " ")
rebalanceWhitespaceAt(startPosition);
m_charactersAdded += text.length();
}
// We could have inserted a part of composed character sequence,
// so we are basically treating ending selection as a range to avoid validation.
// <http://bugs.webkit.org/show_bug.cgi?id=15781>
VisibleSelection forcedEndingSelection;
forcedEndingSelection.setWithoutValidation(startPosition, endPosition);
setEndingSelection(forcedEndingSelection);
// Handle the case where there is a typing style.
CSSMutableStyleDeclaration* typingStyle = document()->frame()->selection()->typingStyle();
RefPtr<CSSComputedStyleDeclaration> endingStyle = endPosition.computedStyle();
RefPtr<CSSValue> unicodeBidi;
RefPtr<CSSValue> direction;
if (typingStyle) {
unicodeBidi = typingStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi);
direction = typingStyle->getPropertyCSSValue(CSSPropertyDirection);
}
endingStyle->diff(typingStyle);
if (typingStyle && unicodeBidi) {
ASSERT(unicodeBidi->isPrimitiveValue());
typingStyle->setProperty(CSSPropertyUnicodeBidi, static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent());
if (direction) {
ASSERT(direction->isPrimitiveValue());
typingStyle->setProperty(CSSPropertyDirection, static_cast<CSSPrimitiveValue*>(direction.get())->getIdent());
}
//.........这里部分代码省略.........
示例15: ASSERT
//.........这里部分代码省略.........
// Delete the current selection.
// FIXME: This delete operation blows away the typing style.
if (endingSelection().isRange()) {
if (performTrivialReplace(m_text, m_selectInsertedText))
return;
bool endOfSelectionWasAtStartOfBlock = isStartOfBlock(endingSelection().visibleEnd());
deleteSelection(false, true, false, false);
// deleteSelection eventually makes a new endingSelection out of a Position. If that Position doesn't have
// a renderer (e.g. it is on a <frameset> in the DOM), the VisibleSelection cannot be canonicalized to
// anything other than NoSelection. The rest of this function requires a real endingSelection, so bail out.
if (endingSelection().isNone())
return;
if (endOfSelectionWasAtStartOfBlock) {
if (EditingStyle* typingStyle = document().frame()->selection().typingStyle())
typingStyle->removeBlockProperties();
}
} else if (document().frame()->editor().isOverwriteModeEnabled()) {
if (performOverwrite(m_text, m_selectInsertedText))
return;
}
Position startPosition(endingSelection().start());
Position placeholder;
// We want to remove preserved newlines and brs that will collapse (and thus become unnecessary) when content
// is inserted just before them.
// FIXME: We shouldn't really have to do this, but removing placeholders is a workaround for 9661.
// If the caret is just before a placeholder, downstream will normalize the caret to it.
Position downstream(startPosition.downstream());
if (lineBreakExistsAtPosition(downstream)) {
// FIXME: This doesn't handle placeholders at the end of anonymous blocks.
VisiblePosition caret(startPosition);
if (isEndOfBlock(caret) && isStartOfParagraph(caret))
placeholder = downstream;
// Don't remove the placeholder yet, otherwise the block we're inserting into would collapse before
// we get a chance to insert into it. We check for a placeholder now, though, because doing so requires
// the creation of a VisiblePosition, and if we did that post-insertion it would force a layout.
}
// Insert the character at the leftmost candidate.
startPosition = startPosition.upstream();
// It is possible for the node that contains startPosition to contain only unrendered whitespace,
// and so deleteInsignificantText could remove it. Save the position before the node in case that happens.
ASSERT(startPosition.containerNode());
Position positionBeforeStartNode(positionInParentBeforeNode(*startPosition.containerNode()));
deleteInsignificantText(startPosition, startPosition.downstream());
if (!startPosition.inDocument())
startPosition = positionBeforeStartNode;
if (!startPosition.isCandidate())
startPosition = startPosition.downstream();
startPosition = positionAvoidingSpecialElementBoundary(startPosition);
Position endPosition;
if (m_text == "\t") {
endPosition = insertTab(startPosition);
startPosition = endPosition.previous();
if (placeholder.isNotNull())
removePlaceholderAt(placeholder);
} else {
// Make sure the document is set up to receive m_text
startPosition = positionInsideTextNode(startPosition);
ASSERT(startPosition.anchorType() == Position::PositionIsOffsetInAnchor);
ASSERT(startPosition.containerNode());
ASSERT(startPosition.containerNode()->isTextNode());
if (placeholder.isNotNull())
removePlaceholderAt(placeholder);
RefPtrWillBeRawPtr<Text> textNode = startPosition.containerText();
const unsigned offset = startPosition.offsetInContainerNode();
insertTextIntoNode(textNode, offset, m_text);
endPosition = Position(textNode, offset + m_text.length());
if (m_rebalanceType == RebalanceLeadingAndTrailingWhitespaces) {
// The insertion may require adjusting adjacent whitespace, if it is present.
rebalanceWhitespaceAt(endPosition);
// Rebalancing on both sides isn't necessary if we've inserted only spaces.
if (!shouldRebalanceLeadingWhitespaceFor(m_text))
rebalanceWhitespaceAt(startPosition);
} else {
ASSERT(m_rebalanceType == RebalanceAllWhitespaces);
if (canRebalance(startPosition) && canRebalance(endPosition))
rebalanceWhitespaceOnTextSubstring(textNode, startPosition.offsetInContainerNode(), endPosition.offsetInContainerNode());
}
}
setEndingSelectionWithoutValidation(startPosition, endPosition);
// Handle the case where there is a typing style.
if (RefPtrWillBeRawPtr<EditingStyle> typingStyle = document().frame()->selection().typingStyle()) {
typingStyle->prepareToApplyAt(endPosition, EditingStyle::PreserveWritingDirection);
if (!typingStyle->isEmpty())
applyStyle(typingStyle.get());
}
if (!m_selectInsertedText)
setEndingSelection(VisibleSelection(endingSelection().end(), endingSelection().affinity(), endingSelection().isDirectional()));
}