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