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 {
CompositionUnderlineCompositionUnderline51 CompositionUnderline()
52 : startOffset(0), endOffset(0), thick(false) { }
CompositionUnderlineCompositionUnderline53 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;
frame()71 Frame* frame() const { return m_frame; }
deleteButtonController()72 DeleteButtonController* deleteButtonController() const { return m_deleteButtonController.get(); }
lastEditCommand()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
removedAnchor()139 Node* removedAnchor() const { return m_removedAnchor.get(); }
setRemovedAnchor(PassRefPtr<Node> n)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
setShouldStyleWithCSS(bool flag)155 void setShouldStyleWithCSS(bool flag) { m_shouldStyleWithCSS = flag; }
shouldStyleWithCSS()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
hasComposition()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)
compositionNode()265 Text* compositionNode() const { return m_compositionNode.get(); }
compositionStart()266 unsigned compositionStart() const { return m_compositionStart; }
compositionEnd()267 unsigned compositionEnd() const { return m_compositionEnd; }
compositionUsesCustomUnderlines()268 bool compositionUsesCustomUnderlines() const { return !m_customCompositionUnderlines.isEmpty(); }
customCompositionUnderlines()269 const Vector<CompositionUnderline>& customCompositionUnderlines() const { return m_customCompositionUnderlines; }
270
ignoreCompositionSelectionChange()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
setStartNewKillRingSequence(bool flag)329 inline void Editor::setStartNewKillRingSequence(bool flag)
330 {
331 m_shouldStartNewKillRingSequence = flag;
332 }
333
334 } // namespace WebCore
335
336 #endif // Editor_h
337