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 "ClipboardAccessPolicy.h"
30#include "Color.h"
31#include "DocumentMarker.h"
32#include "EditAction.h"
33#include "EditingBehavior.h"
34#include "EditorDeleteAction.h"
35#include "EditorInsertAction.h"
36#include "FindOptions.h"
37#include "SelectionController.h"
38#include "TextChecking.h"
39#include "Timer.h"
40#include "VisibleSelection.h"
41#include "WritingDirection.h"
42
43#if PLATFORM(MAC) && !defined(__OBJC__)
44class NSDictionary;
45typedef int NSWritingDirection;
46#endif
47
48namespace WebCore {
49
50class CSSMutableStyleDeclaration;
51class CSSStyleDeclaration;
52class Clipboard;
53class SpellingCorrectionController;
54class DeleteButtonController;
55class EditCommand;
56class EditorClient;
57class EditorInternalCommand;
58class Frame;
59class HTMLElement;
60class HitTestResult;
61class KillRing;
62class Pasteboard;
63class SimpleFontData;
64class SpellChecker;
65class Text;
66class TextCheckerClient;
67class TextEvent;
68
69struct CompositionUnderline {
70    CompositionUnderline()
71        : startOffset(0), endOffset(0), thick(false) { }
72    CompositionUnderline(unsigned s, unsigned e, const Color& c, bool t)
73        : startOffset(s), endOffset(e), color(c), thick(t) { }
74    unsigned startOffset;
75    unsigned endOffset;
76    Color color;
77    bool thick;
78};
79
80enum EditorCommandSource { CommandFromMenuOrKeyBinding, CommandFromDOM, CommandFromDOMWithUserInterface };
81
82class Editor {
83public:
84    Editor(Frame*);
85    ~Editor();
86
87    EditorClient* client() const;
88    TextCheckerClient* textChecker() const;
89
90    Frame* frame() const { return m_frame; }
91    DeleteButtonController* deleteButtonController() const { return m_deleteButtonController.get(); }
92    EditCommand* lastEditCommand() { return m_lastEditCommand.get(); }
93
94    void handleKeyboardEvent(KeyboardEvent*);
95    void handleInputMethodKeydown(KeyboardEvent*);
96    bool handleTextEvent(TextEvent*);
97
98    bool canEdit() const;
99    bool canEditRichly() const;
100
101    bool canDHTMLCut();
102    bool canDHTMLCopy();
103    bool canDHTMLPaste();
104    bool tryDHTMLCopy();
105    bool tryDHTMLCut();
106    bool tryDHTMLPaste();
107
108    bool canCut() const;
109    bool canCopy() const;
110    bool canPaste() const;
111    bool canDelete() const;
112    bool canSmartCopyOrDelete();
113
114    void cut();
115    void copy();
116    void paste();
117    void pasteAsPlainText();
118    void performDelete();
119
120    void copyURL(const KURL&, const String&);
121    void copyImage(const HitTestResult&);
122
123    void indent();
124    void outdent();
125    void transpose();
126
127    bool shouldInsertFragment(PassRefPtr<DocumentFragment>, PassRefPtr<Range>, EditorInsertAction);
128    bool shouldInsertText(const String&, Range*, EditorInsertAction) const;
129    bool shouldShowDeleteInterface(HTMLElement*) const;
130    bool shouldDeleteRange(Range*) const;
131    bool shouldApplyStyle(CSSStyleDeclaration*, Range*);
132
133    void respondToChangedSelection(const VisibleSelection& oldSelection);
134    void respondToChangedContents(const VisibleSelection& endingSelection);
135
136    bool selectionStartHasStyle(int propertyID, const String& value) const;
137    TriState selectionHasStyle(int propertyID, const String& value) const;
138    String selectionStartCSSPropertyValue(int propertyID);
139    const SimpleFontData* fontForSelection(bool&) const;
140    WritingDirection textDirectionForSelection(bool&) const;
141
142    TriState selectionUnorderedListState() const;
143    TriState selectionOrderedListState() const;
144    PassRefPtr<Node> insertOrderedList();
145    PassRefPtr<Node> insertUnorderedList();
146    bool canIncreaseSelectionListLevel();
147    bool canDecreaseSelectionListLevel();
148    PassRefPtr<Node> increaseSelectionListLevel();
149    PassRefPtr<Node> increaseSelectionListLevelOrdered();
150    PassRefPtr<Node> increaseSelectionListLevelUnordered();
151    void decreaseSelectionListLevel();
152
153    void removeFormattingAndStyle();
154
155    void clearLastEditCommand();
156
157    bool deleteWithDirection(SelectionDirection, TextGranularity, bool killRing, bool isTypingAction);
158    void deleteSelectionWithSmartDelete(bool smartDelete);
159    bool dispatchCPPEvent(const AtomicString&, ClipboardAccessPolicy);
160
161    Node* removedAnchor() const { return m_removedAnchor.get(); }
162    void setRemovedAnchor(PassRefPtr<Node> n) { m_removedAnchor = n; }
163
164    void applyStyle(CSSStyleDeclaration*, EditAction = EditActionUnspecified);
165    void applyParagraphStyle(CSSStyleDeclaration*, EditAction = EditActionUnspecified);
166    void applyStyleToSelection(CSSStyleDeclaration*, EditAction);
167    void applyParagraphStyleToSelection(CSSStyleDeclaration*, EditAction);
168
169    void appliedEditing(PassRefPtr<EditCommand>);
170    void unappliedEditing(PassRefPtr<EditCommand>);
171    void reappliedEditing(PassRefPtr<EditCommand>);
172    void unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction);
173
174    void setShouldStyleWithCSS(bool flag) { m_shouldStyleWithCSS = flag; }
175    bool shouldStyleWithCSS() const { return m_shouldStyleWithCSS; }
176
177    class Command {
178    public:
179        Command();
180        Command(const EditorInternalCommand*, EditorCommandSource, PassRefPtr<Frame>);
181
182        bool execute(const String& parameter = String(), Event* triggeringEvent = 0) const;
183        bool execute(Event* triggeringEvent) const;
184
185        bool isSupported() const;
186        bool isEnabled(Event* triggeringEvent = 0) const;
187
188        TriState state(Event* triggeringEvent = 0) const;
189        String value(Event* triggeringEvent = 0) const;
190
191        bool isTextInsertion() const;
192
193    private:
194        const EditorInternalCommand* m_command;
195        EditorCommandSource m_source;
196        RefPtr<Frame> m_frame;
197    };
198    Command command(const String& commandName); // Command source is CommandFromMenuOrKeyBinding.
199    Command command(const String& commandName, EditorCommandSource);
200    static bool commandIsSupportedFromMenuOrKeyBinding(const String& commandName); // Works without a frame.
201
202    bool insertText(const String&, Event* triggeringEvent);
203    bool insertTextForConfirmedComposition(const String& text);
204    bool insertTextWithoutSendingTextEvent(const String&, bool selectInsertedText, TextEvent* triggeringEvent);
205    bool insertLineBreak();
206    bool insertParagraphSeparator();
207
208    bool isContinuousSpellCheckingEnabled();
209    void toggleContinuousSpellChecking();
210    bool isGrammarCheckingEnabled();
211    void toggleGrammarChecking();
212    void ignoreSpelling();
213    void learnSpelling();
214    int spellCheckerDocumentTag();
215    bool isSelectionUngrammatical();
216    bool isSelectionMisspelled();
217    Vector<String> guessesForMisspelledSelection();
218    Vector<String> guessesForUngrammaticalSelection();
219    Vector<String> guessesForMisspelledOrUngrammaticalSelection(bool& misspelled, bool& ungrammatical);
220    bool isSpellCheckingEnabledInFocusedNode() const;
221    bool isSpellCheckingEnabledFor(Node*) const;
222    void markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping, bool doReplacement);
223    void markMisspellings(const VisibleSelection&, RefPtr<Range>& firstMisspellingRange);
224    void markBadGrammar(const VisibleSelection&);
225    void markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection);
226
227    enum TextCheckingOptionFlags {
228        MarkSpelling = 1 << 0,
229        MarkGrammar = 1 << 1,
230        PerformReplacement = 1 << 2,
231        ShowCorrectionPanel = 1 << 3,
232        CheckForCorrection = 1 << 4,
233    };
234    typedef unsigned TextCheckingOptions;
235
236#if USE(AUTOMATIC_TEXT_REPLACEMENT)
237    void uppercaseWord();
238    void lowercaseWord();
239    void capitalizeWord();
240    void showSubstitutionsPanel();
241    bool substitutionsPanelIsShowing();
242    void toggleSmartInsertDelete();
243    bool isAutomaticQuoteSubstitutionEnabled();
244    void toggleAutomaticQuoteSubstitution();
245    bool isAutomaticLinkDetectionEnabled();
246    void toggleAutomaticLinkDetection();
247    bool isAutomaticDashSubstitutionEnabled();
248    void toggleAutomaticDashSubstitution();
249    bool isAutomaticTextReplacementEnabled();
250    void toggleAutomaticTextReplacement();
251    bool isAutomaticSpellingCorrectionEnabled();
252    void toggleAutomaticSpellingCorrection();
253#endif
254
255    void markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions, Range* spellingRange, Range* grammarRange);
256    void changeBackToReplacedString(const String& replacedString);
257
258    void advanceToNextMisspelling(bool startBeforeSelection = false);
259    void showSpellingGuessPanel();
260    bool spellingPanelIsShowing();
261
262    bool shouldBeginEditing(Range*);
263    bool shouldEndEditing(Range*);
264
265    void clearUndoRedoOperations();
266    bool canUndo();
267    void undo();
268    bool canRedo();
269    void redo();
270
271    void didBeginEditing();
272    void didEndEditing();
273    void didWriteSelectionToPasteboard();
274
275    void showFontPanel();
276    void showStylesPanel();
277    void showColorPanel();
278    void toggleBold();
279    void toggleUnderline();
280    void setBaseWritingDirection(WritingDirection);
281
282    // smartInsertDeleteEnabled and selectTrailingWhitespaceEnabled are
283    // mutually exclusive, meaning that enabling one will disable the other.
284    bool smartInsertDeleteEnabled();
285    bool isSelectTrailingWhitespaceEnabled();
286
287    bool hasBidiSelection() const;
288
289    // international text input composition
290    bool hasComposition() const { return m_compositionNode; }
291    void setComposition(const String&, const Vector<CompositionUnderline>&, unsigned selectionStart, unsigned selectionEnd);
292    void confirmComposition();
293    void confirmComposition(const String&); // if no existing composition, replaces selection
294    void confirmCompositionWithoutDisturbingSelection();
295    PassRefPtr<Range> compositionRange() const;
296    bool getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const;
297
298    // getting international text input composition state (for use by InlineTextBox)
299    Text* compositionNode() const { return m_compositionNode.get(); }
300    unsigned compositionStart() const { return m_compositionStart; }
301    unsigned compositionEnd() const { return m_compositionEnd; }
302    bool compositionUsesCustomUnderlines() const { return !m_customCompositionUnderlines.isEmpty(); }
303    const Vector<CompositionUnderline>& customCompositionUnderlines() const { return m_customCompositionUnderlines; }
304
305    bool ignoreCompositionSelectionChange() const { return m_ignoreCompositionSelectionChange; }
306
307    void setStartNewKillRingSequence(bool);
308
309    PassRefPtr<Range> rangeForPoint(const IntPoint& windowPoint);
310
311    void clear();
312
313    VisibleSelection selectionForCommand(Event*);
314
315    KillRing* killRing() const { return m_killRing.get(); }
316    SpellChecker* spellChecker() const { return m_spellChecker.get(); }
317
318    EditingBehavior behavior() const;
319
320    PassRefPtr<Range> selectedRange();
321
322    // We should make these functions private when their callers in Frame are moved over here to Editor
323    bool insideVisibleArea(const IntPoint&) const;
324    bool insideVisibleArea(Range*) const;
325
326    void addToKillRing(Range*, bool prepend);
327
328    void startCorrectionPanelTimer();
329    // If user confirmed a correction in the correction panel, correction has non-zero length, otherwise it means that user has dismissed the panel.
330    void handleCorrectionPanelResult(const String& correction);
331    void dismissCorrectionPanelAsIgnored();
332
333    void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle);
334    void pasteAsPlainText(const String&, bool smartReplace);
335
336    // This is only called on the mac where paste is implemented primarily at the WebKit level.
337    void pasteAsPlainTextBypassingDHTML();
338
339    void clearMisspellingsAndBadGrammar(const VisibleSelection&);
340    void markMisspellingsAndBadGrammar(const VisibleSelection&);
341
342    Node* findEventTargetFrom(const VisibleSelection& selection) const;
343
344    String selectedText() const;
345    bool findString(const String&, FindOptions);
346    // FIXME: Switch callers over to the FindOptions version and retire this one.
347    bool findString(const String&, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection);
348
349    const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
350    void setMark(const VisibleSelection&);
351
352    void computeAndSetTypingStyle(CSSStyleDeclaration* , EditAction = EditActionUnspecified);
353    void applyEditingStyleToBodyElement() const;
354    void applyEditingStyleToElement(Element*) const;
355
356    IntRect firstRectForRange(Range*) const;
357
358    void respondToChangedSelection(const VisibleSelection& oldSelection, SelectionController::SetSelectionOptions);
359    bool shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity, bool stillSelecting) const;
360
361    RenderStyle* styleForSelectionStart(Node*& nodeToRemove) const;
362
363    unsigned countMatchesForText(const String&, FindOptions, unsigned limit, bool markMatches);
364    unsigned countMatchesForText(const String&, Range*, FindOptions, unsigned limit, bool markMatches);
365    bool markedTextMatchesAreHighlighted() const;
366    void setMarkedTextMatchesAreHighlighted(bool);
367
368    PassRefPtr<EditingStyle> selectionStartStyle() const;
369
370    void textFieldDidBeginEditing(Element*);
371    void textFieldDidEndEditing(Element*);
372    void textDidChangeInTextField(Element*);
373    bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*);
374    void textWillBeDeletedInTextField(Element* input);
375    void textDidChangeInTextArea(Element*);
376
377#if PLATFORM(MAC)
378    NSDictionary* fontAttributesForSelectionStart() const;
379    NSWritingDirection baseWritingDirectionForSelectionStart() const;
380    bool canCopyExcludingStandaloneImages();
381    void takeFindStringFromSelection();
382    void writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes);
383    void readSelectionFromPasteboard(const String& pasteboardName);
384#endif
385
386    bool selectionStartHasMarkerFor(DocumentMarker::MarkerType, int from, int length) const;
387    void updateMarkersForWordsAffectedByEditing(bool onlyHandleWordsContainingSelection);
388
389private:
390    Frame* m_frame;
391    OwnPtr<DeleteButtonController> m_deleteButtonController;
392    RefPtr<EditCommand> m_lastEditCommand;
393    RefPtr<Node> m_removedAnchor;
394    RefPtr<Text> m_compositionNode;
395    unsigned m_compositionStart;
396    unsigned m_compositionEnd;
397    Vector<CompositionUnderline> m_customCompositionUnderlines;
398    bool m_ignoreCompositionSelectionChange;
399    bool m_shouldStartNewKillRingSequence;
400    bool m_shouldStyleWithCSS;
401    OwnPtr<KillRing> m_killRing;
402    OwnPtr<SpellChecker> m_spellChecker;
403    OwnPtr<SpellingCorrectionController> m_spellingCorrector;
404    VisibleSelection m_mark;
405    bool m_areMarkedTextMatchesHighlighted;
406
407    bool canDeleteRange(Range*) const;
408    bool canSmartReplaceWithPasteboard(Pasteboard*);
409    PassRefPtr<Clipboard> newGeneralClipboard(ClipboardAccessPolicy, Frame*);
410    void pasteAsPlainTextWithPasteboard(Pasteboard*);
411    void pasteWithPasteboard(Pasteboard*, bool allowPlainText);
412    void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle);
413    void replaceSelectionWithText(const String&, bool selectReplacement, bool smartReplace);
414    void writeSelectionToPasteboard(Pasteboard*);
415    void revealSelectionAfterEditingOperation();
416    void markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling, RefPtr<Range>& firstMisspellingRange);
417    TextCheckingTypeMask textCheckingTypeMaskFor(TextCheckingOptions);
418
419    void selectComposition();
420    void confirmComposition(const String&, bool preserveSelection);
421    void setIgnoreCompositionSelectionChange(bool ignore);
422
423    PassRefPtr<Range> firstVisibleRange(const String&, FindOptions);
424    PassRefPtr<Range> lastVisibleRange(const String&, FindOptions);
425    PassRefPtr<Range> nextVisibleRange(Range*, const String&, FindOptions);
426
427    void changeSelectionAfterCommand(const VisibleSelection& newSelection, bool closeTyping, bool clearTypingStyle);
428
429    Node* findEventTargetFromSelection() const;
430    void stopCorrectionPanelTimer();
431
432    void applyCorrectionPanelInfo(const Vector<DocumentMarker::MarkerType>& markerTypesToAdd);
433    // Return true if correction was applied, false otherwise.
434    bool applyAutocorrectionBeforeTypingIfAppropriate();
435    FloatRect windowRectForRange(const Range*) const;
436};
437
438inline void Editor::setStartNewKillRingSequence(bool flag)
439{
440    m_shouldStartNewKillRingSequence = flag;
441}
442
443inline const VisibleSelection& Editor::mark() const
444{
445    return m_mark;
446}
447
448inline void Editor::setMark(const VisibleSelection& selection)
449{
450    m_mark = selection;
451}
452
453inline bool Editor::markedTextMatchesAreHighlighted() const
454{
455    return m_areMarkedTextMatchesHighlighted;
456}
457
458
459} // namespace WebCore
460
461#endif // Editor_h
462