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 "EditAction.h"
     32 #include "EditorDeleteAction.h"
     33 #include "EditorInsertAction.h"
     34 #include "SelectionController.h"
     35 
     36 namespace WebCore {
     37 
     38 class CSSStyleDeclaration;
     39 class Clipboard;
     40 class DeleteButtonController;
     41 class EditCommand;
     42 class EditorClient;
     43 class EditorInternalCommand;
     44 class HTMLElement;
     45 class HitTestResult;
     46 class Pasteboard;
     47 class SimpleFontData;
     48 class Text;
     49 
     50 struct CompositionUnderline {
     51     CompositionUnderline()
     52         : startOffset(0), endOffset(0), thick(false) { }
     53     CompositionUnderline(unsigned s, unsigned e, const Color& c, bool t)
     54         : startOffset(s), endOffset(e), color(c), thick(t) { }
     55     unsigned startOffset;
     56     unsigned endOffset;
     57     Color color;
     58     bool thick;
     59 };
     60 
     61 enum TriState { FalseTriState, TrueTriState, MixedTriState };
     62 enum EditorCommandSource { CommandFromMenuOrKeyBinding, CommandFromDOM, CommandFromDOMWithUserInterface };
     63 enum WritingDirection { NaturalWritingDirection, LeftToRightWritingDirection, RightToLeftWritingDirection };
     64 
     65 class Editor {
     66 public:
     67     Editor(Frame*);
     68     ~Editor();
     69 
     70     EditorClient* client() const;
     71     Frame* frame() const { return m_frame; }
     72     DeleteButtonController* deleteButtonController() const { return m_deleteButtonController.get(); }
     73     EditCommand* lastEditCommand() { return m_lastEditCommand.get(); }
     74 
     75     void handleKeyboardEvent(KeyboardEvent*);
     76     void handleInputMethodKeydown(KeyboardEvent*);
     77 
     78     bool canEdit() const;
     79     bool canEditRichly() const;
     80 
     81     bool canDHTMLCut();
     82     bool canDHTMLCopy();
     83     bool canDHTMLPaste();
     84     bool tryDHTMLCopy();
     85     bool tryDHTMLCut();
     86     bool tryDHTMLPaste();
     87 
     88     bool canCut() const;
     89     bool canCopy() const;
     90     bool canPaste() const;
     91     bool canDelete() const;
     92     bool canSmartCopyOrDelete();
     93 
     94     void cut();
     95     void copy();
     96     void paste();
     97     void pasteAsPlainText();
     98     void performDelete();
     99 
    100     void copyURL(const KURL&, const String&);
    101     void copyImage(const HitTestResult&);
    102 
    103     void indent();
    104     void outdent();
    105     void transpose();
    106 
    107     bool shouldInsertFragment(PassRefPtr<DocumentFragment>, PassRefPtr<Range>, EditorInsertAction);
    108     bool shouldInsertText(const String&, Range*, EditorInsertAction) const;
    109     bool shouldShowDeleteInterface(HTMLElement*) const;
    110     bool shouldDeleteRange(Range*) const;
    111     bool shouldApplyStyle(CSSStyleDeclaration*, Range*);
    112 
    113     void respondToChangedSelection(const VisibleSelection& oldSelection);
    114     void respondToChangedContents(const VisibleSelection& endingSelection);
    115 
    116     TriState selectionHasStyle(CSSStyleDeclaration*) const;
    117     const SimpleFontData* fontForSelection(bool&) const;
    118     WritingDirection textDirectionForSelection(bool&) const;
    119 
    120     TriState selectionUnorderedListState() const;
    121     TriState selectionOrderedListState() const;
    122     PassRefPtr<Node> insertOrderedList();
    123     PassRefPtr<Node> insertUnorderedList();
    124     bool canIncreaseSelectionListLevel();
    125     bool canDecreaseSelectionListLevel();
    126     PassRefPtr<Node> increaseSelectionListLevel();
    127     PassRefPtr<Node> increaseSelectionListLevelOrdered();
    128     PassRefPtr<Node> increaseSelectionListLevelUnordered();
    129     void decreaseSelectionListLevel();
    130 
    131     void removeFormattingAndStyle();
    132 
    133     void clearLastEditCommand();
    134 
    135     bool deleteWithDirection(SelectionController::EDirection, TextGranularity, bool killRing, bool isTypingAction);
    136     void deleteSelectionWithSmartDelete(bool smartDelete);
    137     bool dispatchCPPEvent(const AtomicString&, ClipboardAccessPolicy);
    138 
    139     Node* removedAnchor() const { return m_removedAnchor.get(); }
    140     void setRemovedAnchor(PassRefPtr<Node> n) { m_removedAnchor = n; }
    141 
    142     void applyStyle(CSSStyleDeclaration*, EditAction = EditActionUnspecified);
    143     void applyParagraphStyle(CSSStyleDeclaration*, EditAction = EditActionUnspecified);
    144     void applyStyleToSelection(CSSStyleDeclaration*, EditAction);
    145     void applyParagraphStyleToSelection(CSSStyleDeclaration*, EditAction);
    146 
    147     void appliedEditing(PassRefPtr<EditCommand>);
    148     void unappliedEditing(PassRefPtr<EditCommand>);
    149     void reappliedEditing(PassRefPtr<EditCommand>);
    150 
    151     bool selectionStartHasStyle(CSSStyleDeclaration*) const;
    152 
    153     bool clientIsEditable() const;
    154 
    155     void setShouldStyleWithCSS(bool flag) { m_shouldStyleWithCSS = flag; }
    156     bool shouldStyleWithCSS() const { return m_shouldStyleWithCSS; }
    157 
    158     class Command {
    159     public:
    160         Command();
    161         Command(PassRefPtr<Frame>, const EditorInternalCommand*, EditorCommandSource);
    162 
    163         bool execute(const String& parameter = String(), Event* triggeringEvent = 0) const;
    164         bool execute(Event* triggeringEvent) const;
    165 
    166         bool isSupported() const;
    167         bool isEnabled(Event* triggeringEvent = 0) const;
    168 
    169         TriState state(Event* triggeringEvent = 0) const;
    170         String value(Event* triggeringEvent = 0) const;
    171 
    172         bool isTextInsertion() const;
    173 
    174     private:
    175         RefPtr<Frame> m_frame;
    176         const EditorInternalCommand* m_command;
    177         EditorCommandSource m_source;
    178     };
    179     Command command(const String& commandName); // Default is CommandFromMenuOrKeyBinding.
    180     Command command(const String& commandName, EditorCommandSource);
    181 
    182     bool insertText(const String&, Event* triggeringEvent);
    183     bool insertTextWithoutSendingTextEvent(const String&, bool selectInsertedText, Event* triggeringEvent);
    184     bool insertLineBreak();
    185     bool insertParagraphSeparator();
    186 
    187     bool isContinuousSpellCheckingEnabled();
    188     void toggleContinuousSpellChecking();
    189     bool isGrammarCheckingEnabled();
    190     void toggleGrammarChecking();
    191     void ignoreSpelling();
    192     void learnSpelling();
    193     int spellCheckerDocumentTag();
    194     bool isSelectionUngrammatical();
    195     bool isSelectionMisspelled();
    196     Vector<String> guessesForMisspelledSelection();
    197     Vector<String> guessesForUngrammaticalSelection();
    198     Vector<String> guessesForMisspelledOrUngrammaticalSelection(bool& misspelled, bool& ungrammatical);
    199     bool spellCheckingEnabledInFocusedNode() const;
    200     void markMisspellingsAfterTypingToPosition(const VisiblePosition&);
    201     void markMisspellings(const VisibleSelection&, RefPtr<Range>& firstMisspellingRange);
    202     void markBadGrammar(const VisibleSelection&);
    203     void markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection);
    204 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
    205     void uppercaseWord();
    206     void lowercaseWord();
    207     void capitalizeWord();
    208     void showSubstitutionsPanel();
    209     bool substitutionsPanelIsShowing();
    210     void toggleSmartInsertDelete();
    211     bool isAutomaticQuoteSubstitutionEnabled();
    212     void toggleAutomaticQuoteSubstitution();
    213     bool isAutomaticLinkDetectionEnabled();
    214     void toggleAutomaticLinkDetection();
    215     bool isAutomaticDashSubstitutionEnabled();
    216     void toggleAutomaticDashSubstitution();
    217     bool isAutomaticTextReplacementEnabled();
    218     void toggleAutomaticTextReplacement();
    219     bool isAutomaticSpellingCorrectionEnabled();
    220     void toggleAutomaticSpellingCorrection();
    221     void markAllMisspellingsAndBadGrammarInRanges(bool markSpelling, Range* spellingRange, bool markGrammar, Range* grammarRange, bool performTextCheckingReplacements);
    222     void changeBackToReplacedString(const String& replacedString);
    223 #endif
    224     void advanceToNextMisspelling(bool startBeforeSelection = false);
    225     void showSpellingGuessPanel();
    226     bool spellingPanelIsShowing();
    227 
    228     bool shouldBeginEditing(Range*);
    229     bool shouldEndEditing(Range*);
    230 
    231     void clearUndoRedoOperations();
    232     bool canUndo();
    233     void undo();
    234     bool canRedo();
    235     void redo();
    236 
    237     void didBeginEditing();
    238     void didEndEditing();
    239     void didWriteSelectionToPasteboard();
    240 
    241     void showFontPanel();
    242     void showStylesPanel();
    243     void showColorPanel();
    244     void toggleBold();
    245     void toggleUnderline();
    246     void setBaseWritingDirection(WritingDirection);
    247 
    248     // smartInsertDeleteEnabled and selectTrailingWhitespaceEnabled are
    249     // mutually exclusive, meaning that enabling one will disable the other.
    250     bool smartInsertDeleteEnabled();
    251     bool isSelectTrailingWhitespaceEnabled();
    252 
    253     bool hasBidiSelection() const;
    254 
    255     // international text input composition
    256     bool hasComposition() const { return m_compositionNode; }
    257     void setComposition(const String&, const Vector<CompositionUnderline>&, unsigned selectionStart, unsigned selectionEnd);
    258     void confirmComposition();
    259     void confirmComposition(const String&); // if no existing composition, replaces selection
    260     void confirmCompositionWithoutDisturbingSelection();
    261     PassRefPtr<Range> compositionRange() const;
    262     bool getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const;
    263 
    264     // getting international text input composition state (for use by InlineTextBox)
    265     Text* compositionNode() const { return m_compositionNode.get(); }
    266     unsigned compositionStart() const { return m_compositionStart; }
    267     unsigned compositionEnd() const { return m_compositionEnd; }
    268     bool compositionUsesCustomUnderlines() const { return !m_customCompositionUnderlines.isEmpty(); }
    269     const Vector<CompositionUnderline>& customCompositionUnderlines() const { return m_customCompositionUnderlines; }
    270 
    271     bool ignoreCompositionSelectionChange() const { return m_ignoreCompositionSelectionChange; }
    272 
    273     void setStartNewKillRingSequence(bool);
    274 
    275     PassRefPtr<Range> rangeForPoint(const IntPoint& windowPoint);
    276 
    277     void clear();
    278 
    279     VisibleSelection selectionForCommand(Event*);
    280 
    281     void appendToKillRing(const String&);
    282     void prependToKillRing(const String&);
    283     String yankFromKillRing();
    284     void startNewKillRingSequence();
    285     void setKillRingToYankedState();
    286 
    287     PassRefPtr<Range> selectedRange();
    288 
    289     // We should make these functions private when their callers in Frame are moved over here to Editor
    290     bool insideVisibleArea(const IntPoint&) const;
    291     bool insideVisibleArea(Range*) const;
    292     PassRefPtr<Range> nextVisibleRange(Range*, const String&, bool forward, bool caseFlag, bool wrapFlag);
    293 
    294     void addToKillRing(Range*, bool prepend);
    295 private:
    296     Frame* m_frame;
    297     OwnPtr<DeleteButtonController> m_deleteButtonController;
    298     RefPtr<EditCommand> m_lastEditCommand;
    299     RefPtr<Node> m_removedAnchor;
    300 
    301     RefPtr<Text> m_compositionNode;
    302     unsigned m_compositionStart;
    303     unsigned m_compositionEnd;
    304     Vector<CompositionUnderline> m_customCompositionUnderlines;
    305     bool m_ignoreCompositionSelectionChange;
    306     bool m_shouldStartNewKillRingSequence;
    307     bool m_shouldStyleWithCSS;
    308 
    309     bool canDeleteRange(Range*) const;
    310     bool canSmartReplaceWithPasteboard(Pasteboard*);
    311     PassRefPtr<Clipboard> newGeneralClipboard(ClipboardAccessPolicy);
    312     void pasteAsPlainTextWithPasteboard(Pasteboard*);
    313     void pasteWithPasteboard(Pasteboard*, bool allowPlainText);
    314     void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle);
    315     void replaceSelectionWithText(const String&, bool selectReplacement, bool smartReplace);
    316     void writeSelectionToPasteboard(Pasteboard*);
    317     void revealSelectionAfterEditingOperation();
    318 
    319     void selectComposition();
    320     void confirmComposition(const String&, bool preserveSelection);
    321     void setIgnoreCompositionSelectionChange(bool ignore);
    322 
    323     PassRefPtr<Range> firstVisibleRange(const String&, bool caseFlag);
    324     PassRefPtr<Range> lastVisibleRange(const String&, bool caseFlag);
    325 
    326     void changeSelectionAfterCommand(const VisibleSelection& newSelection, bool closeTyping, bool clearTypingStyle, EditCommand*);
    327 };
    328 
    329 inline void Editor::setStartNewKillRingSequence(bool flag)
    330 {
    331     m_shouldStartNewKillRingSequence = flag;
    332 }
    333 
    334 } // namespace WebCore
    335 
    336 #endif // Editor_h
    337