📄 editorcommand.cpp
字号:
/* * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "AtomicString.h"#include "CSSPropertyNames.h"#include "CSSValueKeywords.h"#include "CreateLinkCommand.h"#include "DocumentFragment.h"#include "Editor.h"#include "EditorClient.h"#include "Event.h"#include "EventHandler.h"#include "FormatBlockCommand.h"#include "Frame.h"#include "HTMLFontElement.h"#include "HTMLImageElement.h"#include "IndentOutdentCommand.h"#include "InsertListCommand.h"#include "Page.h"#include "RenderBox.h"#include "ReplaceSelectionCommand.h"#include "Scrollbar.h"#include "Settings.h"#include "Sound.h"#include "TypingCommand.h"#include "UnlinkCommand.h"#include "htmlediting.h"#include "markup.h"namespace WebCore {using namespace HTMLNames;class EditorInternalCommand {public: bool (*execute)(Frame*, Event*, EditorCommandSource, const String&); bool (*isSupported)(Frame*, EditorCommandSource); bool (*isEnabled)(Frame*, Event*, EditorCommandSource); TriState (*state)(Frame*, Event*); String (*value)(Frame*, Event*); bool isTextInsertion; bool allowExecutionWhenDisabled;};typedef HashMap<String, const EditorInternalCommand*, CaseFoldingHash> CommandMap;static const bool notTextInsertion = false;static const bool isTextInsertion = true;static const bool allowExecutionWhenDisabled = true;static const bool doNotAllowExecutionWhenDisabled = false;// Related to Editor::selectionForCommand.// Certain operations continue to use the target control's selection even if the event handler// already moved the selection outside of the text control.static Frame* targetFrame(Frame* frame, Event* event){ if (!event) return frame; Node* node = event->target()->toNode(); if (!node) return frame; return node->document()->frame();}static bool executeApplyStyle(Frame* frame, EditorCommandSource source, EditAction action, int propertyID, const String& propertyValue){ RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create(); style->setProperty(propertyID, propertyValue); // FIXME: We don't call shouldApplyStyle when the source is DOM; is there a good reason for that? switch (source) { case CommandFromMenuOrKeyBinding: frame->editor()->applyStyleToSelection(style.get(), action); return true; case CommandFromDOM: case CommandFromDOMWithUserInterface: frame->editor()->applyStyle(style.get()); return true; } ASSERT_NOT_REACHED(); return false;}static bool executeApplyStyle(Frame* frame, EditorCommandSource source, EditAction action, int propertyID, const char* propertyValue){ return executeApplyStyle(frame, source, action, propertyID, String(propertyValue));}static bool executeApplyStyle(Frame* frame, EditorCommandSource source, EditAction action, int propertyID, int propertyValue){ RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create(); style->setProperty(propertyID, propertyValue); // FIXME: We don't call shouldApplyStyle when the source is DOM; is there a good reason for that? switch (source) { case CommandFromMenuOrKeyBinding: frame->editor()->applyStyleToSelection(style.get(), action); return true; case CommandFromDOM: case CommandFromDOMWithUserInterface: frame->editor()->applyStyle(style.get()); return true; } ASSERT_NOT_REACHED(); return false;}static bool executeToggleStyle(Frame* frame, EditorCommandSource source, EditAction action, int propertyID, const char* offValue, const char* onValue){ RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create(); style->setProperty(propertyID, onValue); style->setProperty(propertyID, frame->editor()->selectionStartHasStyle(style.get()) ? offValue : onValue); // FIXME: We don't call shouldApplyStyle when the source is DOM; is there a good reason for that? switch (source) { case CommandFromMenuOrKeyBinding: frame->editor()->applyStyleToSelection(style.get(), action); return true; case CommandFromDOM: case CommandFromDOMWithUserInterface: frame->editor()->applyStyle(style.get()); return true; } ASSERT_NOT_REACHED(); return false;}static bool executeApplyParagraphStyle(Frame* frame, EditorCommandSource source, EditAction action, int propertyID, const String& propertyValue){ RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create(); style->setProperty(propertyID, propertyValue); // FIXME: We don't call shouldApplyStyle when the source is DOM; is there a good reason for that? switch (source) { case CommandFromMenuOrKeyBinding: frame->editor()->applyParagraphStyleToSelection(style.get(), action); return true; case CommandFromDOM: case CommandFromDOMWithUserInterface: frame->editor()->applyParagraphStyle(style.get()); return true; } ASSERT_NOT_REACHED(); return false;}static bool executeInsertFragment(Frame* frame, PassRefPtr<DocumentFragment> fragment){ applyCommand(ReplaceSelectionCommand::create(frame->document(), fragment, false, false, false, true, false, EditActionUnspecified)); return true;}static bool executeInsertNode(Frame* frame, PassRefPtr<Node> content){ RefPtr<DocumentFragment> fragment = new DocumentFragment(frame->document()); ExceptionCode ec = 0; fragment->appendChild(content, ec); if (ec) return false; return executeInsertFragment(frame, fragment.release());}static bool expandSelectionToGranularity(Frame* frame, TextGranularity granularity){ VisibleSelection selection = frame->selection()->selection(); selection.expandUsingGranularity(granularity); RefPtr<Range> newRange = selection.toNormalizedRange(); if (!newRange) return false; ExceptionCode ec = 0; if (newRange->collapsed(ec)) return false; RefPtr<Range> oldRange = frame->selection()->selection().toNormalizedRange(); EAffinity affinity = frame->selection()->affinity(); if (!frame->editor()->client()->shouldChangeSelectedRange(oldRange.get(), newRange.get(), affinity, false)) return false; frame->selection()->setSelectedRange(newRange.get(), affinity, true); return true;}static TriState stateStyle(Frame* frame, int propertyID, const char* desiredValue){ RefPtr<CSSMutableStyleDeclaration> style = CSSMutableStyleDeclaration::create(); style->setProperty(propertyID, desiredValue); return frame->editor()->selectionHasStyle(style.get());}static String valueStyle(Frame* frame, int propertyID){ return frame->selectionStartStylePropertyValue(propertyID);}static TriState stateTextWritingDirection(Frame* frame, WritingDirection direction){ bool hasNestedOrMultipleEmbeddings; WritingDirection selectionDirection = frame->editor()->textDirectionForSelection(hasNestedOrMultipleEmbeddings); return (selectionDirection == direction && !hasNestedOrMultipleEmbeddings) ? TrueTriState : FalseTriState;}static int verticalScrollDistance(Frame* frame){ Node* focusedNode = frame->document()->focusedNode(); if (!focusedNode) return 0; RenderObject* renderer = focusedNode->renderer(); if (!renderer || !renderer->isBox()) return 0; RenderStyle* style = renderer->style(); if (!style) return 0; if (!(style->overflowY() == OSCROLL || style->overflowY() == OAUTO || renderer->isTextArea())) return 0; int height = toRenderBox(renderer)->clientHeight(); return max((height + 1) / 2, height - cAmountToKeepWhenPaging);}static RefPtr<Range> unionDOMRanges(Range* a, Range* b){ ExceptionCode ec = 0; Range* start = a->compareBoundaryPoints(Range::START_TO_START, b, ec) <= 0 ? a : b; ASSERT(!ec); Range* end = a->compareBoundaryPoints(Range::END_TO_END, b, ec) <= 0 ? b : a; ASSERT(!ec); return Range::create(a->startContainer(ec)->ownerDocument(), start->startContainer(ec), start->startOffset(ec), end->endContainer(ec), end->endOffset(ec));}// Execute command functionsstatic bool executeBackColor(Frame* frame, Event*, EditorCommandSource source, const String& value){ return executeApplyStyle(frame, source, EditActionSetBackgroundColor, CSSPropertyBackgroundColor, value);}static bool executeCopy(Frame* frame, Event*, EditorCommandSource, const String&){ frame->editor()->copy(); return true;}static bool executeCreateLink(Frame* frame, Event*, EditorCommandSource, const String& value){ // FIXME: If userInterface is true, we should display a dialog box to let the user enter a URL. if (value.isEmpty()) return false; applyCommand(CreateLinkCommand::create(frame->document(), value));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -