mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix (most) generated includes to have gen/ in their path. This makes it easier to tell where files exist on disk. Unfortunately I had to leave the old include path in engine/BUILD.gn to support all the v8 includes which were too many to deal with in this patch. It's a little nasty to have the raw build directory in our include path, but it produces nicer paths. R=abarth@chromium.org
658 lines
29 KiB
C++
658 lines
29 KiB
C++
/*
|
|
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
|
|
* Copyright (C) 2009 Igalia S.L.
|
|
*
|
|
* 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 "core/editing/Editor.h"
|
|
|
|
#include "bindings/core/v8/ExceptionState.h"
|
|
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
|
|
#include "gen/sky/core/CSSPropertyNames.h"
|
|
#include "gen/sky/core/CSSValueKeywords.h"
|
|
#include "core/css/CSSValueList.h"
|
|
#include "core/css/StylePropertySet.h"
|
|
#include "core/dom/DocumentFragment.h"
|
|
#include "core/editing/FrameSelection.h"
|
|
#include "core/editing/ReplaceSelectionCommand.h"
|
|
#include "core/editing/SpellChecker.h"
|
|
#include "core/editing/TypingCommand.h"
|
|
#include "core/editing/htmlediting.h"
|
|
#include "core/editing/markup.h"
|
|
#include "core/events/Event.h"
|
|
#include "core/frame/FrameHost.h"
|
|
#include "core/frame/FrameView.h"
|
|
#include "core/frame/LocalFrame.h"
|
|
#include "core/frame/Settings.h"
|
|
#include "core/html/HTMLImageElement.h"
|
|
#include "core/page/Chrome.h"
|
|
#include "core/page/EditorClient.h"
|
|
#include "core/page/EventHandler.h"
|
|
#include "core/rendering/RenderBox.h"
|
|
#include "platform/scroll/Scrollbar.h"
|
|
#include "public/platform/Platform.h"
|
|
#include "wtf/text/AtomicString.h"
|
|
|
|
namespace blink {
|
|
|
|
class EditorInternalCommand {
|
|
public:
|
|
int idForUserMetrics;
|
|
bool (*execute)(LocalFrame&, Event*, EditorCommandSource, const String&);
|
|
bool (*isSupportedFromDOM)(LocalFrame*);
|
|
bool (*isEnabled)(LocalFrame&, Event*, EditorCommandSource);
|
|
TriState (*state)(LocalFrame&, Event*);
|
|
String (*value)(LocalFrame&, 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 LocalFrame* targetFrame(LocalFrame& frame, Event* event)
|
|
{
|
|
if (!event)
|
|
return &frame;
|
|
Node* node = event->target()->toNode();
|
|
if (!node)
|
|
return &frame;
|
|
return node->document().frame();
|
|
}
|
|
|
|
static unsigned verticalScrollDistance(LocalFrame& frame)
|
|
{
|
|
Element* focusedElement = frame.document()->focusedElement();
|
|
if (!focusedElement)
|
|
return 0;
|
|
RenderObject* renderer = focusedElement->renderer();
|
|
if (!renderer || !renderer->isBox())
|
|
return 0;
|
|
RenderBox& renderBox = toRenderBox(*renderer);
|
|
RenderStyle* style = renderBox.style();
|
|
if (!style)
|
|
return 0;
|
|
if (!(style->overflowY() == OSCROLL || style->overflowY() == OAUTO || focusedElement->hasEditableStyle()))
|
|
return 0;
|
|
int height = std::min<int>(renderBox.clientHeight(),
|
|
frame.view()->height());
|
|
return static_cast<unsigned>(max(max<int>(height * ScrollableArea::minFractionToStepWhenPaging(), height - ScrollableArea::maxOverlapBetweenPages()), 1));
|
|
}
|
|
|
|
static bool executeCopy(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().copy();
|
|
return true;
|
|
}
|
|
|
|
static bool executeCut(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().cut();
|
|
return true;
|
|
}
|
|
|
|
static bool executeDeleteBackward(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().deleteWithDirection(DirectionBackward, CharacterGranularity, true);
|
|
return true;
|
|
}
|
|
|
|
static bool executeDeleteForward(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().deleteWithDirection(DirectionForward, CharacterGranularity, true);
|
|
return true;
|
|
}
|
|
|
|
static bool executeDeleteWordBackward(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().deleteWithDirection(DirectionBackward, WordGranularity, false);
|
|
return true;
|
|
}
|
|
|
|
static bool executeDeleteWordForward(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().deleteWithDirection(DirectionForward, WordGranularity, false);
|
|
return true;
|
|
}
|
|
|
|
static bool executeInsertNewline(LocalFrame& frame, Event* event, EditorCommandSource, const String&)
|
|
{
|
|
LocalFrame* targetFrame = blink::targetFrame(frame, event);
|
|
return targetFrame->eventHandler().handleTextInputEvent("\n", event, targetFrame->editor().canEditRichly() ? TextEventInputKeyboard : TextEventInputLineBreak);
|
|
}
|
|
|
|
static bool executeMoveDown(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
return frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, LineGranularity, UserTriggered);
|
|
}
|
|
|
|
static bool executeMoveDownAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionForward, LineGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveLeft(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
return frame.selection().modify(FrameSelection::AlterationMove, DirectionLeft, CharacterGranularity, UserTriggered);
|
|
}
|
|
|
|
static bool executeMoveLeftAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionLeft, CharacterGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMovePageDown(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
unsigned distance = verticalScrollDistance(frame);
|
|
if (!distance)
|
|
return false;
|
|
return frame.selection().modify(FrameSelection::AlterationMove, distance, FrameSelection::DirectionDown,
|
|
UserTriggered, FrameSelection::AlignCursorOnScrollAlways);
|
|
}
|
|
|
|
static bool executeMovePageDownAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
unsigned distance = verticalScrollDistance(frame);
|
|
if (!distance)
|
|
return false;
|
|
return frame.selection().modify(FrameSelection::AlterationExtend, distance, FrameSelection::DirectionDown,
|
|
UserTriggered, FrameSelection::AlignCursorOnScrollAlways);
|
|
}
|
|
|
|
static bool executeMovePageUp(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
unsigned distance = verticalScrollDistance(frame);
|
|
if (!distance)
|
|
return false;
|
|
return frame.selection().modify(FrameSelection::AlterationMove, distance, FrameSelection::DirectionUp,
|
|
UserTriggered, FrameSelection::AlignCursorOnScrollAlways);
|
|
}
|
|
|
|
static bool executeMovePageUpAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
unsigned distance = verticalScrollDistance(frame);
|
|
if (!distance)
|
|
return false;
|
|
return frame.selection().modify(FrameSelection::AlterationExtend, distance, FrameSelection::DirectionUp,
|
|
UserTriggered, FrameSelection::AlignCursorOnScrollAlways);
|
|
}
|
|
|
|
static bool executeMoveRight(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
return frame.selection().modify(FrameSelection::AlterationMove, DirectionRight, CharacterGranularity, UserTriggered);
|
|
}
|
|
|
|
static bool executeMoveRightAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionRight, CharacterGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToBeginningOfDocument(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionBackward, DocumentBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToBeginningOfDocumentAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionBackward, DocumentBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToBeginningOfLine(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionBackward, LineBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToBeginningOfLineAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionBackward, LineBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToEndOfDocument(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, DocumentBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToEndOfDocumentAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionForward, DocumentBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToEndOfLine(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, LineBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToEndOfLineAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionForward, LineBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveParagraphBackward(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionBackward, ParagraphGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveParagraphBackwardAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionBackward, ParagraphGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveParagraphForward(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, ParagraphGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveParagraphForwardAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionForward, ParagraphGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveUp(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
return frame.selection().modify(FrameSelection::AlterationMove, DirectionBackward, LineGranularity, UserTriggered);
|
|
}
|
|
|
|
static bool executeMoveUpAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionBackward, LineGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveWordLeft(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionLeft, WordGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveWordLeftAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionLeft, WordGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveWordRight(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionRight, WordGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveWordRightAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionRight, WordGranularity, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToLeftEndOfLine(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationMove, DirectionLeft, LineBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeMoveToLeftEndOfLineAndModifySelection(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().modify(FrameSelection::AlterationExtend, DirectionLeft, LineBoundary, UserTriggered);
|
|
return true;
|
|
}
|
|
|
|
static bool executeToggleOverwrite(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().toggleOverwriteModeEnabled();
|
|
return true;
|
|
}
|
|
|
|
static bool executePaste(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().paste();
|
|
return true;
|
|
}
|
|
|
|
static bool executePasteAndMatchStyle(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.editor().pasteAsPlainText();
|
|
return true;
|
|
}
|
|
|
|
static bool executeSelectAll(LocalFrame& frame, Event*, EditorCommandSource, const String&)
|
|
{
|
|
frame.selection().selectAll();
|
|
return true;
|
|
}
|
|
|
|
static bool supported(LocalFrame*)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool supportedFromMenuOrKeyBinding(LocalFrame*)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static bool supportedCopyCut(LocalFrame* frame)
|
|
{
|
|
if (!frame)
|
|
return false;
|
|
|
|
Settings* settings = frame->settings();
|
|
bool defaultValue = settings && settings->javaScriptCanAccessClipboard();
|
|
return frame->editor().client().canCopyCut(frame, defaultValue);
|
|
}
|
|
|
|
static bool supportedPaste(LocalFrame* frame)
|
|
{
|
|
if (!frame)
|
|
return false;
|
|
|
|
Settings* settings = frame->settings();
|
|
bool defaultValue = settings && settings->javaScriptCanAccessClipboard() && settings->DOMPasteAllowed();
|
|
return frame->editor().client().canPaste(frame, defaultValue);
|
|
}
|
|
|
|
// Enabled functions
|
|
|
|
static bool enabled(LocalFrame&, Event*, EditorCommandSource)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static bool enabledVisibleSelection(LocalFrame& frame, Event* event, EditorCommandSource)
|
|
{
|
|
// The term "visible" here includes a caret in editable text or a range in any text.
|
|
const VisibleSelection& selection = frame.editor().selectionForCommand(event);
|
|
return (selection.isCaret() && selection.isContentEditable()) || selection.isRange();
|
|
}
|
|
|
|
static bool enabledCopy(LocalFrame& frame, Event*, EditorCommandSource)
|
|
{
|
|
return frame.editor().canDHTMLCopy() || frame.editor().canCopy();
|
|
}
|
|
|
|
static bool enabledCut(LocalFrame& frame, Event*, EditorCommandSource)
|
|
{
|
|
return frame.editor().canDHTMLCut() || frame.editor().canCut();
|
|
}
|
|
|
|
static bool enabledInEditableText(LocalFrame& frame, Event* event, EditorCommandSource)
|
|
{
|
|
return frame.editor().selectionForCommand(event).rootEditableElement();
|
|
}
|
|
|
|
static bool enabledInRichlyEditableText(LocalFrame& frame, Event*, EditorCommandSource)
|
|
{
|
|
return frame.selection().isCaretOrRange() && frame.selection().isContentRichlyEditable() && frame.selection().rootEditableElement();
|
|
}
|
|
|
|
static bool enabledPaste(LocalFrame& frame, Event*, EditorCommandSource)
|
|
{
|
|
return frame.editor().canPaste();
|
|
}
|
|
|
|
static TriState stateNone(LocalFrame&, Event*)
|
|
{
|
|
return FalseTriState;
|
|
}
|
|
|
|
static String valueNull(LocalFrame&, Event*)
|
|
{
|
|
return String();
|
|
}
|
|
|
|
// Map of functions
|
|
|
|
struct CommandEntry {
|
|
const char* name;
|
|
EditorInternalCommand command;
|
|
};
|
|
|
|
static const CommandMap& createCommandMap()
|
|
{
|
|
// If you add new commands, you should assign new Id to each idForUserMetrics and update MappedEditingCommands
|
|
// in chrome/trunk/src/tools/metrics/histograms/histograms.xml.
|
|
static const CommandEntry commands[] = {
|
|
{ "Copy", {7, executeCopy, supportedCopyCut, enabledCopy, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } },
|
|
{ "Cut", {9, executeCut, supportedCopyCut, enabledCut, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } },
|
|
{ "DeleteBackward", {12, executeDeleteBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "DeleteForward", {14, executeDeleteForward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "DeleteWordBackward", {20, executeDeleteWordBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "DeleteWordForward", {21, executeDeleteWordForward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "InsertNewline", {37, executeInsertNewline, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, isTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveDown", {55, executeMoveDown, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveDownAndModifySelection", {56, executeMoveDownAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveLeft", {59, executeMoveLeft, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveLeftAndModifySelection", {60, executeMoveLeftAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MovePageDown", {61, executeMovePageDown, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MovePageDownAndModifySelection", {62, executeMovePageDownAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MovePageUp", {63, executeMovePageUp, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MovePageUpAndModifySelection", {64, executeMovePageUpAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveParagraphBackward", {65, executeMoveParagraphBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveParagraphBackwardAndModifySelection", {66, executeMoveParagraphBackwardAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveParagraphForward", {67, executeMoveParagraphForward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveParagraphForwardAndModifySelection", {68, executeMoveParagraphForwardAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveRight", {69, executeMoveRight, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveRightAndModifySelection", {70, executeMoveRightAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToBeginningOfDocument", {71, executeMoveToBeginningOfDocument, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToBeginningOfDocumentAndModifySelection", {72, executeMoveToBeginningOfDocumentAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToBeginningOfLine", {73, executeMoveToBeginningOfLine, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToBeginningOfLineAndModifySelection", {74, executeMoveToBeginningOfLineAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToEndOfDocument", {79, executeMoveToEndOfDocument, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToEndOfDocumentAndModifySelection", {80, executeMoveToEndOfDocumentAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToEndOfLine", {81, executeMoveToEndOfLine, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToEndOfLineAndModifySelection", {82, executeMoveToEndOfLineAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToLeftEndOfLine", {87, executeMoveToLeftEndOfLine, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveToLeftEndOfLineAndModifySelection", {88, executeMoveToLeftEndOfLineAndModifySelection, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveUp", {91, executeMoveUp, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveUpAndModifySelection", {92, executeMoveUpAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveWordLeft", {97, executeMoveWordLeft, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveWordLeftAndModifySelection", {98, executeMoveWordLeftAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveWordRight", {99, executeMoveWordRight, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "MoveWordRightAndModifySelection", {100, executeMoveWordRightAndModifySelection, supportedFromMenuOrKeyBinding, enabledVisibleSelection, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "OverWrite", {102, executeToggleOverwrite, supportedFromMenuOrKeyBinding, enabledInRichlyEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
{ "Paste", {103, executePaste, supportedPaste, enabledPaste, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } },
|
|
{ "PasteAndMatchStyle", {104, executePasteAndMatchStyle, supportedPaste, enabledPaste, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } },
|
|
{ "SelectAll", {115, executeSelectAll, supported, enabled, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
|
|
};
|
|
|
|
CommandMap& commandMap = *new CommandMap;
|
|
#if ENABLE(ASSERT)
|
|
HashSet<int> idSet;
|
|
#endif
|
|
for (size_t i = 0; i < WTF_ARRAY_LENGTH(commands); ++i) {
|
|
const CommandEntry& command = commands[i];
|
|
ASSERT(!commandMap.get(command.name));
|
|
commandMap.set(command.name, &command.command);
|
|
#if ENABLE(ASSERT)
|
|
ASSERT(!idSet.contains(command.command.idForUserMetrics));
|
|
idSet.add(command.command.idForUserMetrics);
|
|
#endif
|
|
}
|
|
|
|
return commandMap;
|
|
}
|
|
|
|
static const EditorInternalCommand* internalCommand(const String& commandName)
|
|
{
|
|
static const CommandMap& commandMap = createCommandMap();
|
|
return commandName.isEmpty() ? 0 : commandMap.get(commandName);
|
|
}
|
|
|
|
Editor::Command Editor::command(const String& commandName)
|
|
{
|
|
return Command(internalCommand(commandName), CommandFromMenuOrKeyBinding, &m_frame);
|
|
}
|
|
|
|
Editor::Command Editor::command(const String& commandName, EditorCommandSource source)
|
|
{
|
|
return Command(internalCommand(commandName), source, &m_frame);
|
|
}
|
|
|
|
bool Editor::executeCommand(const String& commandName)
|
|
{
|
|
// Specially handling commands that Editor::execCommand does not directly
|
|
// support.
|
|
if (commandName == "DeleteToEndOfParagraph") {
|
|
if (!deleteWithDirection(DirectionForward, ParagraphBoundary, false))
|
|
deleteWithDirection(DirectionForward, CharacterGranularity, false);
|
|
return true;
|
|
}
|
|
if (commandName == "DeleteBackward")
|
|
return command(AtomicString("BackwardDelete")).execute();
|
|
if (commandName == "DeleteForward")
|
|
return command(AtomicString("ForwardDelete")).execute();
|
|
if (commandName == "AdvanceToNextMisspelling") {
|
|
// Wee need to pass false here or else the currently selected word will never be skipped.
|
|
spellChecker().advanceToNextMisspelling(false);
|
|
return true;
|
|
}
|
|
if (commandName == "ToggleSpellPanel") {
|
|
spellChecker().showSpellingGuessPanel();
|
|
return true;
|
|
}
|
|
return command(commandName).execute();
|
|
}
|
|
|
|
bool Editor::executeCommand(const String& commandName, const String& value)
|
|
{
|
|
// moveToBeginningOfDocument and moveToEndfDocument are only handled by WebKit for editable nodes.
|
|
if (!canEdit() && commandName == "moveToBeginningOfDocument")
|
|
return m_frame.eventHandler().bubblingScroll(ScrollUp, ScrollByDocument);
|
|
|
|
if (!canEdit() && commandName == "moveToEndOfDocument")
|
|
return m_frame.eventHandler().bubblingScroll(ScrollDown, ScrollByDocument);
|
|
|
|
if (commandName == "showGuessPanel") {
|
|
spellChecker().showSpellingGuessPanel();
|
|
return true;
|
|
}
|
|
|
|
return command(commandName).execute(value);
|
|
}
|
|
|
|
Editor::Command::Command()
|
|
: m_command(0)
|
|
{
|
|
}
|
|
|
|
Editor::Command::Command(const EditorInternalCommand* command, EditorCommandSource source, PassRefPtr<LocalFrame> frame)
|
|
: m_command(command)
|
|
, m_source(source)
|
|
, m_frame(command ? frame : nullptr)
|
|
{
|
|
// Use separate assertions so we can tell which bad thing happened.
|
|
if (!command)
|
|
ASSERT(!m_frame);
|
|
else
|
|
ASSERT(m_frame);
|
|
}
|
|
|
|
bool Editor::Command::execute(const String& parameter, Event* triggeringEvent) const
|
|
{
|
|
if (!isEnabled(triggeringEvent)) {
|
|
// Let certain commands be executed when performed explicitly even if they are disabled.
|
|
if (!isSupported() || !m_frame || !m_command->allowExecutionWhenDisabled)
|
|
return false;
|
|
}
|
|
m_frame->document()->updateLayoutIgnorePendingStylesheets();
|
|
blink::Platform::current()->histogramSparse("WebCore.Editing.Commands", m_command->idForUserMetrics);
|
|
return m_command->execute(*m_frame, triggeringEvent, m_source, parameter);
|
|
}
|
|
|
|
bool Editor::Command::execute(Event* triggeringEvent) const
|
|
{
|
|
return execute(String(), triggeringEvent);
|
|
}
|
|
|
|
bool Editor::Command::isSupported() const
|
|
{
|
|
if (!m_command)
|
|
return false;
|
|
switch (m_source) {
|
|
case CommandFromMenuOrKeyBinding:
|
|
return true;
|
|
case CommandFromDOM:
|
|
case CommandFromDOMWithUserInterface:
|
|
return m_command->isSupportedFromDOM(m_frame.get());
|
|
}
|
|
ASSERT_NOT_REACHED();
|
|
return false;
|
|
}
|
|
|
|
bool Editor::Command::isEnabled(Event* triggeringEvent) const
|
|
{
|
|
if (!isSupported() || !m_frame)
|
|
return false;
|
|
return m_command->isEnabled(*m_frame, triggeringEvent, m_source);
|
|
}
|
|
|
|
TriState Editor::Command::state(Event* triggeringEvent) const
|
|
{
|
|
if (!isSupported() || !m_frame)
|
|
return FalseTriState;
|
|
return m_command->state(*m_frame, triggeringEvent);
|
|
}
|
|
|
|
String Editor::Command::value(Event* triggeringEvent) const
|
|
{
|
|
if (!isSupported() || !m_frame)
|
|
return String();
|
|
if (m_command->value == valueNull && m_command->state != stateNone)
|
|
return m_command->state(*m_frame, triggeringEvent) == TrueTriState ? "true" : "false";
|
|
return m_command->value(*m_frame, triggeringEvent);
|
|
}
|
|
|
|
bool Editor::Command::isTextInsertion() const
|
|
{
|
|
return m_command && m_command->isTextInsertion;
|
|
}
|
|
|
|
int Editor::Command::idForHistogram() const
|
|
{
|
|
return isSupported() ? m_command->idForUserMetrics : 0;
|
|
}
|
|
|
|
} // namespace blink
|