|
Lines 45-53
a/Source/WebCore/editing/SpellChecker.cpp_sec1
|
| 45 |
|
45 |
|
| 46 |
namespace WebCore { |
46 |
namespace WebCore { |
| 47 |
|
47 |
|
|
|
48 |
class SpellChecker::SpellCheckRequest { |
| 49 |
public: |
| 50 |
SpellCheckRequest(int sequence, PassRefPtr<Range> range, const String& text, TextCheckingTypeMask mask) |
| 51 |
: m_sequence(sequence) |
| 52 |
, m_range(range) |
| 53 |
, m_text(text) |
| 54 |
, m_mask(mask) |
| 55 |
{ |
| 56 |
} |
| 57 |
|
| 58 |
int sequence() const { return m_sequence; } |
| 59 |
PassRefPtr<Range> range() const { return m_range; } |
| 60 |
const String& text() const { return m_text; } |
| 61 |
TextCheckingTypeMask mask() const { return m_mask; } |
| 62 |
|
| 63 |
private: |
| 64 |
int m_sequence; |
| 65 |
RefPtr<Range> m_range; |
| 66 |
String m_text; |
| 67 |
TextCheckingTypeMask m_mask; |
| 68 |
}; |
| 69 |
|
| 48 |
SpellChecker::SpellChecker(Frame* frame) |
70 |
SpellChecker::SpellChecker(Frame* frame) |
| 49 |
: m_frame(frame) |
71 |
: m_frame(frame) |
| 50 |
, m_requestSequence(0) |
72 |
, m_maxRequestedSequence(0) |
|
|
73 |
, m_timer(this, &SpellChecker::timerFired) |
| 51 |
{ |
74 |
{ |
| 52 |
} |
75 |
} |
| 53 |
|
76 |
|
|
Lines 63-87
TextCheckerClient* SpellChecker::client() const
a/Source/WebCore/editing/SpellChecker.cpp_sec2
|
| 63 |
return page->editorClient()->textChecker(); |
86 |
return page->editorClient()->textChecker(); |
| 64 |
} |
87 |
} |
| 65 |
|
88 |
|
| 66 |
bool SpellChecker::initRequest(PassRefPtr<Range> range) |
89 |
PassOwnPtr<SpellChecker::SpellCheckRequest> SpellChecker::initRequest(TextCheckingTypeMask mask, PassRefPtr<Range> range) |
| 67 |
{ |
90 |
{ |
| 68 |
ASSERT(canCheckAsynchronously(range.get())); |
91 |
ASSERT(canCheckAsynchronously(range.get())); |
| 69 |
|
92 |
|
| 70 |
String text = range->text(); |
93 |
String text = range->text(); |
| 71 |
if (!text.length()) |
94 |
if (!text.length()) |
| 72 |
return false; |
95 |
return PassOwnPtr<SpellCheckRequest>(); |
| 73 |
|
96 |
|
| 74 |
m_requestRange = range; |
97 |
return adoptPtr(new SpellCheckRequest(++m_maxRequestedSequence, range, text, mask)); |
| 75 |
m_requestText = text; |
98 |
} |
| 76 |
m_requestSequence++; |
99 |
|
|
|
100 |
void SpellChecker::timerFired(Timer<SpellChecker>*) |
| 101 |
{ |
| 102 |
if (!m_queuedRequest.get()) |
| 103 |
return; |
| 77 |
|
104 |
|
| 78 |
return true; |
105 |
m_processingRequest = m_queuedRequest.release(); |
|
|
106 |
client()->requestCheckingOfString(this, m_processingRequest->sequence(), m_processingRequest->mask(), m_processingRequest->text()); |
| 79 |
} |
107 |
} |
| 80 |
|
108 |
|
| 81 |
void SpellChecker::clearRequest() |
109 |
void SpellChecker::processQueuedRequest() |
| 82 |
{ |
110 |
{ |
| 83 |
m_requestRange.clear(); |
111 |
m_processingRequest.clear(); |
| 84 |
m_requestText = String(); |
112 |
if (!m_queuedRequest.get()) |
|
|
113 |
return; |
| 114 |
|
| 115 |
m_timer.startOneShot(0); |
| 85 |
} |
116 |
} |
| 86 |
|
117 |
|
| 87 |
bool SpellChecker::isAsynchronousEnabled() const |
118 |
bool SpellChecker::isAsynchronousEnabled() const |
|
Lines 91-107
bool SpellChecker::isAsynchronousEnabled() const
a/Source/WebCore/editing/SpellChecker.cpp_sec3
|
| 91 |
|
122 |
|
| 92 |
bool SpellChecker::canCheckAsynchronously(Range* range) const |
123 |
bool SpellChecker::canCheckAsynchronously(Range* range) const |
| 93 |
{ |
124 |
{ |
| 94 |
return client() && isCheckable(range) && isAsynchronousEnabled() && !isBusy(); |
125 |
return client() && isCheckable(range) && isAsynchronousEnabled(); |
| 95 |
} |
|
|
| 96 |
|
| 97 |
bool SpellChecker::isBusy() const |
| 98 |
{ |
| 99 |
return m_requestRange.get(); |
| 100 |
} |
126 |
} |
| 101 |
|
127 |
|
| 102 |
bool SpellChecker::isValid(int sequence) const |
128 |
bool SpellChecker::isValid(int sequence) const |
| 103 |
{ |
129 |
{ |
| 104 |
return m_requestRange.get() && m_requestText.length() && m_requestSequence == sequence; |
130 |
return m_processingRequest.get() && m_processingRequest->text().length() && m_processingRequest->sequence() == sequence; |
| 105 |
} |
131 |
} |
| 106 |
|
132 |
|
| 107 |
bool SpellChecker::isCheckable(Range* range) const |
133 |
bool SpellChecker::isCheckable(Range* range) const |
|
Lines 121-129
void SpellChecker::doRequestCheckingFor(TextCheckingTypeMask mask, PassRefPtr<Ra
a/Source/WebCore/editing/SpellChecker.cpp_sec4
|
| 121 |
{ |
147 |
{ |
| 122 |
ASSERT(canCheckAsynchronously(range.get())); |
148 |
ASSERT(canCheckAsynchronously(range.get())); |
| 123 |
|
149 |
|
| 124 |
if (!initRequest(range)) |
150 |
OwnPtr<SpellCheckRequest> request(initRequest(mask, range)); |
|
|
151 |
if (!request.get()) |
| 125 |
return; |
152 |
return; |
| 126 |
client()->requestCheckingOfString(this, m_requestSequence, mask, m_requestText); |
153 |
|
|
|
154 |
if (m_processingRequest.get()) |
| 155 |
m_queuedRequest = request.release(); |
| 156 |
else { |
| 157 |
client()->requestCheckingOfString(this, request->sequence(), request->mask(), request->text()); |
| 158 |
m_processingRequest = request.release(); |
| 159 |
} |
| 127 |
} |
160 |
} |
| 128 |
|
161 |
|
| 129 |
static bool forwardIterator(PositionIterator& iterator, int distance) |
162 |
static bool forwardIterator(PositionIterator& iterator, int distance) |
|
Lines 162-174
void SpellChecker::didCheck(int sequence, const Vector<TextCheckingResult>& resu
a/Source/WebCore/editing/SpellChecker.cpp_sec5
|
| 162 |
if (!isValid(sequence)) |
195 |
if (!isValid(sequence)) |
| 163 |
return; |
196 |
return; |
| 164 |
|
197 |
|
| 165 |
if (!isCheckable(m_requestRange.get())) { |
198 |
if (!isCheckable(m_processingRequest->range().get())) { |
| 166 |
clearRequest(); |
199 |
processQueuedRequest(); |
| 167 |
return; |
200 |
return; |
| 168 |
} |
201 |
} |
| 169 |
|
202 |
|
| 170 |
int startOffset = 0; |
203 |
int startOffset = 0; |
| 171 |
PositionIterator start = m_requestRange->startPosition(); |
204 |
PositionIterator start = m_processingRequest->range()->startPosition(); |
| 172 |
for (size_t i = 0; i < results.size(); ++i) { |
205 |
for (size_t i = 0; i < results.size(); ++i) { |
| 173 |
if (results[i].type != TextCheckingTypeSpelling && results[i].type != TextCheckingTypeGrammar) |
206 |
if (results[i].type != TextCheckingTypeSpelling && results[i].type != TextCheckingTypeGrammar) |
| 174 |
continue; |
207 |
continue; |
|
Lines 186-202
void SpellChecker::didCheck(int sequence, const Vector<TextCheckingResult>& resu
a/Source/WebCore/editing/SpellChecker.cpp_sec6
|
| 186 |
// spellings in the background. To avoid adding markers to the words modified by users or |
219 |
// spellings in the background. To avoid adding markers to the words modified by users or |
| 187 |
// JavaScript applications, retrieve the words in the specified region and compare them with |
220 |
// JavaScript applications, retrieve the words in the specified region and compare them with |
| 188 |
// the original ones. |
221 |
// the original ones. |
| 189 |
RefPtr<Range> range = Range::create(m_requestRange->ownerDocument(), start, end); |
222 |
RefPtr<Range> range = Range::create(m_processingRequest->range()->ownerDocument(), start, end); |
| 190 |
// FIXME: Use textContent() compatible string conversion. |
223 |
// FIXME: Use textContent() compatible string conversion. |
| 191 |
String destination = range->text(); |
224 |
String destination = range->text(); |
| 192 |
String source = m_requestText.substring(results[i].location, results[i].length); |
225 |
String source = m_processingRequest->text().substring(results[i].location, results[i].length); |
| 193 |
if (destination == source) |
226 |
if (destination == source) |
| 194 |
m_requestRange->ownerDocument()->markers()->addMarker(range.get(), toMarkerType(results[i].type)); |
227 |
m_processingRequest->range()->ownerDocument()->markers()->addMarker(range.get(), toMarkerType(results[i].type)); |
| 195 |
|
228 |
|
| 196 |
startOffset = results[i].location; |
229 |
startOffset = results[i].location; |
| 197 |
} |
230 |
} |
| 198 |
|
231 |
|
| 199 |
clearRequest(); |
232 |
processQueuedRequest(); |
| 200 |
} |
233 |
} |
| 201 |
|
234 |
|
| 202 |
|
235 |
|