1/*
2 * Copyright (C) 2006, 2007, 2008, 2013, 2014 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 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 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#pragma once
27
28#include "CompositionUnderline.h"
29#include "DictationAlternative.h"
30#include "DocumentMarker.h"
31#include "EditAction.h"
32#include "EditingBehavior.h"
33#include "EditingStyle.h"
34#include "EditorInsertAction.h"
35#include "FindOptions.h"
36#include "FrameSelection.h"
37#include "PasteboardWriterData.h"
38#include "TextChecking.h"
39#include "TextEventInputType.h"
40#include "TextIteratorBehavior.h"
41#include "VisibleSelection.h"
42#include "WritingDirection.h"
43#include <memory>
44
45#if PLATFORM(COCOA)
46OBJC_CLASS NSAttributedString;
47OBJC_CLASS NSDictionary;
48OBJC_CLASS NSMutableDictionary;
49#endif
50
51namespace PAL {
52class KillRing;
53}
54
55namespace WebCore {
56
57class AlternativeTextController;
58class ArchiveResource;
59class DataTransfer;
60class CompositeEditCommand;
61class CustomUndoStep;
62class DeleteButtonController;
63class EditCommand;
64class EditCommandComposition;
65class EditorClient;
66class EditorInternalCommand;
67class File;
68class Frame;
69class HTMLElement;
70class HitTestResult;
71class KeyboardEvent;
72class KillRing;
73class Pasteboard;
74class PasteboardWriterData;
75class SharedBuffer;
76class Font;
77class SpellCheckRequest;
78class SpellChecker;
79class StaticRange;
80class StyleProperties;
81class Text;
82class TextCheckerClient;
83class TextEvent;
84
85struct FontAttributes;
86struct PasteboardPlainText;
87struct PasteboardURL;
88struct TextCheckingResult;
89
90#if ENABLE(ATTACHMENT_ELEMENT)
91struct SerializedAttachmentData;
92#endif
93
94enum EditorCommandSource { CommandFromMenuOrKeyBinding, CommandFromDOM, CommandFromDOMWithUserInterface };
95enum EditorParagraphSeparator { EditorParagraphSeparatorIsDiv, EditorParagraphSeparatorIsP };
96
97enum class MailBlockquoteHandling {
98 RespectBlockquote,
99 IgnoreBlockquote,
100};
101
102#if ENABLE(ATTACHMENT_ELEMENT)
103class HTMLAttachmentElement;
104#endif
105
106enum class TemporarySelectionOption : uint8_t {
107 RevealSelection = 1 << 0,
108 DoNotSetFocus = 1 << 1,
109
110 // Don't propagate selection changes to the client layer.
111 IgnoreSelectionChanges = 1 << 2,
112
113 // Force the render tree to update selection state. Only respected on iOS.
114 EnableAppearanceUpdates = 1 << 3,
115};
116
117class TemporarySelectionChange {
118public:
119 TemporarySelectionChange(Frame&, Optional<VisibleSelection> = WTF::nullopt, OptionSet<TemporarySelectionOption> = { });
120 ~TemporarySelectionChange();
121
122private:
123 void setSelection(const VisibleSelection&);
124
125 Ref<Frame> m_frame;
126 OptionSet<TemporarySelectionOption> m_options;
127 bool m_wasIgnoringSelectionChanges;
128#if PLATFORM(IOS_FAMILY)
129 bool m_appearanceUpdatesWereEnabled;
130#endif
131 Optional<VisibleSelection> m_selectionToRestore;
132};
133
134class Editor {
135 WTF_MAKE_FAST_ALLOCATED;
136public:
137 explicit Editor(Frame&);
138 ~Editor();
139
140 enum class PasteOption : uint8_t {
141 AllowPlainText = 1 << 0,
142 IgnoreMailBlockquote = 1 << 1,
143 AsQuotation = 1 << 2,
144 };
145
146 WEBCORE_EXPORT EditorClient* client() const;
147 WEBCORE_EXPORT TextCheckerClient* textChecker() const;
148
149 CompositeEditCommand* lastEditCommand() { return m_lastEditCommand.get(); }
150
151 void handleKeyboardEvent(KeyboardEvent&);
152 void handleInputMethodKeydown(KeyboardEvent&);
153 bool handleTextEvent(TextEvent&);
154
155 WEBCORE_EXPORT bool canEdit() const;
156 WEBCORE_EXPORT bool canEditRichly() const;
157
158 bool canDHTMLCut();
159 bool canDHTMLCopy();
160 WEBCORE_EXPORT bool canDHTMLPaste();
161 bool tryDHTMLCopy();
162 bool tryDHTMLCut();
163
164 WEBCORE_EXPORT bool canCut() const;
165 WEBCORE_EXPORT bool canCopy() const;
166 WEBCORE_EXPORT bool canPaste() const;
167 WEBCORE_EXPORT bool canDelete() const;
168 WEBCORE_EXPORT bool canSmartCopyOrDelete();
169 bool shouldSmartDelete();
170
171 WEBCORE_EXPORT void cut();
172 WEBCORE_EXPORT void copy();
173 WEBCORE_EXPORT void paste();
174 void paste(Pasteboard&);
175 WEBCORE_EXPORT void pasteAsPlainText();
176 void pasteAsQuotation();
177 WEBCORE_EXPORT void performDelete();
178
179 WEBCORE_EXPORT void copyURL(const URL&, const String& title);
180 void copyURL(const URL&, const String& title, Pasteboard&);
181 PasteboardWriterData::URLData pasteboardWriterURL(const URL&, const String& title);
182#if !PLATFORM(IOS_FAMILY)
183 WEBCORE_EXPORT void copyImage(const HitTestResult&);
184#endif
185
186 String readPlainTextFromPasteboard(Pasteboard&);
187
188 WEBCORE_EXPORT void indent();
189 WEBCORE_EXPORT void outdent();
190 void transpose();
191
192 bool shouldInsertFragment(DocumentFragment&, Range*, EditorInsertAction);
193 bool shouldInsertText(const String&, Range*, EditorInsertAction) const;
194 WEBCORE_EXPORT bool shouldDeleteRange(Range*) const;
195 bool shouldApplyStyle(StyleProperties*, Range*);
196
197 void respondToChangedContents(const VisibleSelection& endingSelection);
198
199 bool selectionStartHasStyle(CSSPropertyID, const String& value) const;
200 WEBCORE_EXPORT TriState selectionHasStyle(CSSPropertyID, const String& value) const;
201 String selectionStartCSSPropertyValue(CSSPropertyID);
202
203 TriState selectionUnorderedListState() const;
204 TriState selectionOrderedListState() const;
205 WEBCORE_EXPORT RefPtr<Node> insertOrderedList();
206 WEBCORE_EXPORT RefPtr<Node> insertUnorderedList();
207 WEBCORE_EXPORT bool canIncreaseSelectionListLevel();
208 WEBCORE_EXPORT bool canDecreaseSelectionListLevel();
209 WEBCORE_EXPORT RefPtr<Node> increaseSelectionListLevel();
210 WEBCORE_EXPORT RefPtr<Node> increaseSelectionListLevelOrdered();
211 WEBCORE_EXPORT RefPtr<Node> increaseSelectionListLevelUnordered();
212 WEBCORE_EXPORT void decreaseSelectionListLevel();
213 WEBCORE_EXPORT void changeSelectionListType();
214
215 void removeFormattingAndStyle();
216
217 void clearLastEditCommand();
218#if PLATFORM(IOS_FAMILY)
219 WEBCORE_EXPORT void ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping();
220#endif
221
222 WEBCORE_EXPORT bool deleteWithDirection(SelectionDirection, TextGranularity, bool killRing, bool isTypingAction);
223 WEBCORE_EXPORT void deleteSelectionWithSmartDelete(bool smartDelete, EditAction = EditAction::Delete);
224 void clearText();
225#if PLATFORM(IOS_FAMILY)
226 WEBCORE_EXPORT void removeUnchangeableStyles();
227#endif
228
229 WEBCORE_EXPORT void applyStyle(StyleProperties*, EditAction = EditAction::Unspecified);
230 enum class ColorFilterMode { InvertColor, UseOriginalColor };
231 void applyStyle(RefPtr<EditingStyle>&&, EditAction, ColorFilterMode);
232 void applyParagraphStyle(StyleProperties*, EditAction = EditAction::Unspecified);
233 WEBCORE_EXPORT void applyStyleToSelection(StyleProperties*, EditAction);
234 WEBCORE_EXPORT void applyStyleToSelection(Ref<EditingStyle>&&, EditAction, ColorFilterMode);
235 void applyParagraphStyleToSelection(StyleProperties*, EditAction);
236
237 // Returns whether or not we should proceed with editing.
238 bool willApplyEditing(CompositeEditCommand&, Vector<RefPtr<StaticRange>>&&) const;
239 bool willUnapplyEditing(const EditCommandComposition&) const;
240 bool willReapplyEditing(const EditCommandComposition&) const;
241
242 void appliedEditing(CompositeEditCommand&);
243 void unappliedEditing(EditCommandComposition&);
244 void reappliedEditing(EditCommandComposition&);
245 void unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction);
246
247 // This is off by default, since most editors want this behavior (originally matched IE but not Firefox).
248 void setShouldStyleWithCSS(bool flag) { m_shouldStyleWithCSS = flag; }
249 bool shouldStyleWithCSS() const { return m_shouldStyleWithCSS; }
250
251 class Command {
252 public:
253 WEBCORE_EXPORT Command();
254 Command(const EditorInternalCommand*, EditorCommandSource, Frame&);
255
256 WEBCORE_EXPORT bool execute(const String& parameter = String(), Event* triggeringEvent = nullptr) const;
257 WEBCORE_EXPORT bool execute(Event* triggeringEvent) const;
258
259 WEBCORE_EXPORT bool isSupported() const;
260 WEBCORE_EXPORT bool isEnabled(Event* triggeringEvent = nullptr) const;
261
262 WEBCORE_EXPORT TriState state(Event* triggeringEvent = nullptr) const;
263 String value(Event* triggeringEvent = nullptr) const;
264
265 WEBCORE_EXPORT bool isTextInsertion() const;
266 WEBCORE_EXPORT bool allowExecutionWhenDisabled() const;
267
268 private:
269 const EditorInternalCommand* m_command { nullptr };
270 EditorCommandSource m_source;
271 RefPtr<Frame> m_frame;
272 };
273 WEBCORE_EXPORT Command command(const String& commandName); // Command source is CommandFromMenuOrKeyBinding.
274 Command command(const String& commandName, EditorCommandSource);
275 WEBCORE_EXPORT static bool commandIsSupportedFromMenuOrKeyBinding(const String& commandName); // Works without a frame.
276
277 WEBCORE_EXPORT bool insertText(const String&, Event* triggeringEvent, TextEventInputType = TextEventInputKeyboard);
278 bool insertTextForConfirmedComposition(const String& text);
279 WEBCORE_EXPORT bool insertDictatedText(const String&, const Vector<DictationAlternative>& dictationAlternatives, Event* triggeringEvent);
280 bool insertTextWithoutSendingTextEvent(const String&, bool selectInsertedText, TextEvent* triggeringEvent);
281 bool insertLineBreak();
282 bool insertParagraphSeparator();
283 WEBCORE_EXPORT bool insertParagraphSeparatorInQuotedContent();
284
285 WEBCORE_EXPORT bool isContinuousSpellCheckingEnabled() const;
286 WEBCORE_EXPORT void toggleContinuousSpellChecking();
287 bool isGrammarCheckingEnabled();
288 void toggleGrammarChecking();
289 void ignoreSpelling();
290 void learnSpelling();
291 int spellCheckerDocumentTag();
292 WEBCORE_EXPORT bool isSelectionUngrammatical();
293 String misspelledSelectionString() const;
294 String misspelledWordAtCaretOrRange(Node* clickedNode) const;
295 Vector<String> guessesForMisspelledWord(const String&) const;
296 Vector<String> guessesForMisspelledOrUngrammatical(bool& misspelled, bool& ungrammatical);
297 bool isSpellCheckingEnabledInFocusedNode() const;
298 bool isSpellCheckingEnabledFor(Node*) const;
299 WEBCORE_EXPORT void markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping, bool doReplacement);
300 void markMisspellings(const VisibleSelection&, RefPtr<Range>& firstMisspellingRange);
301 void markBadGrammar(const VisibleSelection&);
302 void markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection);
303 void markAndReplaceFor(const SpellCheckRequest&, const Vector<TextCheckingResult>&);
304 WEBCORE_EXPORT void replaceRangeForSpellChecking(Range&, const String&);
305
306 bool isOverwriteModeEnabled() const { return m_overwriteModeEnabled; }
307 WEBCORE_EXPORT void toggleOverwriteModeEnabled();
308
309 void markAllMisspellingsAndBadGrammarInRanges(OptionSet<TextCheckingType>, RefPtr<Range>&& spellingRange, RefPtr<Range>&& automaticReplacementRange, RefPtr<Range>&& grammarRange);
310#if PLATFORM(IOS_FAMILY)
311 NO_RETURN_DUE_TO_ASSERT
312#endif
313 void changeBackToReplacedString(const String& replacedString);
314
315#if !PLATFORM(IOS_FAMILY)
316 WEBCORE_EXPORT void advanceToNextMisspelling(bool startBeforeSelection = false);
317#endif
318 void showSpellingGuessPanel();
319 bool spellingPanelIsShowing();
320
321 bool shouldBeginEditing(Range*);
322 bool shouldEndEditing(Range*);
323
324 void clearUndoRedoOperations();
325 bool canUndo() const;
326 void undo();
327 bool canRedo() const;
328 void redo();
329
330 void registerCustomUndoStep(Ref<CustomUndoStep>&&);
331
332 void didBeginEditing();
333 void didEndEditing();
334 void willWriteSelectionToPasteboard(Range*);
335 void didWriteSelectionToPasteboard();
336
337 void showFontPanel();
338 void showStylesPanel();
339 void showColorPanel();
340 void toggleBold();
341 void toggleUnderline();
342 WEBCORE_EXPORT void setBaseWritingDirection(WritingDirection);
343
344 // smartInsertDeleteEnabled and selectTrailingWhitespaceEnabled are
345 // mutually exclusive, meaning that enabling one will disable the other.
346 bool smartInsertDeleteEnabled();
347 bool isSelectTrailingWhitespaceEnabled() const;
348
349 WEBCORE_EXPORT bool hasBidiSelection() const;
350
351 // international text input composition
352 bool hasComposition() const { return m_compositionNode; }
353 WEBCORE_EXPORT void setComposition(const String&, const Vector<CompositionUnderline>&, unsigned selectionStart, unsigned selectionEnd);
354 WEBCORE_EXPORT void confirmComposition();
355 WEBCORE_EXPORT void confirmComposition(const String&); // if no existing composition, replaces selection
356 WEBCORE_EXPORT void cancelComposition();
357 bool cancelCompositionIfSelectionIsInvalid();
358 WEBCORE_EXPORT RefPtr<Range> compositionRange() const;
359 WEBCORE_EXPORT bool getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const;
360
361 // getting international text input composition state (for use by InlineTextBox)
362 Text* compositionNode() const { return m_compositionNode.get(); }
363 unsigned compositionStart() const { return m_compositionStart; }
364 unsigned compositionEnd() const { return m_compositionEnd; }
365 bool compositionUsesCustomUnderlines() const { return !m_customCompositionUnderlines.isEmpty(); }
366 const Vector<CompositionUnderline>& customCompositionUnderlines() const { return m_customCompositionUnderlines; }
367
368 enum class RevealSelection { No, Yes };
369 WEBCORE_EXPORT void setIgnoreSelectionChanges(bool, RevealSelection shouldRevealExistingSelection = RevealSelection::Yes);
370 bool ignoreSelectionChanges() const { return m_ignoreSelectionChanges; }
371
372 WEBCORE_EXPORT RefPtr<Range> rangeForPoint(const IntPoint& windowPoint);
373
374 void clear();
375
376 VisibleSelection selectionForCommand(Event*);
377
378 PAL::KillRing& killRing() const { return *m_killRing; }
379 SpellChecker& spellChecker() const { return *m_spellChecker; }
380
381 EditingBehavior behavior() const;
382
383 RefPtr<Range> selectedRange();
384
385#if PLATFORM(IOS_FAMILY)
386 WEBCORE_EXPORT void confirmMarkedText();
387 WEBCORE_EXPORT void setTextAsChildOfElement(const String&, Element&);
388 WEBCORE_EXPORT void setTextAlignmentForChangedBaseWritingDirection(WritingDirection);
389 WEBCORE_EXPORT void insertDictationPhrases(Vector<Vector<String>>&& dictationPhrases, RetainPtr<id> metadata);
390 WEBCORE_EXPORT void setDictationPhrasesAsChildOfElement(const Vector<Vector<String>>& dictationPhrases, RetainPtr<id> metadata, Element&);
391#endif
392
393 enum class KillRingInsertionMode { PrependText, AppendText };
394 void addRangeToKillRing(const Range&, KillRingInsertionMode);
395 void addTextToKillRing(const String&, KillRingInsertionMode);
396 void setStartNewKillRingSequence(bool);
397
398 void startAlternativeTextUITimer();
399 // If user confirmed a correction in the correction panel, correction has non-zero length, otherwise it means that user has dismissed the panel.
400 WEBCORE_EXPORT void handleAlternativeTextUIResult(const String& correction);
401 void dismissCorrectionPanelAsIgnored();
402
403 WEBCORE_EXPORT void pasteAsFragment(Ref<DocumentFragment>&&, bool smartReplace, bool matchStyle, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
404 WEBCORE_EXPORT void pasteAsPlainText(const String&, bool smartReplace);
405
406 // This is only called on the mac where paste is implemented primarily at the WebKit level.
407 WEBCORE_EXPORT void pasteAsPlainTextBypassingDHTML();
408
409 void clearMisspellingsAndBadGrammar(const VisibleSelection&);
410 void markMisspellingsAndBadGrammar(const VisibleSelection&);
411
412 Element* findEventTargetFrom(const VisibleSelection& selection) const;
413
414 WEBCORE_EXPORT String selectedText() const;
415 String selectedTextForDataTransfer() const;
416 WEBCORE_EXPORT bool findString(const String&, FindOptions);
417
418 WEBCORE_EXPORT RefPtr<Range> rangeOfString(const String&, Range*, FindOptions);
419
420 const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
421 void setMark(const VisibleSelection&);
422
423 void computeAndSetTypingStyle(EditingStyle& , EditAction = EditAction::Unspecified);
424 WEBCORE_EXPORT void computeAndSetTypingStyle(StyleProperties& , EditAction = EditAction::Unspecified);
425 WEBCORE_EXPORT void applyEditingStyleToBodyElement() const;
426 void applyEditingStyleToElement(Element*) const;
427
428 WEBCORE_EXPORT IntRect firstRectForRange(Range*) const;
429
430 void selectionWillChange();
431 void respondToChangedSelection(const VisibleSelection& oldSelection, OptionSet<FrameSelection::SetSelectionOption>);
432 WEBCORE_EXPORT void updateEditorUINowIfScheduled();
433 bool shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity, bool stillSelecting) const;
434 WEBCORE_EXPORT unsigned countMatchesForText(const String&, Range*, FindOptions, unsigned limit, bool markMatches, Vector<RefPtr<Range>>*);
435 bool markedTextMatchesAreHighlighted() const;
436 WEBCORE_EXPORT void setMarkedTextMatchesAreHighlighted(bool);
437
438 void textFieldDidBeginEditing(Element*);
439 void textFieldDidEndEditing(Element*);
440 void textDidChangeInTextField(Element*);
441 bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*);
442 void textWillBeDeletedInTextField(Element* input);
443 void textDidChangeInTextArea(Element*);
444 WEBCORE_EXPORT WritingDirection baseWritingDirectionForSelectionStart() const;
445
446 enum class SelectReplacement : bool { No, Yes };
447 enum class SmartReplace : bool { No, Yes };
448 enum class MatchStyle : bool { No, Yes };
449 WEBCORE_EXPORT void replaceSelectionWithFragment(DocumentFragment&, SelectReplacement, SmartReplace, MatchStyle, EditAction = EditAction::Insert, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
450 WEBCORE_EXPORT void replaceSelectionWithText(const String&, SelectReplacement, SmartReplace, EditAction = EditAction::Insert);
451 WEBCORE_EXPORT bool selectionStartHasMarkerFor(DocumentMarker::MarkerType, int from, int length) const;
452 void updateMarkersForWordsAffectedByEditing(bool onlyHandleWordsContainingSelection);
453 void deletedAutocorrectionAtPosition(const Position&, const String& originalString);
454
455 WEBCORE_EXPORT void simplifyMarkup(Node* startNode, Node* endNode);
456
457 EditorParagraphSeparator defaultParagraphSeparator() const { return m_defaultParagraphSeparator; }
458 void setDefaultParagraphSeparator(EditorParagraphSeparator separator) { m_defaultParagraphSeparator = separator; }
459 Vector<String> dictationAlternativesForMarker(const DocumentMarker&);
460 void applyDictationAlternativelternative(const String& alternativeString);
461
462#if USE(APPKIT)
463 WEBCORE_EXPORT void uppercaseWord();
464 WEBCORE_EXPORT void lowercaseWord();
465 WEBCORE_EXPORT void capitalizeWord();
466#endif
467
468#if USE(AUTOMATIC_TEXT_REPLACEMENT)
469 WEBCORE_EXPORT void showSubstitutionsPanel();
470 WEBCORE_EXPORT bool substitutionsPanelIsShowing();
471 WEBCORE_EXPORT void toggleSmartInsertDelete();
472 WEBCORE_EXPORT bool isAutomaticQuoteSubstitutionEnabled();
473 WEBCORE_EXPORT void toggleAutomaticQuoteSubstitution();
474 WEBCORE_EXPORT bool isAutomaticLinkDetectionEnabled();
475 WEBCORE_EXPORT void toggleAutomaticLinkDetection();
476 WEBCORE_EXPORT bool isAutomaticDashSubstitutionEnabled();
477 WEBCORE_EXPORT void toggleAutomaticDashSubstitution();
478 WEBCORE_EXPORT bool isAutomaticTextReplacementEnabled();
479 WEBCORE_EXPORT void toggleAutomaticTextReplacement();
480 WEBCORE_EXPORT bool isAutomaticSpellingCorrectionEnabled();
481 WEBCORE_EXPORT void toggleAutomaticSpellingCorrection();
482#endif
483
484 RefPtr<DocumentFragment> webContentFromPasteboard(Pasteboard&, Range& context, bool allowPlainText, bool& chosePlainText);
485
486 WEBCORE_EXPORT const Font* fontForSelection(bool& hasMultipleFonts) const;
487 WEBCORE_EXPORT static const RenderStyle* styleForSelectionStart(Frame* , Node *&nodeToRemove);
488 WEBCORE_EXPORT FontAttributes fontAttributesAtSelectionStart() const;
489
490#if PLATFORM(COCOA)
491 WEBCORE_EXPORT String stringSelectionForPasteboard();
492 String stringSelectionForPasteboardWithImageAltText();
493 void takeFindStringFromSelection();
494#if !PLATFORM(IOS_FAMILY)
495 WEBCORE_EXPORT void readSelectionFromPasteboard(const String& pasteboardName);
496 WEBCORE_EXPORT void replaceNodeFromPasteboard(Node*, const String& pasteboardName);
497 WEBCORE_EXPORT RefPtr<SharedBuffer> dataSelectionForPasteboard(const String& pasteboardName);
498#endif // !PLATFORM(IOS_FAMILY)
499 WEBCORE_EXPORT void replaceSelectionWithAttributedString(NSAttributedString *, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
500#endif
501
502 bool canCopyExcludingStandaloneImages() const;
503
504#if !PLATFORM(WIN)
505 WEBCORE_EXPORT void writeSelectionToPasteboard(Pasteboard&);
506 WEBCORE_EXPORT void writeImageToPasteboard(Pasteboard&, Element& imageElement, const URL&, const String& title);
507 void writeSelection(PasteboardWriterData&);
508#endif
509
510#if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
511 void scanSelectionForTelephoneNumbers();
512 const Vector<RefPtr<Range>>& detectedTelephoneNumberRanges() const { return m_detectedTelephoneNumberRanges; }
513#endif
514
515 WEBCORE_EXPORT String stringForCandidateRequest() const;
516 WEBCORE_EXPORT void handleAcceptedCandidate(TextCheckingResult);
517 WEBCORE_EXPORT RefPtr<Range> contextRangeForCandidateRequest() const;
518 RefPtr<Range> rangeForTextCheckingResult(const TextCheckingResult&) const;
519 bool isHandlingAcceptedCandidate() const { return m_isHandlingAcceptedCandidate; }
520
521 void setIsGettingDictionaryPopupInfo(bool b) { m_isGettingDictionaryPopupInfo = b; }
522 bool isGettingDictionaryPopupInfo() const { return m_isGettingDictionaryPopupInfo; }
523
524#if ENABLE(ATTACHMENT_ELEMENT)
525 WEBCORE_EXPORT void insertAttachment(const String& identifier, Optional<uint64_t>&& fileSize, const String& fileName, const String& contentType);
526 void registerAttachmentIdentifier(const String&, const String& contentType, const String& preferredFileName, Ref<SharedBuffer>&& fileData);
527 void registerAttachments(Vector<SerializedAttachmentData>&&);
528 void registerAttachmentIdentifier(const String&, const String& contentType, const String& filePath);
529 void registerAttachmentIdentifier(const String&);
530 void cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier);
531 void didInsertAttachmentElement(HTMLAttachmentElement&);
532 void didRemoveAttachmentElement(HTMLAttachmentElement&);
533
534#if PLATFORM(COCOA)
535 void getPasteboardTypesAndDataForAttachment(Element&, Vector<String>& outTypes, Vector<RefPtr<SharedBuffer>>& outData);
536#endif
537#endif
538
539 WEBCORE_EXPORT RefPtr<HTMLImageElement> insertEditableImage();
540
541private:
542 Document& document() const;
543
544 bool canDeleteRange(Range*) const;
545 bool canSmartReplaceWithPasteboard(Pasteboard&);
546 void pasteAsPlainTextWithPasteboard(Pasteboard&);
547 void pasteWithPasteboard(Pasteboard*, OptionSet<PasteOption>);
548 String plainTextFromPasteboard(const PasteboardPlainText&);
549
550 void quoteFragmentForPasting(DocumentFragment&);
551
552 void revealSelectionAfterEditingOperation(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);
553 void markMisspellingsOrBadGrammar(const VisibleSelection&, bool checkSpelling, RefPtr<Range>& firstMisspellingRange);
554 OptionSet<TextCheckingType> resolveTextCheckingTypeMask(const Node& rootEditableElement, OptionSet<TextCheckingType>);
555
556 WEBCORE_EXPORT String selectedText(TextIteratorBehavior) const;
557
558 void selectComposition();
559 enum SetCompositionMode { ConfirmComposition, CancelComposition };
560 void setComposition(const String&, SetCompositionMode);
561
562 void changeSelectionAfterCommand(const VisibleSelection& newSelection, OptionSet<FrameSelection::SetSelectionOption>);
563
564 enum EditorActionSpecifier { CutAction, CopyAction };
565 void performCutOrCopy(EditorActionSpecifier);
566
567 void editorUIUpdateTimerFired();
568
569 Element* findEventTargetFromSelection() const;
570
571 bool unifiedTextCheckerEnabled() const;
572
573 RefPtr<Range> adjustedSelectionRange();
574
575#if PLATFORM(COCOA)
576 RefPtr<SharedBuffer> selectionInWebArchiveFormat();
577 String selectionInHTMLFormat();
578 RefPtr<SharedBuffer> imageInWebArchiveFormat(Element&);
579 static String userVisibleString(const URL&);
580 static RefPtr<SharedBuffer> dataInRTFDFormat(NSAttributedString *);
581 static RefPtr<SharedBuffer> dataInRTFFormat(NSAttributedString *);
582#endif
583 void platformFontAttributesAtSelectionStart(FontAttributes&, const RenderStyle&) const;
584
585 void scheduleEditorUIUpdate();
586
587#if ENABLE(ATTACHMENT_ELEMENT)
588 void notifyClientOfAttachmentUpdates();
589#endif
590
591 void postTextStateChangeNotificationForCut(const String&, const VisibleSelection&);
592
593 Frame& m_frame;
594 RefPtr<CompositeEditCommand> m_lastEditCommand;
595 RefPtr<Text> m_compositionNode;
596 unsigned m_compositionStart;
597 unsigned m_compositionEnd;
598 Vector<CompositionUnderline> m_customCompositionUnderlines;
599 bool m_ignoreSelectionChanges { false };
600 bool m_shouldStartNewKillRingSequence { false };
601 bool m_shouldStyleWithCSS { false };
602 const std::unique_ptr<PAL::KillRing> m_killRing;
603 const std::unique_ptr<SpellChecker> m_spellChecker;
604 const std::unique_ptr<AlternativeTextController> m_alternativeTextController;
605 EditorParagraphSeparator m_defaultParagraphSeparator { EditorParagraphSeparatorIsDiv };
606 bool m_overwriteModeEnabled { false };
607
608#if ENABLE(ATTACHMENT_ELEMENT)
609 HashSet<String> m_insertedAttachmentIdentifiers;
610 HashSet<String> m_removedAttachmentIdentifiers;
611#endif
612
613 VisibleSelection m_mark;
614 bool m_areMarkedTextMatchesHighlighted { false };
615
616 VisibleSelection m_oldSelectionForEditorUIUpdate;
617 Timer m_editorUIUpdateTimer;
618 bool m_editorUIUpdateTimerShouldCheckSpellingAndGrammar { false };
619 bool m_editorUIUpdateTimerWasTriggeredByDictation { false };
620 bool m_isHandlingAcceptedCandidate { false };
621
622#if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS_FAMILY)
623 bool shouldDetectTelephoneNumbers();
624 void scanRangeForTelephoneNumbers(Range&, const StringView&, Vector<RefPtr<Range>>& markedRanges);
625
626 Timer m_telephoneNumberDetectionUpdateTimer;
627 Vector<RefPtr<Range>> m_detectedTelephoneNumberRanges;
628#endif
629
630 bool m_isGettingDictionaryPopupInfo { false };
631};
632
633inline void Editor::setStartNewKillRingSequence(bool flag)
634{
635 m_shouldStartNewKillRingSequence = flag;
636}
637
638inline const VisibleSelection& Editor::mark() const
639{
640 return m_mark;
641}
642
643inline void Editor::setMark(const VisibleSelection& selection)
644{
645 m_mark = selection;
646}
647
648inline bool Editor::markedTextMatchesAreHighlighted() const
649{
650 return m_areMarkedTextMatchesHighlighted;
651}
652
653} // namespace WebCore
654