📄 editor.cpp
字号:
return false; // Must be done before oncut adds types and data to the pboard, // also done for security, as it erases data from the last copy/paste. Pasteboard::generalPasteboard()->clear(); return !dispatchCPPEvent(eventNames().cutEvent, ClipboardWritable);}bool Editor::tryDHTMLPaste(){ return !dispatchCPPEvent(eventNames().pasteEvent, ClipboardReadable);}void Editor::writeSelectionToPasteboard(Pasteboard* pasteboard){ pasteboard->writeSelection(selectedRange().get(), canSmartCopyOrDelete(), m_frame);}bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const{ return client() && client()->shouldInsertText(text, range, action);}bool Editor::shouldShowDeleteInterface(HTMLElement* element) const{ return client() && client()->shouldShowDeleteInterface(element);}void Editor::respondToChangedSelection(const VisibleSelection& oldSelection){ if (client()) client()->respondToChangedSelection(); m_deleteButtonController->respondToChangedSelection(oldSelection);}void Editor::respondToChangedContents(const VisibleSelection& endingSelection){ if (AXObjectCache::accessibilityEnabled()) { Node* node = endingSelection.start().node(); if (node) m_frame->document()->axObjectCache()->postNotification(node->renderer(), "AXValueChanged"); } if (client()) client()->respondToChangedContents(); }const SimpleFontData* Editor::fontForSelection(bool& hasMultipleFonts) const{#if !PLATFORM(QT) hasMultipleFonts = false; if (!m_frame->selection()->isRange()) { Node* nodeToRemove; RenderStyle* style = m_frame->styleForSelectionStart(nodeToRemove); // sets nodeToRemove const SimpleFontData* result = 0; if (style) result = style->font().primaryFont(); if (nodeToRemove) { ExceptionCode ec; nodeToRemove->remove(ec); ASSERT(ec == 0); } return result; } const SimpleFontData* font = 0; RefPtr<Range> range = m_frame->selection()->toNormalizedRange(); Node* startNode = range->editingStartPosition().node(); if (startNode) { Node* pastEnd = range->pastLastNode(); // In the loop below, n should eventually match pastEnd and not become nil, but we've seen at least one // unreproducible case where this didn't happen, so check for nil also. for (Node* n = startNode; n && n != pastEnd; n = n->traverseNextNode()) { RenderObject *renderer = n->renderer(); if (!renderer) continue; // FIXME: Are there any node types that have renderers, but that we should be skipping? const SimpleFontData* f = renderer->style()->font().primaryFont(); if (!font) font = f; else if (font != f) { hasMultipleFonts = true; break; } } } return font;#else return 0;#endif}WritingDirection Editor::textDirectionForSelection(bool& hasNestedOrMultipleEmbeddings) const{ hasNestedOrMultipleEmbeddings = true; if (m_frame->selection()->isNone()) return NaturalWritingDirection; Position pos = m_frame->selection()->selection().start().downstream(); Node* node = pos.node(); if (!node) return NaturalWritingDirection; Position end; if (m_frame->selection()->isRange()) { end = m_frame->selection()->selection().end().upstream(); Node* pastLast = Range::create(m_frame->document(), rangeCompliantEquivalent(pos), rangeCompliantEquivalent(end))->pastLastNode(); for (Node* n = node; n && n != pastLast; n = n->traverseNextNode()) { if (!n->isStyledElement()) continue; RefPtr<CSSComputedStyleDeclaration> style = computedStyle(n); RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropertyUnicodeBidi); if (!unicodeBidi) continue; ASSERT(unicodeBidi->isPrimitiveValue()); int unicodeBidiValue = static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent(); if (unicodeBidiValue == CSSValueEmbed || unicodeBidiValue == CSSValueBidiOverride) return NaturalWritingDirection; } } if (m_frame->selection()->isCaret()) { if (CSSMutableStyleDeclaration *typingStyle = m_frame->typingStyle()) { RefPtr<CSSValue> unicodeBidi = typingStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi); if (unicodeBidi) { ASSERT(unicodeBidi->isPrimitiveValue()); int unicodeBidiValue = static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent(); if (unicodeBidiValue == CSSValueEmbed) { RefPtr<CSSValue> direction = typingStyle->getPropertyCSSValue(CSSPropertyDirection); ASSERT(!direction || direction->isPrimitiveValue()); if (direction) { hasNestedOrMultipleEmbeddings = false; return static_cast<CSSPrimitiveValue*>(direction.get())->getIdent() == CSSValueLtr ? LeftToRightWritingDirection : RightToLeftWritingDirection; } } else if (unicodeBidiValue == CSSValueNormal) { hasNestedOrMultipleEmbeddings = false; return NaturalWritingDirection; } } } node = m_frame->selection()->selection().visibleStart().deepEquivalent().node(); } // The selection is either a caret with no typing attributes or a range in which no embedding is added, so just use the start position // to decide. Node* block = enclosingBlock(node); WritingDirection foundDirection = NaturalWritingDirection; for (; node != block; node = node->parent()) { if (!node->isStyledElement()) continue; RefPtr<CSSComputedStyleDeclaration> style = computedStyle(node); RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropertyUnicodeBidi); if (!unicodeBidi) continue; ASSERT(unicodeBidi->isPrimitiveValue()); int unicodeBidiValue = static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent(); if (unicodeBidiValue == CSSValueNormal) continue; if (unicodeBidiValue == CSSValueBidiOverride) return NaturalWritingDirection; ASSERT(unicodeBidiValue == CSSValueEmbed); RefPtr<CSSValue> direction = style->getPropertyCSSValue(CSSPropertyDirection); if (!direction) continue; ASSERT(direction->isPrimitiveValue()); int directionValue = static_cast<CSSPrimitiveValue*>(direction.get())->getIdent(); if (directionValue != CSSValueLtr && directionValue != CSSValueRtl) continue; if (foundDirection != NaturalWritingDirection) return NaturalWritingDirection; // In the range case, make sure that the embedding element persists until the end of the range. if (m_frame->selection()->isRange() && !end.node()->isDescendantOf(node)) return NaturalWritingDirection; foundDirection = directionValue == CSSValueLtr ? LeftToRightWritingDirection : RightToLeftWritingDirection; } hasNestedOrMultipleEmbeddings = false; return foundDirection;}bool Editor::hasBidiSelection() const{ if (m_frame->selection()->isNone()) return false; Node* startNode; if (m_frame->selection()->isRange()) { startNode = m_frame->selection()->selection().start().downstream().node(); Node* endNode = m_frame->selection()->selection().end().upstream().node(); if (enclosingBlock(startNode) != enclosingBlock(endNode)) return false; } else startNode = m_frame->selection()->selection().visibleStart().deepEquivalent().node(); RenderObject* renderer = startNode->renderer(); while (renderer && !renderer->isRenderBlock()) renderer = renderer->parent(); if (!renderer) return false; RenderStyle* style = renderer->style(); if (style->direction() == RTL) return true; return toRenderBlock(renderer)->containsNonZeroBidiLevel();}TriState Editor::selectionUnorderedListState() const{ if (m_frame->selection()->isCaret()) { if (enclosingNodeWithTag(m_frame->selection()->selection().start(), ulTag)) return TrueTriState; } else if (m_frame->selection()->isRange()) { Node* startNode = enclosingNodeWithTag(m_frame->selection()->selection().start(), ulTag); Node* endNode = enclosingNodeWithTag(m_frame->selection()->selection().end(), ulTag); if (startNode && endNode && startNode == endNode) return TrueTriState; } return FalseTriState;}TriState Editor::selectionOrderedListState() const{ if (m_frame->selection()->isCaret()) { if (enclosingNodeWithTag(m_frame->selection()->selection().start(), olTag)) return TrueTriState; } else if (m_frame->selection()->isRange()) { Node* startNode = enclosingNodeWithTag(m_frame->selection()->selection().start(), olTag); Node* endNode = enclosingNodeWithTag(m_frame->selection()->selection().end(), olTag); if (startNode && endNode && startNode == endNode) return TrueTriState; } return FalseTriState;}PassRefPtr<Node> Editor::insertOrderedList(){ if (!canEditRichly()) return 0; RefPtr<Node> newList = InsertListCommand::insertList(m_frame->document(), InsertListCommand::OrderedList); revealSelectionAfterEditingOperation(); return newList;}PassRefPtr<Node> Editor::insertUnorderedList(){ if (!canEditRichly()) return 0; RefPtr<Node> newList = InsertListCommand::insertList(m_frame->document(), InsertListCommand::UnorderedList); revealSelectionAfterEditingOperation(); return newList;}bool Editor::canIncreaseSelectionListLevel(){ return canEditRichly() && IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(m_frame->document());}bool Editor::canDecreaseSelectionListLevel(){ return canEditRichly() && DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(m_frame->document());}PassRefPtr<Node> Editor::increaseSelectionListLevel(){ if (!canEditRichly() || m_frame->selection()->isNone()) return 0; RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(m_frame->document()); revealSelectionAfterEditingOperation(); return newList;}PassRefPtr<Node> Editor::increaseSelectionListLevelOrdered(){ if (!canEditRichly() || m_frame->selection()->isNone()) return 0; PassRefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(m_frame->document()); revealSelectionAfterEditingOperation(); return newList;}PassRefPtr<Node> Editor::increaseSelectionListLevelUnordered(){ if (!canEditRichly() || m_frame->selection()->isNone()) return 0; PassRefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(m_frame->document()); revealSelectionAfterEditingOperation(); return newList;}void Editor::decreaseSelectionListLevel(){ if (!canEditRichly() || m_frame->selection()->isNone()) return; DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(m_frame->document()); revealSelectionAfterEditingOperation();}void Editor::removeFormattingAndStyle(){ applyCommand(RemoveFormatCommand::create(m_frame->document()));}void Editor::clearLastEditCommand() { m_lastEditCommand.clear();}// Returns whether caller should continue with "the default processing", which is the same as // the event handler NOT setting the return value to falsebool Editor::dispatchCPPEvent(const AtomicString &eventType, ClipboardAccessPolicy policy){ Node* target = m_frame->selection()->start().element(); if (!target) target = m_frame->document()->body(); if (!target) return true; target = target->shadowAncestorNode(); RefPtr<Clipboard> clipboard = newGeneralClipboard(policy);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -