OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. |
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
13 * | 13 * |
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 */ | 25 */ |
26 | 26 |
27 #include "core/editing/spellcheck/TextCheckingHelper.h" | 27 #include "core/editing/spellcheck/TextCheckingParagraph.h" |
28 | 28 |
29 #include "core/dom/Document.h" | 29 #include "core/dom/Document.h" |
30 #include "core/dom/Range.h" | 30 #include "core/dom/Range.h" |
31 #include "core/editing/VisiblePosition.h" | 31 #include "core/editing/VisiblePosition.h" |
32 #include "core/editing/VisibleUnits.h" | 32 #include "core/editing/VisibleUnits.h" |
33 #include "core/editing/iterators/CharacterIterator.h" | 33 #include "core/editing/iterators/CharacterIterator.h" |
34 #include "core/editing/iterators/WordAwareIterator.h" | 34 #include "core/editing/iterators/WordAwareIterator.h" |
35 #include "core/editing/markers/DocumentMarkerController.h" | |
36 #include "core/frame/LocalFrame.h" | |
37 #include "core/frame/Settings.h" | |
38 #include "core/page/SpellCheckerClient.h" | |
39 #include "platform/text/TextBreakIterator.h" | |
40 #include "platform/text/TextCheckerClient.h" | |
41 | 35 |
42 namespace blink { | 36 namespace blink { |
43 | 37 |
44 static void findMisspellings(TextCheckerClient& client, const String& text, Vect or<TextCheckingResult>& results) | |
yosin_UTC9
2016/08/16 06:04:06
Let's move class here, then re-factor.
| |
45 { | |
46 Vector<UChar> characters; | |
47 text.appendTo(characters); | |
48 unsigned length = text.length(); | |
49 | |
50 TextBreakIterator* iterator = wordBreakIterator(characters.data(), length); | |
51 if (!iterator) | |
52 return; | |
53 | |
54 int wordStart = iterator->current(); | |
55 while (0 <= wordStart) { | |
56 int wordEnd = iterator->next(); | |
57 if (wordEnd < 0) | |
58 break; | |
59 int wordLength = wordEnd - wordStart; | |
60 int misspellingLocation = -1; | |
61 int misspellingLength = 0; | |
62 client.checkSpellingOfString(String(characters.data() + wordStart, wordL ength), &misspellingLocation, &misspellingLength); | |
63 if (0 < misspellingLength) { | |
64 DCHECK_LE(0, misspellingLocation); | |
65 DCHECK_LE(misspellingLocation, wordLength); | |
66 DCHECK_LT(0, misspellingLength); | |
67 DCHECK_LE(misspellingLocation + misspellingLength, wordLength); | |
68 TextCheckingResult misspelling; | |
69 misspelling.decoration = TextDecorationTypeSpelling; | |
70 misspelling.location = wordStart + misspellingLocation; | |
71 misspelling.length = misspellingLength; | |
72 results.append(misspelling); | |
73 } | |
74 | |
75 wordStart = wordEnd; | |
76 } | |
77 } | |
78 | |
79 static EphemeralRange expandToParagraphBoundary(const EphemeralRange& range) | 38 static EphemeralRange expandToParagraphBoundary(const EphemeralRange& range) |
80 { | 39 { |
81 const VisiblePosition& start = createVisiblePosition(range.startPosition()); | 40 const VisiblePosition& start = createVisiblePosition(range.startPosition()); |
82 DCHECK(start.isNotNull()) << range.startPosition(); | 41 DCHECK(start.isNotNull()) << range.startPosition(); |
83 const VisiblePosition& paragraphStart = startOfParagraph(start); | 42 const VisiblePosition& paragraphStart = startOfParagraph(start); |
84 DCHECK(paragraphStart.isNotNull()) << range.startPosition(); | 43 DCHECK(paragraphStart.isNotNull()) << range.startPosition(); |
85 | 44 |
86 const VisiblePosition& end = createVisiblePosition(range.endPosition()); | 45 const VisiblePosition& end = createVisiblePosition(range.endPosition()); |
87 DCHECK(end.isNotNull()) << range.endPosition(); | 46 DCHECK(end.isNotNull()) << range.endPosition(); |
88 const VisiblePosition& paragraphEnd = endOfParagraph(end); | 47 const VisiblePosition& paragraphEnd = endOfParagraph(end); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 } | 173 } |
215 | 174 |
216 int TextCheckingParagraph::checkingLength() const | 175 int TextCheckingParagraph::checkingLength() const |
217 { | 176 { |
218 DCHECK(m_checkingRange.isNotNull()); | 177 DCHECK(m_checkingRange.isNotNull()); |
219 if (-1 == m_checkingLength) | 178 if (-1 == m_checkingLength) |
220 m_checkingLength = TextIterator::rangeLength(checkingRange().startPositi on(), checkingRange().endPosition()); | 179 m_checkingLength = TextIterator::rangeLength(checkingRange().startPositi on(), checkingRange().endPosition()); |
221 return m_checkingLength; | 180 return m_checkingLength; |
222 } | 181 } |
223 | 182 |
224 TextCheckingHelper::TextCheckingHelper(SpellCheckerClient& client, const Positio n& start, const Position& end) | |
225 : m_client(&client) | |
226 , m_start(start) | |
227 , m_end(end) | |
228 { | |
229 } | |
230 | |
231 TextCheckingHelper::~TextCheckingHelper() | |
232 { | |
233 } | |
234 | |
235 String TextCheckingHelper::findFirstMisspellingOrBadGrammar(int& outFirstFoundOf fset) | |
236 { | |
237 String firstFoundItem; | |
238 String misspelledWord; | |
239 | |
240 // Initialize out parameter; it will be updated if we find something to retu rn. | |
241 outFirstFoundOffset = 0; | |
242 | |
243 // Expand the search range to encompass entire paragraphs, since text checki ng needs that much context. | |
244 // Determine the character offset from the start of the paragraph to the sta rt of the original search range, | |
245 // since we will want to ignore results in this area. | |
246 Position paragraphStart = startOfParagraph(createVisiblePosition(m_start)).t oParentAnchoredPosition(); | |
247 Position paragraphEnd = m_end; | |
248 int totalRangeLength = TextIterator::rangeLength(paragraphStart, paragraphEn d); | |
249 paragraphEnd = endOfParagraph(createVisiblePosition(m_start)).toParentAnchor edPosition(); | |
250 | |
251 int rangeStartOffset = TextIterator::rangeLength(paragraphStart, m_start); | |
252 int totalLengthProcessed = 0; | |
253 | |
254 bool firstIteration = true; | |
255 bool lastIteration = false; | |
256 while (totalLengthProcessed < totalRangeLength) { | |
257 // Iterate through the search range by paragraphs, checking each one for spelling. | |
258 int currentLength = TextIterator::rangeLength(paragraphStart, paragraphE nd); | |
259 int currentStartOffset = firstIteration ? rangeStartOffset : 0; | |
260 int currentEndOffset = currentLength; | |
261 if (inSameParagraph(createVisiblePosition(paragraphStart), createVisible Position(m_end))) { | |
262 // Determine the character offset from the end of the original searc h range to the end of the paragraph, | |
263 // since we will want to ignore results in this area. | |
264 currentEndOffset = TextIterator::rangeLength(paragraphStart, m_end); | |
265 lastIteration = true; | |
266 } | |
267 if (currentStartOffset < currentEndOffset) { | |
268 String paragraphString = plainText(EphemeralRange(paragraphStart, pa ragraphEnd)); | |
269 if (paragraphString.length() > 0) { | |
270 int spellingLocation = 0; | |
271 | |
272 Vector<TextCheckingResult> results; | |
273 findMisspellings(m_client->textChecker(), paragraphString, resul ts); | |
274 | |
275 for (unsigned i = 0; i < results.size(); i++) { | |
276 const TextCheckingResult* result = &results[i]; | |
277 if (result->decoration == TextDecorationTypeSpelling && resu lt->location >= currentStartOffset && result->location + result->length <= curre ntEndOffset) { | |
278 DCHECK_GT(result->length, 0); | |
279 DCHECK_GE(result->location, 0); | |
280 spellingLocation = result->location; | |
281 misspelledWord = paragraphString.substring(result->locat ion, result->length); | |
282 DCHECK(misspelledWord.length()); | |
283 break; | |
284 } | |
285 } | |
286 | |
287 if (!misspelledWord.isEmpty()) { | |
288 int spellingOffset = spellingLocation - currentStartOffset; | |
289 if (!firstIteration) | |
290 spellingOffset += TextIterator::rangeLength(m_start, par agraphStart); | |
291 outFirstFoundOffset = spellingOffset; | |
292 firstFoundItem = misspelledWord; | |
293 break; | |
294 } | |
295 } | |
296 } | |
297 if (lastIteration || totalLengthProcessed + currentLength >= totalRangeL ength) | |
298 break; | |
299 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo sition(paragraphEnd)); | |
300 paragraphStart = newParagraphStart.toParentAnchoredPosition(); | |
301 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio n(); | |
302 firstIteration = false; | |
303 totalLengthProcessed += currentLength; | |
304 } | |
305 return firstFoundItem; | |
306 } | |
307 | |
308 } // namespace blink | 183 } // namespace blink |
OLD | NEW |