2010-10-31 Xan Lopez <xlopez@igalia.com>
[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(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
38 // Some platforms provide UI for suggesting autocorrection.
39 #define SUPPORT_AUTOCORRECTION_PANEL 1
40 // Some platforms use spelling and autocorrection markers to provide visual cue.
41 // On such platform, if word with marker is edited, we need to remove the marker.
42 #define REMOVE_MARKERS_UPON_EDITING 1
43 #else
44 #define SUPPORT_AUTOCORRECTION_PANEL 0
45 #define REMOVE_MARKERS_UPON_EDITING 0
46 #endif /* #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) */
47
48 #if PLATFORM(MAC) && !defined(__OBJC__)
49 class NSDictionary;
50 typedef int NSWritingDirection;
51 #endif
52
53 namespace WebCore {
54
55 class CSSStyleDeclaration;
56 class Clipboard;
57 class DeleteButtonController;
58 class EditCommand;
59 class EditorClient;
60 class EditorInternalCommand;
61 class Frame;
62 class HTMLElement;
63 class HitTestResult;
64 class KillRing;
65 class Pasteboard;
66 class SimpleFontData;
67 class Text;
68 class TextEvent;
69
70 struct CompositionUnderline {
71     CompositionUnderline() 
72         : startOffset(0), endOffset(0), thick(false) { }
73     CompositionUnderline(unsigned s, unsigned e, const Color& c, bool t) 
74         : startOffset(s), endOffset(e), color(c), thick(t) { }
75     unsigned startOffset;
76     unsigned endOffset;
77     Color color;
78     bool thick;
79 };
80
81 enum TriState { FalseTriState, TrueTriState, MixedTriState };
82 enum EditorCommandSource { CommandFromMenuOrKeyBinding, CommandFromDOM, CommandFromDOMWithUserInterface };
83 enum WritingDirection { NaturalWritingDirection, LeftToRightWritingDirection, RightToLeftWritingDirection };
84
85 class Editor {
86 public:
87     Editor(Frame*);
88     ~Editor();
89
90     EditorClient* client() const;
91     Frame* frame() const { return m_frame; }
92     DeleteButtonController* deleteButtonController() const { return m_deleteButtonController.get(); }
93     EditCommand* lastEditCommand() { return m_lastEditCommand.get(); }
94
95     void handleKeyboardEvent(KeyboardEvent*);
96     void handleInputMethodKeydown(KeyboardEvent*);
97     bool handleTextEvent(TextEvent*);
98
99     bool canEdit() const;
100     bool canEditRichly() const;
101
102     bool canDHTMLCut();
103     bool canDHTMLCopy();
104     bool canDHTMLPaste();
105     bool tryDHTMLCopy();
106     bool tryDHTMLCut();
107     bool tryDHTMLPaste();
108
109     bool canCut() const;
110     bool canCopy() const;
111     bool canPaste() const;
112     bool canDelete() const;
113     bool canSmartCopyOrDelete();
114
115     void cut();
116     void copy();
117     void paste();
118     void pasteAsPlainText();
119     void performDelete();
120
121     void copyURL(const KURL&, const String&);
122     void copyImage(const HitTestResult&);
123
124     void indent();
125     void outdent();
126     void transpose();
127
128     bool shouldInsertFragment(PassRefPtr<DocumentFragment>, PassRefPtr<Range>, EditorInsertAction);
129     bool shouldInsertText(const String&, Range*, EditorInsertAction) const;
130     bool shouldShowDeleteInterface(HTMLElement*) const;
131     bool shouldDeleteRange(Range*) const;
132     bool shouldApplyStyle(CSSStyleDeclaration*, Range*);
133     
134     void respondToChangedSelection(const VisibleSelection& oldSelection);
135     void respondToChangedContents(const VisibleSelection& endingSelection);
136
137     TriState selectionHasStyle(CSSStyleDeclaration*) 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(SelectionController::EDirection, 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     
173     bool selectionStartHasStyle(CSSStyleDeclaration*) const;
174
175     bool clientIsEditable() const;
176     
177     void setShouldStyleWithCSS(bool flag) { m_shouldStyleWithCSS = flag; }
178     bool shouldStyleWithCSS() const { return m_shouldStyleWithCSS; }
179
180     class Command {
181     public:
182         Command();
183         Command(PassRefPtr<Frame>, const EditorInternalCommand*, EditorCommandSource);
184
185         bool execute(const String& parameter = String(), Event* triggeringEvent = 0) const;
186         bool execute(Event* triggeringEvent) const;
187
188         bool isSupported() const;
189         bool isEnabled(Event* triggeringEvent = 0) const;
190
191         TriState state(Event* triggeringEvent = 0) const;
192         String value(Event* triggeringEvent = 0) const;
193
194         bool isTextInsertion() const;
195
196     private:
197         RefPtr<Frame> m_frame;
198         const EditorInternalCommand* m_command;
199         EditorCommandSource m_source;
200     };
201     Command command(const String& commandName); // Default is CommandFromMenuOrKeyBinding.
202     Command command(const String& commandName, EditorCommandSource);
203
204     bool insertText(const String&, Event* triggeringEvent);
205     bool insertTextWithoutSendingTextEvent(const String&, bool selectInsertedText, Event* triggeringEvent);
206     bool insertLineBreak();
207     bool insertParagraphSeparator();
208     
209     bool isContinuousSpellCheckingEnabled();
210     void toggleContinuousSpellChecking();
211     bool isGrammarCheckingEnabled();
212     void toggleGrammarChecking();
213     void ignoreSpelling();
214     void learnSpelling();
215     int spellCheckerDocumentTag();
216     bool isSelectionUngrammatical();
217     bool isSelectionMisspelled();
218     Vector<String> guessesForMisspelledSelection();
219     Vector<String> guessesForUngrammaticalSelection();
220     Vector<String> guessesForMisspelledOrUngrammaticalSelection(bool& misspelled, bool& ungrammatical);
221     bool isSpellCheckingEnabledInFocusedNode() const;
222     void markMisspellingsAfterTypingToPosition(const VisiblePosition&);
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 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
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     enum TextCheckingOptionFlags {
244         MarkSpelling = 1 << 0,
245         MarkGrammar = 1 << 1,
246         PerformReplacement = 1 << 2,
247         ShowCorrectionPanel = 1 << 3,
248     };
249     typedef unsigned TextCheckingOptions;
250
251     void markAllMisspellingsAndBadGrammarInRanges(TextCheckingOptions, Range* spellingRange, Range* grammarRange);
252     void changeBackToReplacedString(const String& replacedString);
253 #endif
254     void advanceToNextMisspelling(bool startBeforeSelection = false);
255     void showSpellingGuessPanel();
256     bool spellingPanelIsShowing();
257
258     bool shouldBeginEditing(Range*);
259     bool shouldEndEditing(Range*);
260
261     void clearUndoRedoOperations();
262     bool canUndo();
263     void undo();
264     bool canRedo();
265     void redo();
266
267     void didBeginEditing();
268     void didEndEditing();
269     void didWriteSelectionToPasteboard();
270     
271     void showFontPanel();
272     void showStylesPanel();
273     void showColorPanel();
274     void toggleBold();
275     void toggleUnderline();
276     void setBaseWritingDirection(WritingDirection);
277
278     // smartInsertDeleteEnabled and selectTrailingWhitespaceEnabled are 
279     // mutually exclusive, meaning that enabling one will disable the other.
280     bool smartInsertDeleteEnabled();
281     bool isSelectTrailingWhitespaceEnabled();
282     
283     bool hasBidiSelection() const;
284
285     // international text input composition
286     bool hasComposition() const { return m_compositionNode; }
287     void setComposition(const String&, const Vector<CompositionUnderline>&, unsigned selectionStart, unsigned selectionEnd);
288     void confirmComposition();
289     void confirmComposition(const String&); // if no existing composition, replaces selection
290     void confirmCompositionWithoutDisturbingSelection();
291     PassRefPtr<Range> compositionRange() const;
292     bool getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const;
293
294     // getting international text input composition state (for use by InlineTextBox)
295     Text* compositionNode() const { return m_compositionNode.get(); }
296     unsigned compositionStart() const { return m_compositionStart; }
297     unsigned compositionEnd() const { return m_compositionEnd; }
298     bool compositionUsesCustomUnderlines() const { return !m_customCompositionUnderlines.isEmpty(); }
299     const Vector<CompositionUnderline>& customCompositionUnderlines() const { return m_customCompositionUnderlines; }
300
301     bool ignoreCompositionSelectionChange() const { return m_ignoreCompositionSelectionChange; }
302
303     void setStartNewKillRingSequence(bool);
304
305     PassRefPtr<Range> rangeForPoint(const IntPoint& windowPoint);
306
307     void clear();
308
309     VisibleSelection selectionForCommand(Event*);
310
311     KillRing* killRing() const { return m_killRing.get(); }
312
313     EditingBehavior behavior() const;
314
315     PassRefPtr<Range> selectedRange();
316     
317     // We should make these functions private when their callers in Frame are moved over here to Editor
318     bool insideVisibleArea(const IntPoint&) const;
319     bool insideVisibleArea(Range*) const;
320     PassRefPtr<Range> nextVisibleRange(Range*, const String&, bool forward, bool caseFlag, bool wrapFlag);
321
322     void addToKillRing(Range*, bool prepend);
323
324     void handleCancelOperation();
325     void startCorrectionPanelTimer();
326     void handleRejectedCorrection();
327     bool isShowingCorrectionPanel();
328
329     void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle);
330     void pasteAsPlainText(const String&, bool smartReplace);
331
332     // This is only called on the mac where paste is implemented primarily at the WebKit level.
333     void pasteAsPlainTextBypassingDHTML();
334  
335     void clearMisspellingsAndBadGrammar(const VisibleSelection&);
336     void markMisspellingsAndBadGrammar(const VisibleSelection&);
337
338     Node* findEventTargetFrom(const VisibleSelection& selection) const;
339
340     String selectedText() const;
341     bool findString(const String&, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection);
342
343     const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
344     void setMark(const VisibleSelection&);
345
346     void computeAndSetTypingStyle(CSSStyleDeclaration* , EditAction = EditActionUnspecified);
347     void applyEditingStyleToBodyElement() const;
348     void applyEditingStyleToElement(Element*) const;
349
350     IntRect firstRectForRange(Range*) const;
351
352     void respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping);
353     bool shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity, bool stillSelecting) const;
354
355     RenderStyle* styleForSelectionStart(Node*& nodeToRemove) const;
356
357     unsigned countMatchesForText(const String&, bool caseFlag, unsigned limit, bool markMatches);
358     bool markedTextMatchesAreHighlighted() const;
359     void setMarkedTextMatchesAreHighlighted(bool);
360
361     PassRefPtr<CSSMutableStyleDeclaration> selectionComputedStyle(bool& shouldUseFixedFontDefaultSize) const;
362
363     void textFieldDidBeginEditing(Element*);
364     void textFieldDidEndEditing(Element*);
365     void textDidChangeInTextField(Element*);
366     bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*);
367     void textWillBeDeletedInTextField(Element* input);
368     void textDidChangeInTextArea(Element*);
369
370 #if PLATFORM(MAC)
371     NSDictionary* fontAttributesForSelectionStart() const;
372     NSWritingDirection baseWritingDirectionForSelectionStart() const;
373 #endif
374
375     bool selectionStartHasSpellingMarkerFor(int from, int length) const;
376     void removeSpellAndCorrectionMarkersFromWordsToBeEdited(bool doNotRemoveIfSelectionAtWordBoundary);
377
378 private:
379     Frame* m_frame;
380     OwnPtr<DeleteButtonController> m_deleteButtonController;
381     RefPtr<EditCommand> m_lastEditCommand;
382     RefPtr<Node> m_removedAnchor;
383     RefPtr<Text> m_compositionNode;
384     unsigned m_compositionStart;
385     unsigned m_compositionEnd;
386     Vector<CompositionUnderline> m_customCompositionUnderlines;
387     bool m_ignoreCompositionSelectionChange;
388     bool m_shouldStartNewKillRingSequence;
389     bool m_shouldStyleWithCSS;
390     OwnPtr<KillRing> m_killRing;
391     RefPtr<Range> m_rangeToBeReplacedByCorrection;
392     String m_stringToBeReplacedByCorrection;
393     String m_correctionReplacementString;
394     Timer<Editor> m_correctionPanelTimer;
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
408     void selectComposition();
409     void confirmComposition(const String&, bool preserveSelection);
410     void setIgnoreCompositionSelectionChange(bool ignore);
411
412     PassRefPtr<Range> firstVisibleRange(const String&, bool caseFlag);
413     PassRefPtr<Range> lastVisibleRange(const String&, bool caseFlag);
414
415     void changeSelectionAfterCommand(const VisibleSelection& newSelection, bool closeTyping, bool clearTypingStyle);
416     void correctionPanelTimerFired(Timer<Editor>*);
417     Node* findEventTargetFromSelection() const;
418     void stopCorrectionPanelTimer();
419 };
420
421 inline void Editor::setStartNewKillRingSequence(bool flag)
422 {
423     m_shouldStartNewKillRingSequence = flag;
424 }
425
426 inline const VisibleSelection& Editor::mark() const
427 {
428     return m_mark;
429 }
430
431 inline void Editor::setMark(const VisibleSelection& selection)
432 {
433     m_mark = selection;
434 }
435
436 inline bool Editor::markedTextMatchesAreHighlighted() const
437 {
438     return m_areMarkedTextMatchesHighlighted;
439 }
440
441
442 } // namespace WebCore
443
444 #endif // Editor_h