| 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 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 #include "core/editing/markers/DocumentMarkerController.h" | 35 #include "core/editing/markers/DocumentMarkerController.h" |
| 36 #include "core/editing/spellcheck/SpellChecker.h" | 36 #include "core/editing/spellcheck/SpellChecker.h" |
| 37 #include "core/frame/LocalFrame.h" | 37 #include "core/frame/LocalFrame.h" |
| 38 #include "core/frame/Settings.h" | 38 #include "core/frame/Settings.h" |
| 39 #include "core/page/SpellCheckerClient.h" | 39 #include "core/page/SpellCheckerClient.h" |
| 40 #include "platform/text/TextBreakIterator.h" | 40 #include "platform/text/TextBreakIterator.h" |
| 41 #include "platform/text/TextCheckerClient.h" | 41 #include "platform/text/TextCheckerClient.h" |
| 42 | 42 |
| 43 namespace blink { | 43 namespace blink { |
| 44 | 44 |
| 45 // TODO(xiaochengh): Move this function to SpellChecker.cpp | |
| 46 void SpellChecker::findMisspellings(const String& text, Vector<TextCheckingResul
t>& results) | |
| 47 { | |
| 48 Vector<UChar> characters; | |
| 49 text.appendTo(characters); | |
| 50 unsigned length = text.length(); | |
| 51 | |
| 52 TextBreakIterator* iterator = wordBreakIterator(characters.data(), length); | |
| 53 if (!iterator) | |
| 54 return; | |
| 55 | |
| 56 int wordStart = iterator->current(); | |
| 57 while (0 <= wordStart) { | |
| 58 int wordEnd = iterator->next(); | |
| 59 if (wordEnd < 0) | |
| 60 break; | |
| 61 int wordLength = wordEnd - wordStart; | |
| 62 int misspellingLocation = -1; | |
| 63 int misspellingLength = 0; | |
| 64 textChecker().checkSpellingOfString(String(characters.data() + wordStart
, wordLength), &misspellingLocation, &misspellingLength); | |
| 65 if (0 < misspellingLength) { | |
| 66 DCHECK_LE(0, misspellingLocation); | |
| 67 DCHECK_LE(misspellingLocation, wordLength); | |
| 68 DCHECK_LT(0, misspellingLength); | |
| 69 DCHECK_LE(misspellingLocation + misspellingLength, wordLength); | |
| 70 TextCheckingResult misspelling; | |
| 71 misspelling.decoration = TextDecorationTypeSpelling; | |
| 72 misspelling.location = wordStart + misspellingLocation; | |
| 73 misspelling.length = misspellingLength; | |
| 74 results.append(misspelling); | |
| 75 } | |
| 76 | |
| 77 wordStart = wordEnd; | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 static EphemeralRange expandToParagraphBoundary(const EphemeralRange& range) | 45 static EphemeralRange expandToParagraphBoundary(const EphemeralRange& range) |
| 82 { | 46 { |
| 83 const VisiblePosition& start = createVisiblePosition(range.startPosition()); | 47 const VisiblePosition& start = createVisiblePosition(range.startPosition()); |
| 84 DCHECK(start.isNotNull()) << range.startPosition(); | 48 DCHECK(start.isNotNull()) << range.startPosition(); |
| 85 const VisiblePosition& paragraphStart = startOfParagraph(start); | 49 const VisiblePosition& paragraphStart = startOfParagraph(start); |
| 86 DCHECK(paragraphStart.isNotNull()) << range.startPosition(); | 50 DCHECK(paragraphStart.isNotNull()) << range.startPosition(); |
| 87 | 51 |
| 88 const VisiblePosition& end = createVisiblePosition(range.endPosition()); | 52 const VisiblePosition& end = createVisiblePosition(range.endPosition()); |
| 89 DCHECK(end.isNotNull()) << range.endPosition(); | 53 DCHECK(end.isNotNull()) << range.endPosition(); |
| 90 const VisiblePosition& paragraphEnd = endOfParagraph(end); | 54 const VisiblePosition& paragraphEnd = endOfParagraph(end); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 } | 180 } |
| 217 | 181 |
| 218 int TextCheckingParagraph::checkingLength() const | 182 int TextCheckingParagraph::checkingLength() const |
| 219 { | 183 { |
| 220 DCHECK(m_checkingRange.isNotNull()); | 184 DCHECK(m_checkingRange.isNotNull()); |
| 221 if (-1 == m_checkingLength) | 185 if (-1 == m_checkingLength) |
| 222 m_checkingLength = TextIterator::rangeLength(checkingRange().startPositi
on(), checkingRange().endPosition()); | 186 m_checkingLength = TextIterator::rangeLength(checkingRange().startPositi
on(), checkingRange().endPosition()); |
| 223 return m_checkingLength; | 187 return m_checkingLength; |
| 224 } | 188 } |
| 225 | 189 |
| 226 // TODO(xiaochengh): Move this function to SpellChecker.cpp | |
| 227 String SpellChecker::findFirstMisspellingOrBadGrammar(const Position& start, con
st Position& end, int& outFirstFoundOffset) | |
| 228 { | |
| 229 String firstFoundItem; | |
| 230 String misspelledWord; | |
| 231 | |
| 232 // Initialize out parameter; it will be updated if we find something to retu
rn. | |
| 233 outFirstFoundOffset = 0; | |
| 234 | |
| 235 // Expand the search range to encompass entire paragraphs, since text checki
ng needs that much context. | |
| 236 // Determine the character offset from the start of the paragraph to the sta
rt of the original search range, | |
| 237 // since we will want to ignore results in this area. | |
| 238 Position paragraphStart = startOfParagraph(createVisiblePosition(start)).toP
arentAnchoredPosition(); | |
| 239 Position paragraphEnd = end; | |
| 240 int totalRangeLength = TextIterator::rangeLength(paragraphStart, paragraphEn
d); | |
| 241 paragraphEnd = endOfParagraph(createVisiblePosition(start)).toParentAnchored
Position(); | |
| 242 | |
| 243 int rangeStartOffset = TextIterator::rangeLength(paragraphStart, start); | |
| 244 int totalLengthProcessed = 0; | |
| 245 | |
| 246 bool firstIteration = true; | |
| 247 bool lastIteration = false; | |
| 248 while (totalLengthProcessed < totalRangeLength) { | |
| 249 // Iterate through the search range by paragraphs, checking each one for
spelling. | |
| 250 int currentLength = TextIterator::rangeLength(paragraphStart, paragraphE
nd); | |
| 251 int currentStartOffset = firstIteration ? rangeStartOffset : 0; | |
| 252 int currentEndOffset = currentLength; | |
| 253 if (inSameParagraph(createVisiblePosition(paragraphStart), createVisible
Position(end))) { | |
| 254 // Determine the character offset from the end of the original searc
h range to the end of the paragraph, | |
| 255 // since we will want to ignore results in this area. | |
| 256 currentEndOffset = TextIterator::rangeLength(paragraphStart, end); | |
| 257 lastIteration = true; | |
| 258 } | |
| 259 if (currentStartOffset < currentEndOffset) { | |
| 260 String paragraphString = plainText(EphemeralRange(paragraphStart, pa
ragraphEnd)); | |
| 261 if (paragraphString.length() > 0) { | |
| 262 int spellingLocation = 0; | |
| 263 | |
| 264 Vector<TextCheckingResult> results; | |
| 265 findMisspellings(paragraphString, results); | |
| 266 | |
| 267 for (unsigned i = 0; i < results.size(); i++) { | |
| 268 const TextCheckingResult* result = &results[i]; | |
| 269 if (result->decoration == TextDecorationTypeSpelling && resu
lt->location >= currentStartOffset && result->location + result->length <= curre
ntEndOffset) { | |
| 270 DCHECK_GT(result->length, 0); | |
| 271 DCHECK_GE(result->location, 0); | |
| 272 spellingLocation = result->location; | |
| 273 misspelledWord = paragraphString.substring(result->locat
ion, result->length); | |
| 274 DCHECK(misspelledWord.length()); | |
| 275 break; | |
| 276 } | |
| 277 } | |
| 278 | |
| 279 if (!misspelledWord.isEmpty()) { | |
| 280 int spellingOffset = spellingLocation - currentStartOffset; | |
| 281 if (!firstIteration) | |
| 282 spellingOffset += TextIterator::rangeLength(start, parag
raphStart); | |
| 283 outFirstFoundOffset = spellingOffset; | |
| 284 firstFoundItem = misspelledWord; | |
| 285 break; | |
| 286 } | |
| 287 } | |
| 288 } | |
| 289 if (lastIteration || totalLengthProcessed + currentLength >= totalRangeL
ength) | |
| 290 break; | |
| 291 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); | |
| 292 paragraphStart = newParagraphStart.toParentAnchoredPosition(); | |
| 293 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); | |
| 294 firstIteration = false; | |
| 295 totalLengthProcessed += currentLength; | |
| 296 } | |
| 297 return firstFoundItem; | |
| 298 } | |
| 299 | |
| 300 } // namespace blink | 190 } // namespace blink |
| OLD | NEW |