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