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