Home | History | Annotate | Download | only in editing
      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 {
     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     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 
    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     void unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction);
    173 
    174     void setShouldStyleWithCSS(bool flag) { m_shouldStyleWithCSS = flag; }
    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
    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)
    299     Text* compositionNode() const { return m_compositionNode.get(); }
    300     unsigned compositionStart() const { return m_compositionStart; }
    301     unsigned compositionEnd() const { return m_compositionEnd; }
    302     bool compositionUsesCustomUnderlines() const { return !m_customCompositionUnderlines.isEmpty(); }
    303     const Vector<CompositionUnderline>& customCompositionUnderlines() const { return m_customCompositionUnderlines; }
    304 
    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 
    315     KillRing* killRing() const { return m_killRing.get(); }
    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 
    438 inline void Editor::setStartNewKillRingSequence(bool flag)
    439 {
    440     m_shouldStartNewKillRingSequence = flag;
    441 }
    442 
    443 inline const VisibleSelection& Editor::mark() const
    444 {
    445     return m_mark;
    446 }
    447 
    448 inline void Editor::setMark(const VisibleSelection& selection)
    449 {
    450     m_mark = selection;
    451 }
    452 
    453 inline bool Editor::markedTextMatchesAreHighlighted() const
    454 {
    455     return m_areMarkedTextMatchesHighlighted;
    456 }
    457 
    458 
    459 } // namespace WebCore
    460 
    461 #endif // Editor_h
    462