📄 editor.cpp
字号:
return; // DHTML did the whole operation if (!canPaste()) return; DocLoader* loader = m_frame->document()->docLoader(); loader->setAllowStaleResources(true); if (m_frame->selection()->isContentRichlyEditable()) pasteWithPasteboard(Pasteboard::generalPasteboard(), true); else pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); loader->setAllowStaleResources(false);}#endifvoid Editor::pasteAsPlainText(){ if (!canPaste()) return; pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());}void Editor::performDelete(){ if (!canDelete()) { systemBeep(); return; } addToKillRing(selectedRange().get(), false); deleteSelectionWithSmartDelete(canSmartCopyOrDelete()); // clear the "start new kill ring sequence" setting, because it was set to true // when the selection was updated by deleting the range setStartNewKillRingSequence(false);}void Editor::copyURL(const KURL& url, const String& title){ Pasteboard::generalPasteboard()->writeURL(url, title, m_frame);}void Editor::copyImage(const HitTestResult& result){ KURL url = result.absoluteLinkURL(); if (url.isEmpty()) url = result.absoluteImageURL(); Pasteboard::generalPasteboard()->writeImage(result.innerNonSharedNode(), url, result.altDisplayString());}bool Editor::isContinuousSpellCheckingEnabled(){ return client() && client()->isContinuousSpellCheckingEnabled();}void Editor::toggleContinuousSpellChecking(){ if (client()) client()->toggleContinuousSpellChecking();}bool Editor::isGrammarCheckingEnabled(){ return client() && client()->isGrammarCheckingEnabled();}void Editor::toggleGrammarChecking(){ if (client()) client()->toggleGrammarChecking();}int Editor::spellCheckerDocumentTag(){ return client() ? client()->spellCheckerDocumentTag() : 0;}bool Editor::shouldEndEditing(Range* range){ return client() && client()->shouldEndEditing(range);}bool Editor::shouldBeginEditing(Range* range){ return client() && client()->shouldBeginEditing(range);}void Editor::clearUndoRedoOperations(){ if (client()) client()->clearUndoRedoOperations();}bool Editor::canUndo(){ return client() && client()->canUndo();}void Editor::undo(){ if (client()) client()->undo();}bool Editor::canRedo(){ return client() && client()->canRedo();}void Editor::redo(){ if (client()) client()->redo();}void Editor::didBeginEditing(){ if (client()) client()->didBeginEditing();}void Editor::didEndEditing(){ if (client()) client()->didEndEditing();}void Editor::didWriteSelectionToPasteboard(){ if (client()) client()->didWriteSelectionToPasteboard();}void Editor::toggleBold(){ command("ToggleBold").execute();}void Editor::toggleUnderline(){ command("ToggleUnderline").execute();}void Editor::setBaseWritingDirection(WritingDirection direction){ Node* focusedNode = frame()->document()->focusedNode(); if (focusedNode && (focusedNode->hasTagName(textareaTag) || focusedNode->hasTagName(inputTag) && (static_cast<HTMLInputElement*>(focusedNode)->inputType() == HTMLInputElement::TEXT || static_cast<HTMLInputElement*>(focusedNode)->inputType() == HTMLInputElement::SEARCH))) { if (direction == NaturalWritingDirection) return; static_cast<HTMLElement*>(focusedNode)->setAttribute(dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl"); frame()->document()->updateRendering(); return; } RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create(); style->setProperty(CSSPropertyDirection, direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", false); applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection);}void Editor::selectComposition(){ RefPtr<Range> range = compositionRange(); if (!range) return; // The composition can start inside a composed character sequence, so we have to override checks. // See <http://bugs.webkit.org/show_bug.cgi?id=15781> VisibleSelection selection; selection.setWithoutValidation(range->startPosition(), range->endPosition()); m_frame->selection()->setSelection(selection, false, false);}void Editor::confirmComposition(){ if (!m_compositionNode) return; confirmComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), false);}void Editor::confirmCompositionWithoutDisturbingSelection(){ if (!m_compositionNode) return; confirmComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), true);}void Editor::confirmComposition(const String& text){ confirmComposition(text, false);}void Editor::confirmComposition(const String& text, bool preserveSelection){ setIgnoreCompositionSelectionChange(true); VisibleSelection oldSelection = m_frame->selection()->selection(); selectComposition(); if (m_frame->selection()->isNone()) { setIgnoreCompositionSelectionChange(false); return; } // If text is empty, then delete the old composition here. If text is non-empty, InsertTextCommand::input // will delete the old composition with an optimized replace operation. if (text.isEmpty()) TypingCommand::deleteSelection(m_frame->document(), false); m_compositionNode = 0; m_customCompositionUnderlines.clear(); insertText(text, 0); if (preserveSelection) m_frame->selection()->setSelection(oldSelection, false, false); setIgnoreCompositionSelectionChange(false);}void Editor::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd){ setIgnoreCompositionSelectionChange(true); selectComposition(); if (m_frame->selection()->isNone()) { setIgnoreCompositionSelectionChange(false); return; } // If text is empty, then delete the old composition here. If text is non-empty, InsertTextCommand::input // will delete the old composition with an optimized replace operation. if (text.isEmpty()) TypingCommand::deleteSelection(m_frame->document(), false); m_compositionNode = 0; m_customCompositionUnderlines.clear(); if (!text.isEmpty()) { TypingCommand::insertText(m_frame->document(), text, true, true); Node* baseNode = m_frame->selection()->base().node(); unsigned baseOffset = m_frame->selection()->base().offset(); Node* extentNode = m_frame->selection()->extent().node(); unsigned extentOffset = m_frame->selection()->extent().offset(); if (baseNode && baseNode == extentNode && baseNode->isTextNode() && baseOffset + text.length() == extentOffset) { m_compositionNode = static_cast<Text*>(baseNode); m_compositionStart = baseOffset; m_compositionEnd = extentOffset; m_customCompositionUnderlines = underlines; size_t numUnderlines = m_customCompositionUnderlines.size(); for (size_t i = 0; i < numUnderlines; ++i) { m_customCompositionUnderlines[i].startOffset += baseOffset; m_customCompositionUnderlines[i].endOffset += baseOffset; } if (baseNode->renderer()) baseNode->renderer()->repaint(); unsigned start = min(baseOffset + selectionStart, extentOffset); unsigned end = min(max(start, baseOffset + selectionEnd), extentOffset); RefPtr<Range> selectedRange = Range::create(baseNode->document(), baseNode, start, baseNode, end); m_frame->selection()->setSelectedRange(selectedRange.get(), DOWNSTREAM, false); } } setIgnoreCompositionSelectionChange(false);}void Editor::ignoreSpelling(){ if (!client()) return; RefPtr<Range> selectedRange = frame()->selection()->toNormalizedRange(); if (selectedRange) frame()->document()->removeMarkers(selectedRange.get(), DocumentMarker::Spelling); String text = frame()->selectedText(); ASSERT(text.length() != 0); client()->ignoreWordInSpellDocument(text);}void Editor::learnSpelling(){ if (!client()) return; // FIXME: We don't call this on the Mac, and it should remove misppelling markers around the // learned word, see <rdar://problem/5396072>. String text = frame()->selectedText(); ASSERT(text.length() != 0); client()->learnWord(text);}static String findFirstMisspellingInRange(EditorClient* client, Range* searchRange, int& firstMisspellingOffset, bool markAll){ ASSERT_ARG(client, client); ASSERT_ARG(searchRange, searchRange); WordAwareIterator it(searchRange); firstMisspellingOffset = 0; String firstMisspelling; int currentChunkOffset = 0; while (!it.atEnd()) { const UChar* chars = it.characters(); int len = it.length(); // Skip some work for one-space-char hunks if (!(len == 1 && chars[0] == ' ')) { int misspellingLocation = -1; int misspellingLength = 0; client->checkSpellingOfString(chars, len, &misspellingLocation, &misspellingLength); // 5490627 shows that there was some code path here where the String constructor below crashes. // We don't know exactly what combination of bad input caused this, so we're making this much // more robust against bad input on release builds. ASSERT(misspellingLength >= 0); ASSERT(misspellingLocation >= -1); ASSERT(misspellingLength == 0 || misspellingLocation >= 0); ASSERT(misspellingLocation < len); ASSERT(misspellingLength <= len); ASSERT(misspellingLocation + misspellingLength <= len); if (misspellingLocation >= 0 && misspellingLength > 0 && misspellingLocation < len && misspellingLength <= len && misspellingLocation + misspellingLength <= len) { // Remember first-encountered misspelling and its offset if (!firstMisspelling) { firstMisspellingOffset = currentChunkOffset + misspellingLocation; firstMisspelling = String(chars + misspellingLocation, misspellingLength); } // Mark this instance if we're marking all instances. Otherwise bail out because we found the first one. if (!markAll) break; // Compute range of misspelled word RefPtr<Range> misspellingRange = TextIterator::subrange(searchRange, currentChunkOffset + misspellingLocation, misspellingLength); // Store marker for misspelled word ExceptionCode ec = 0; misspellingRange->startContainer(ec)->document()->addMarker(misspellingRange.get(), DocumentMarker::Spelling);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -