📄 typingcommand.cpp
字号:
void TypingCommand::markMisspellingsAfterTyping(){ if (!document()->frame()->editor()->isContinuousSpellCheckingEnabled()) return; // Take a look at the selection that results after typing and determine whether we need to spellcheck. // Since the word containing the current selection is never marked, this does a check to // see if typing made a new word that is not in the current selection. Basically, you // get this by being at the end of a word and typing a space. VisiblePosition start(endingSelection().start(), endingSelection().affinity()); VisiblePosition previous = start.previous(); if (previous.isNotNull()) { VisiblePosition p1 = startOfWord(previous, LeftWordIfOnBoundary); VisiblePosition p2 = startOfWord(start, LeftWordIfOnBoundary); if (p1 != p2) document()->frame()->editor()->markMisspellingsAfterTypingToPosition(p1); }}void TypingCommand::typingAddedToOpenCommand(){ markMisspellingsAfterTyping(); document()->frame()->editor()->appliedEditing(this);}void TypingCommand::insertText(const String &text, bool selectInsertedText){ // FIXME: Need to implement selectInsertedText for cases where more than one insert is involved. // This requires support from insertTextRunWithoutNewlines and insertParagraphSeparator for extending // an existing selection; at the moment they can either put the caret after what's inserted or // select what's inserted, but there's no way to "extend selection" to include both an old selection // that ends just before where we want to insert text and the newly inserted text. int offset = 0; int newline; while ((newline = text.find('\n', offset)) != -1) { if (newline != offset) insertTextRunWithoutNewlines(text.substring(offset, newline - offset), false); insertParagraphSeparator(); offset = newline + 1; } if (offset == 0) insertTextRunWithoutNewlines(text, selectInsertedText); else { int length = text.length(); if (length != offset) { insertTextRunWithoutNewlines(text.substring(offset, length - offset), selectInsertedText); } }}void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool selectInsertedText){ RefPtr<InsertTextCommand> command; if (!document()->frame()->typingStyle() && !m_commands.isEmpty()) { EditCommand* lastCommand = m_commands.last().get(); if (lastCommand->isInsertTextCommand()) command = static_cast<InsertTextCommand*>(lastCommand); } if (!command) { command = InsertTextCommand::create(document()); applyCommandToComposite(command); } command->input(text, selectInsertedText); typingAddedToOpenCommand();}void TypingCommand::insertLineBreak(){ applyCommandToComposite(InsertLineBreakCommand::create(document())); typingAddedToOpenCommand();}void TypingCommand::insertParagraphSeparator(){ applyCommandToComposite(InsertParagraphSeparatorCommand::create(document())); typingAddedToOpenCommand();}void TypingCommand::insertParagraphSeparatorInQuotedContent(){ applyCommandToComposite(BreakBlockquoteCommand::create(document())); typingAddedToOpenCommand();}void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool killRing){ VisibleSelection selectionToDelete; VisibleSelection selectionAfterUndo; switch (endingSelection().selectionType()) { case VisibleSelection::RangeSelection: selectionToDelete = endingSelection(); selectionAfterUndo = selectionToDelete; break; case VisibleSelection::CaretSelection: { if (breakOutOfEmptyMailBlockquotedParagraph()) { typingAddedToOpenCommand(); return; } m_smartDelete = false; SelectionController selection; selection.setSelection(endingSelection()); selection.modify(SelectionController::EXTEND, SelectionController::BACKWARD, granularity); if (killRing && selection.isCaret() && granularity != CharacterGranularity) selection.modify(SelectionController::EXTEND, SelectionController::BACKWARD, CharacterGranularity); // When the caret is at the start of the editable area in an empty list item, break out of the list item. if (endingSelection().visibleStart().previous(true).isNull()) { if (breakOutOfEmptyListItem()) { typingAddedToOpenCommand(); return; } } VisiblePosition visibleStart(endingSelection().visibleStart()); // If the caret is at the start of a paragraph after a table, move content into the last table cell. if (isStartOfParagraph(visibleStart) && isFirstPositionAfterTable(visibleStart.previous(true))) { // Unless the caret is just before a table. We don't want to move a table into the last table cell. if (isLastPositionBeforeTable(visibleStart)) return; // Extend the selection backward into the last cell, then deletion will handle the move. selection.modify(SelectionController::EXTEND, SelectionController::BACKWARD, granularity); // If the caret is just after a table, select the table and don't delete anything. } else if (Node* table = isFirstPositionAfterTable(visibleStart)) { setEndingSelection(VisibleSelection(Position(table, 0), endingSelection().start(), DOWNSTREAM)); typingAddedToOpenCommand(); return; } selectionToDelete = selection.selection(); if (granularity == CharacterGranularity && selectionToDelete.end().node() == selectionToDelete.start().node() && selectionToDelete.end().offset() - selectionToDelete.start().offset() > 1) { // If there are multiple Unicode code points to be deleted, adjust the range to match platform conventions. selectionToDelete.setWithoutValidation(selectionToDelete.end(), selectionToDelete.end().previous(BackwardDeletion)); } if (!startingSelection().isRange() || selectionToDelete.base() != startingSelection().start()) selectionAfterUndo = selectionToDelete; else // It's a little tricky to compute what the starting selection would have been in the original document. // We can't let the VisibleSelection class's validation kick in or it'll adjust for us based on // the current state of the document and we'll get the wrong result. selectionAfterUndo.setWithoutValidation(startingSelection().end(), selectionToDelete.extent()); break; } case VisibleSelection::NoSelection: ASSERT_NOT_REACHED(); break; } ASSERT(!selectionToDelete.isNone()); if (selectionToDelete.isNone()) return; if (selectionToDelete.isCaret() || !document()->frame()->shouldDeleteSelection(selectionToDelete)) return; if (killRing) document()->frame()->editor()->addToKillRing(selectionToDelete.toNormalizedRange().get(), false); // Make undo select everything that has been deleted, unless an undo will undo more than just this deletion. // FIXME: This behaves like TextEdit except for the case where you open with text insertion and then delete // more text than you insert. In that case all of the text that was around originally should be selected. if (m_openedByBackwardDelete) setStartingSelection(selectionAfterUndo); CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete); setSmartDelete(false); typingAddedToOpenCommand();}void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool killRing){ VisibleSelection selectionToDelete; VisibleSelection selectionAfterUndo; switch (endingSelection().selectionType()) { case VisibleSelection::RangeSelection: selectionToDelete = endingSelection(); selectionAfterUndo = selectionToDelete; break; case VisibleSelection::CaretSelection: { m_smartDelete = false; // Handle delete at beginning-of-block case. // Do nothing in the case that the caret is at the start of a // root editable element or at the start of a document. SelectionController selection; selection.setSelection(endingSelection()); selection.modify(SelectionController::EXTEND, SelectionController::FORWARD, granularity); if (killRing && selection.isCaret() && granularity != CharacterGranularity) selection.modify(SelectionController::EXTEND, SelectionController::FORWARD, CharacterGranularity); Position downstreamEnd = endingSelection().end().downstream(); VisiblePosition visibleEnd = endingSelection().visibleEnd(); if (visibleEnd == endOfParagraph(visibleEnd)) downstreamEnd = visibleEnd.next(true).deepEquivalent().downstream(); // When deleting tables: Select the table first, then perform the deletion if (downstreamEnd.node() && downstreamEnd.node()->renderer() && downstreamEnd.node()->renderer()->isTable() && downstreamEnd.offset() == 0) { setEndingSelection(VisibleSelection(endingSelection().end(), Position(downstreamEnd.node(), maxDeepOffset(downstreamEnd.node())), DOWNSTREAM)); typingAddedToOpenCommand(); return; } // deleting to end of paragraph when at end of paragraph needs to merge the next paragraph (if any) if (granularity == ParagraphBoundary && selection.selection().isCaret() && isEndOfParagraph(selection.selection().visibleEnd())) selection.modify(SelectionController::EXTEND, SelectionController::FORWARD, CharacterGranularity); selectionToDelete = selection.selection(); if (!startingSelection().isRange() || selectionToDelete.base() != startingSelection().start()) selectionAfterUndo = selectionToDelete; else { // It's a little tricky to compute what the starting selection would have been in the original document. // We can't let the VisibleSelection class's validation kick in or it'll adjust for us based on // the current state of the document and we'll get the wrong result. Position extent = startingSelection().end(); if (extent.node() != selectionToDelete.end().node()) extent = selectionToDelete.extent(); else { int extraCharacters; if (selectionToDelete.start().node() == selectionToDelete.end().node()) extraCharacters = selectionToDelete.end().offset() - selectionToDelete.start().offset(); else extraCharacters = selectionToDelete.end().offset(); extent = Position(extent.node(), extent.offset() + extraCharacters); } selectionAfterUndo.setWithoutValidation(startingSelection().start(), extent); } break; } case VisibleSelection::NoSelection: ASSERT_NOT_REACHED(); break; } ASSERT(!selectionToDelete.isNone()); if (selectionToDelete.isNone()) return; if (selectionToDelete.isCaret() || !document()->frame()->shouldDeleteSelection(selectionToDelete)) return; if (killRing) document()->frame()->editor()->addToKillRing(selectionToDelete.toNormalizedRange().get(), false); // make undo select what was deleted setStartingSelection(selectionAfterUndo); CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete); setSmartDelete(false); typingAddedToOpenCommand();}void TypingCommand::deleteSelection(bool smartDelete){ CompositeEditCommand::deleteSelection(smartDelete); typingAddedToOpenCommand();}bool TypingCommand::preservesTypingStyle() const{ switch (m_commandType) { case DeleteSelection: case DeleteKey: case ForwardDeleteKey: case InsertParagraphSeparator: case InsertLineBreak: return true; case InsertParagraphSeparatorInQuotedContent: case InsertText: return false; } ASSERT_NOT_REACHED(); return false;}bool TypingCommand::isTypingCommand() const{ return true;}} // namespace WebCore
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -