1/*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef Editor_h
27#define Editor_h
28
29#include "core/dom/ClipboardAccessPolicy.h"
30#include "core/dom/DocumentMarker.h"
31#include "core/editing/EditAction.h"
32#include "core/editing/EditingBehavior.h"
33#include "core/editing/FindOptions.h"
34#include "core/editing/FrameSelection.h"
35#include "core/editing/TextIterator.h"
36#include "core/editing/VisibleSelection.h"
37#include "core/editing/WritingDirection.h"
38#include "core/frame/FrameDestructionObserver.h"
39#include "platform/PasteMode.h"
40
41namespace WebCore {
42
43class Clipboard;
44class CompositeEditCommand;
45class EditCommand;
46class EditCommandComposition;
47class EditorClient;
48class EditorInternalCommand;
49class Frame;
50class HTMLElement;
51class HitTestResult;
52class KillRing;
53class Pasteboard;
54class SharedBuffer;
55class SimpleFontData;
56class SpellChecker;
57class StylePropertySet;
58class Text;
59class TextEvent;
60class UndoStack;
61
62enum EditorCommandSource { CommandFromMenuOrKeyBinding, CommandFromDOM, CommandFromDOMWithUserInterface };
63enum EditorParagraphSeparator { EditorParagraphSeparatorIsDiv, EditorParagraphSeparatorIsP };
64
65class Editor {
66    WTF_MAKE_NONCOPYABLE(Editor);
67public:
68    static PassOwnPtr<Editor> create(Frame&);
69    ~Editor();
70
71    EditorClient& client() const;
72
73    Frame& frame() const { return m_frame; }
74
75    CompositeEditCommand* lastEditCommand() { return m_lastEditCommand.get(); }
76
77    void handleKeyboardEvent(KeyboardEvent*);
78    bool handleTextEvent(TextEvent*);
79
80    bool canEdit() const;
81    bool canEditRichly() const;
82
83    bool canDHTMLCut();
84    bool canDHTMLCopy();
85    bool canDHTMLPaste();
86
87    bool canCut() const;
88    bool canCopy() const;
89    bool canPaste() const;
90    bool canDelete() const;
91    bool canSmartCopyOrDelete() const;
92
93    void cut();
94    void copy();
95    void paste();
96    void pasteAsPlainText();
97    void performDelete();
98
99    void copyImage(const HitTestResult&);
100
101    void indent();
102    void outdent();
103    void transpose();
104
105    bool shouldDeleteRange(Range*) const;
106
107    void respondToChangedContents(const VisibleSelection& endingSelection);
108
109    bool selectionStartHasStyle(CSSPropertyID, const String& value) const;
110    TriState selectionHasStyle(CSSPropertyID, const String& value) const;
111    String selectionStartCSSPropertyValue(CSSPropertyID);
112
113    TriState selectionUnorderedListState() const;
114    TriState selectionOrderedListState() const;
115    PassRefPtr<Node> insertOrderedList();
116    PassRefPtr<Node> insertUnorderedList();
117    bool canIncreaseSelectionListLevel();
118    bool canDecreaseSelectionListLevel();
119    PassRefPtr<Node> increaseSelectionListLevel();
120    PassRefPtr<Node> increaseSelectionListLevelOrdered();
121    PassRefPtr<Node> increaseSelectionListLevelUnordered();
122    void decreaseSelectionListLevel();
123
124    void removeFormattingAndStyle();
125
126    void clearLastEditCommand();
127
128    bool deleteWithDirection(SelectionDirection, TextGranularity, bool killRing, bool isTypingAction);
129    void deleteSelectionWithSmartDelete(bool smartDelete);
130
131    void applyStyle(StylePropertySet*, EditAction = EditActionUnspecified);
132    void applyParagraphStyle(StylePropertySet*, EditAction = EditActionUnspecified);
133    void applyStyleToSelection(StylePropertySet*, EditAction);
134    void applyParagraphStyleToSelection(StylePropertySet*, EditAction);
135
136    void appliedEditing(PassRefPtr<CompositeEditCommand>);
137    void unappliedEditing(PassRefPtr<EditCommandComposition>);
138    void reappliedEditing(PassRefPtr<EditCommandComposition>);
139
140    void setShouldStyleWithCSS(bool flag) { m_shouldStyleWithCSS = flag; }
141    bool shouldStyleWithCSS() const { return m_shouldStyleWithCSS; }
142
143    class Command {
144    public:
145        Command();
146        Command(const EditorInternalCommand*, EditorCommandSource, PassRefPtr<Frame>);
147
148        bool execute(const String& parameter = String(), Event* triggeringEvent = 0) const;
149        bool execute(Event* triggeringEvent) const;
150
151        bool isSupported() const;
152        bool isEnabled(Event* triggeringEvent = 0) const;
153
154        TriState state(Event* triggeringEvent = 0) const;
155        String value(Event* triggeringEvent = 0) const;
156
157        bool isTextInsertion() const;
158
159    private:
160        const EditorInternalCommand* m_command;
161        EditorCommandSource m_source;
162        RefPtr<Frame> m_frame;
163    };
164    Command command(const String& commandName); // Command source is CommandFromMenuOrKeyBinding.
165    Command command(const String& commandName, EditorCommandSource);
166    static bool commandIsSupportedFromMenuOrKeyBinding(const String& commandName); // Works without a frame.
167
168    bool insertText(const String&, Event* triggeringEvent);
169    bool insertTextWithoutSendingTextEvent(const String&, bool selectInsertedText, TextEvent* triggeringEvent);
170    bool insertLineBreak();
171    bool insertParagraphSeparator();
172
173    bool isOverwriteModeEnabled() const { return m_overwriteModeEnabled; }
174    void toggleOverwriteModeEnabled();
175
176    bool canUndo();
177    void undo();
178    bool canRedo();
179    void redo();
180
181    void setBaseWritingDirection(WritingDirection);
182
183    // smartInsertDeleteEnabled and selectTrailingWhitespaceEnabled are
184    // mutually exclusive, meaning that enabling one will disable the other.
185    bool smartInsertDeleteEnabled() const;
186    bool isSelectTrailingWhitespaceEnabled() const;
187
188    bool preventRevealSelection() const { return m_preventRevealSelection; }
189
190    void setStartNewKillRingSequence(bool);
191
192    void clear();
193
194    VisibleSelection selectionForCommand(Event*);
195
196    KillRing& killRing() const { return *m_killRing; }
197
198    EditingBehavior behavior() const;
199
200    PassRefPtr<Range> selectedRange();
201
202    void addToKillRing(Range*, bool prepend);
203
204    void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle);
205    void pasteAsPlainText(const String&, bool smartReplace);
206
207    Node* findEventTargetFrom(const VisibleSelection&) const;
208
209    bool findString(const String&, FindOptions);
210    // FIXME: Switch callers over to the FindOptions version and retire this one.
211    bool findString(const String&, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection);
212
213    PassRefPtr<Range> findStringAndScrollToVisible(const String&, Range*, FindOptions);
214
215    const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
216    void setMark(const VisibleSelection&);
217
218    void computeAndSetTypingStyle(StylePropertySet* , EditAction = EditActionUnspecified);
219
220    IntRect firstRectForRange(Range*) const;
221
222    void respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions);
223
224    bool markedTextMatchesAreHighlighted() const;
225    void setMarkedTextMatchesAreHighlighted(bool);
226
227    void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle);
228    void replaceSelectionWithText(const String&, bool selectReplacement, bool smartReplace);
229
230    EditorParagraphSeparator defaultParagraphSeparator() const { return m_defaultParagraphSeparator; }
231    void setDefaultParagraphSeparator(EditorParagraphSeparator separator) { m_defaultParagraphSeparator = separator; }
232
233    class RevealSelectionScope {
234        WTF_MAKE_NONCOPYABLE(RevealSelectionScope);
235    public:
236        RevealSelectionScope(Editor*);
237        ~RevealSelectionScope();
238    private:
239        Editor* m_editor;
240    };
241    friend class RevealSelectionScope;
242
243    // Export interpretKeyEvent only for testing
244    static const char* interpretKeyEvent(const WebCore::KeyboardEvent*);
245
246private:
247    Frame& m_frame;
248    RefPtr<CompositeEditCommand> m_lastEditCommand;
249    int m_preventRevealSelection;
250    bool m_shouldStartNewKillRingSequence;
251    bool m_shouldStyleWithCSS;
252    const OwnPtr<KillRing> m_killRing;
253    VisibleSelection m_mark;
254    bool m_areMarkedTextMatchesHighlighted;
255    EditorParagraphSeparator m_defaultParagraphSeparator;
256    bool m_overwriteModeEnabled;
257
258    explicit Editor(Frame&);
259
260    bool canDeleteRange(Range*) const;
261
262    UndoStack* undoStack() const;
263
264    bool tryDHTMLCopy();
265    bool tryDHTMLCut();
266    bool tryDHTMLPaste(PasteMode);
267
268    bool canSmartReplaceWithPasteboard(Pasteboard*);
269    void pasteAsPlainTextWithPasteboard(Pasteboard*);
270    void pasteWithPasteboard(Pasteboard*);
271    void writeSelectionToPasteboard(Pasteboard*, Range*, const String& plainText);
272    bool dispatchCPPEvent(const AtomicString&, ClipboardAccessPolicy, PasteMode = AllMimeTypes);
273
274    void revealSelectionAfterEditingOperation(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);
275    void changeSelectionAfterCommand(const VisibleSelection& newSelection, FrameSelection::SetSelectionOptions);
276    void notifyComponentsOnChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions);
277
278    Node* findEventTargetFromSelection() const;
279
280    PassRefPtr<Range> rangeOfString(const String&, Range*, FindOptions);
281
282    SpellChecker& spellChecker() const;
283
284    bool handleEditingKeyboardEvent(WebCore::KeyboardEvent*);
285};
286
287inline void Editor::setStartNewKillRingSequence(bool flag)
288{
289    m_shouldStartNewKillRingSequence = flag;
290}
291
292inline const VisibleSelection& Editor::mark() const
293{
294    return m_mark;
295}
296
297inline void Editor::setMark(const VisibleSelection& selection)
298{
299    m_mark = selection;
300}
301
302inline bool Editor::markedTextMatchesAreHighlighted() const
303{
304    return m_areMarkedTextMatchesHighlighted;
305}
306
307
308} // namespace WebCore
309
310#endif // Editor_h
311