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