1/*
2 * Copyright (C) 2010-2017 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 "AlternativeTextClient.h"
29#include "DocumentMarker.h"
30#include "Position.h"
31#include "Timer.h"
32#include <wtf/Noncopyable.h>
33#include <wtf/Variant.h>
34
35namespace WebCore {
36
37class CompositeEditCommand;
38class EditCommand;
39class EditCommandComposition;
40class EditorClient;
41class Event;
42class Frame;
43class Range;
44class TextCheckerClient;
45class VisibleSelection;
46
47struct DictationAlternative;
48struct TextCheckingResult;
49
50#if USE(AUTOCORRECTION_PANEL)
51// These backslashes are for making style checker happy.
52#define UNLESS_ENABLED(functionBody) \
53;\
54
55#else
56#define UNLESS_ENABLED(functionBody) functionBody
57#endif
58
59class AlternativeTextController {
60 WTF_MAKE_NONCOPYABLE(AlternativeTextController);
61 WTF_MAKE_FAST_ALLOCATED;
62public:
63 explicit AlternativeTextController(Frame& frame) UNLESS_ENABLED( : m_frame(frame) { })
64 ~AlternativeTextController() UNLESS_ENABLED({ })
65
66 void startAlternativeTextUITimer(AlternativeTextType) UNLESS_ENABLED({ })
67 void stopAlternativeTextUITimer() UNLESS_ENABLED({ })
68
69 void dismiss(ReasonForDismissingAlternativeText) UNLESS_ENABLED({ })
70 void show(Range& rangeToReplace, const String& replacement) UNLESS_ENABLED({ UNUSED_PARAM(rangeToReplace); UNUSED_PARAM(replacement); })
71
72 // Return true if correction was applied, false otherwise.
73 bool applyAutocorrectionBeforeTypingIfAppropriate() UNLESS_ENABLED({ return false; })
74
75 void respondToUnappliedSpellCorrection(const VisibleSelection&, const String& corrected, const String& correction) UNLESS_ENABLED({ UNUSED_PARAM(corrected); UNUSED_PARAM(correction); })
76 void respondToAppliedEditing(CompositeEditCommand*) UNLESS_ENABLED({ })
77 void respondToUnappliedEditing(EditCommandComposition*) UNLESS_ENABLED({ })
78 void respondToChangedSelection(const VisibleSelection& oldSelection) UNLESS_ENABLED({ UNUSED_PARAM(oldSelection); })
79
80 void stopPendingCorrection(const VisibleSelection& oldSelection) UNLESS_ENABLED({ UNUSED_PARAM(oldSelection); })
81 void applyPendingCorrection(const VisibleSelection& selectionAfterTyping) UNLESS_ENABLED({ UNUSED_PARAM(selectionAfterTyping); })
82
83 void handleAlternativeTextUIResult(const String& result) UNLESS_ENABLED({ UNUSED_PARAM(result); })
84 void handleCancelOperation() UNLESS_ENABLED({ })
85
86 bool hasPendingCorrection() const UNLESS_ENABLED({ return false; })
87 bool isSpellingMarkerAllowed(Range& misspellingRange) const UNLESS_ENABLED({ UNUSED_PARAM(misspellingRange); return true; })
88 bool isAutomaticSpellingCorrectionEnabled() UNLESS_ENABLED({ return false; })
89 bool shouldRemoveMarkersUponEditing();
90
91 void recordAutocorrectionResponse(AutocorrectionResponse, const String& replacedString, Range* replacementRange) UNLESS_ENABLED({ UNUSED_PARAM(replacedString); UNUSED_PARAM(replacementRange); })
92 void markReversed(Range& changedRange) UNLESS_ENABLED({ UNUSED_PARAM(changedRange); })
93 void markCorrection(Range& replacedRange, const String& replacedString) UNLESS_ENABLED({ UNUSED_PARAM(replacedRange); UNUSED_PARAM(replacedString); })
94
95 // This function returns false if the replacement should not be carried out.
96 bool processMarkersOnTextToBeReplacedByResult(const TextCheckingResult&, Range& rangeToBeReplaced, const String& stringToBeReplaced) UNLESS_ENABLED({ UNUSED_PARAM(rangeToBeReplaced); UNUSED_PARAM(stringToBeReplaced); return true; });
97 void deletedAutocorrectionAtPosition(const Position&, const String& originalString) UNLESS_ENABLED({ UNUSED_PARAM(originalString); })
98
99 bool insertDictatedText(const String&, const Vector<DictationAlternative>&, Event*);
100 void removeDictationAlternativesForMarker(const DocumentMarker&);
101 Vector<String> dictationAlternativesForMarker(const DocumentMarker&);
102 void applyDictationAlternative(const String& alternativeString);
103
104private:
105#if USE(AUTOCORRECTION_PANEL)
106 using AutocorrectionReplacement = String;
107 using AlternativeDictationContext = uint64_t;
108
109 struct AlternativeTextInfo {
110 RefPtr<Range> rangeWithAlternative;
111 bool isActive;
112 AlternativeTextType type;
113 String originalText;
114 Variant<AutocorrectionReplacement, AlternativeDictationContext> details;
115 };
116
117 String dismissSoon(ReasonForDismissingAlternativeText);
118 void applyAlternativeTextToRange(const Range&, const String& alternative, AlternativeTextType, OptionSet<DocumentMarker::MarkerType>);
119 void timerFired();
120 void recordSpellcheckerResponseForModifiedCorrection(Range& rangeOfCorrection, const String& corrected, const String& correction);
121 String markerDescriptionForAppliedAlternativeText(AlternativeTextType, DocumentMarker::MarkerType);
122
123 bool shouldStartTimerFor(const DocumentMarker&, int endOffset) const;
124 bool respondToMarkerAtEndOfWord(const DocumentMarker&, const Position& endOfWordPosition);
125
126 AlternativeTextClient* alternativeTextClient();
127 EditorClient* editorClient();
128
129 TextCheckerClient* textChecker();
130 FloatRect rootViewRectForRange(const Range*) const;
131 void markPrecedingWhitespaceForDeletedAutocorrectionAfterCommand(EditCommand*);
132
133 Timer m_timer;
134 RefPtr<Range> m_rangeWithAlternative;
135 bool m_isActive;
136 bool m_isDismissedByEditing;
137 AlternativeTextType m_type;
138 String m_originalText;
139 Variant<AutocorrectionReplacement, AlternativeDictationContext> m_details;
140
141 String m_originalStringForLastDeletedAutocorrection;
142 Position m_positionForLastDeletedAutocorrection;
143#endif
144
145 Frame& m_frame;
146};
147
148#undef UNLESS_ENABLED
149
150inline bool AlternativeTextController::shouldRemoveMarkersUponEditing()
151{
152#if USE(MARKER_REMOVAL_UPON_EDITING)
153 return true;
154#else
155 return false;
156#endif
157}
158
159} // namespace WebCore
160