• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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__)
44 class NSDictionary;
45 typedef int NSWritingDirection;
46 #endif
47 
48 namespace WebCore {
49 
50 class CSSMutableStyleDeclaration;
51 class CSSStyleDeclaration;
52 class Clipboard;
53 class SpellingCorrectionController;
54 class DeleteButtonController;
55 class EditCommand;
56 class EditorClient;
57 class EditorInternalCommand;
58 class Frame;
59 class HTMLElement;
60 class HitTestResult;
61 class KillRing;
62 class Pasteboard;
63 class SimpleFontData;
64 class SpellChecker;
65 class Text;
66 class TextCheckerClient;
67 class TextEvent;
68 
69 struct CompositionUnderline {
CompositionUnderlineCompositionUnderline70     CompositionUnderline()
71         : startOffset(0), endOffset(0), thick(false) { }
CompositionUnderlineCompositionUnderline72     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 
frame()90     Frame* frame() const { return m_frame; }
deleteButtonController()91     DeleteButtonController* deleteButtonController() const { return m_deleteButtonController.get(); }
lastEditCommand()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 
removedAnchor()161     Node* removedAnchor() const { return m_removedAnchor.get(); }
setRemovedAnchor(PassRefPtr<Node> n)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 
setShouldStyleWithCSS(bool flag)174     void setShouldStyleWithCSS(bool flag) { m_shouldStyleWithCSS = flag; }
shouldStyleWithCSS()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
hasComposition()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)
compositionNode()299     Text* compositionNode() const { return m_compositionNode.get(); }
compositionStart()300     unsigned compositionStart() const { return m_compositionStart; }
compositionEnd()301     unsigned compositionEnd() const { return m_compositionEnd; }
compositionUsesCustomUnderlines()302     bool compositionUsesCustomUnderlines() const { return !m_customCompositionUnderlines.isEmpty(); }
customCompositionUnderlines()303     const Vector<CompositionUnderline>& customCompositionUnderlines() const { return m_customCompositionUnderlines; }
304 
ignoreCompositionSelectionChange()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 
killRing()315     KillRing* killRing() const { return m_killRing.get(); }
spellChecker()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 
389 private:
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 
setStartNewKillRingSequence(bool flag)438 inline void Editor::setStartNewKillRingSequence(bool flag)
439 {
440     m_shouldStartNewKillRingSequence = flag;
441 }
442 
mark()443 inline const VisibleSelection& Editor::mark() const
444 {
445     return m_mark;
446 }
447 
setMark(const VisibleSelection & selection)448 inline void Editor::setMark(const VisibleSelection& selection)
449 {
450     m_mark = selection;
451 }
452 
markedTextMatchesAreHighlighted()453 inline bool Editor::markedTextMatchesAreHighlighted() const
454 {
455     return m_areMarkedTextMatchesHighlighted;
456 }
457 
458 
459 } // namespace WebCore
460 
461 #endif // Editor_h
462