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 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 : m_client(&client) | 225 : m_client(&client) |
226 , m_start(start) | 226 , m_start(start) |
227 , m_end(end) | 227 , m_end(end) |
228 { | 228 { |
229 } | 229 } |
230 | 230 |
231 TextCheckingHelper::~TextCheckingHelper() | 231 TextCheckingHelper::~TextCheckingHelper() |
232 { | 232 { |
233 } | 233 } |
234 | 234 |
235 String TextCheckingHelper::findFirstMisspelling(int& firstMisspellingOffset, boo
l markAll) | |
236 { | |
237 // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets n
eeds to be audited. | |
238 // see http://crbug.com/590369 for more details. | |
239 m_start.document()->updateStyleAndLayoutIgnorePendingStylesheets(); | |
240 | |
241 WordAwareIterator it(m_start, m_end); | |
242 firstMisspellingOffset = 0; | |
243 | |
244 String firstMisspelling; | |
245 int currentChunkOffset = 0; | |
246 | |
247 while (!it.atEnd()) { | |
248 int length = it.length(); | |
249 | |
250 // Skip some work for one-space-char hunks | |
251 if (!(length == 1 && it.characterAt(0) == ' ')) { | |
252 | |
253 int misspellingLocation = -1; | |
254 int misspellingLength = 0; | |
255 m_client->textChecker().checkSpellingOfString(it.substring(0, length
), &misspellingLocation, &misspellingLength); | |
256 | |
257 // 5490627 shows that there was some code path here where the String
constructor below crashes. | |
258 // We don't know exactly what combination of bad input caused this,
so we're making this much | |
259 // more robust against bad input on release builds. | |
260 DCHECK_GE(misspellingLength, 0); | |
261 DCHECK_GE(misspellingLocation, -1); | |
262 DCHECK(!misspellingLength || misspellingLocation >= 0); | |
263 DCHECK_LT(misspellingLocation, length); | |
264 DCHECK_LE(misspellingLength, length); | |
265 DCHECK_LE(misspellingLocation + misspellingLength, length); | |
266 | |
267 if (misspellingLocation >= 0 && misspellingLength > 0 && misspelling
Location < length && misspellingLength <= length && misspellingLocation + misspe
llingLength <= length) { | |
268 | |
269 // Compute range of misspelled word | |
270 const EphemeralRange misspellingRange = calculateCharacterSubran
ge(EphemeralRange(m_start, m_end), currentChunkOffset + misspellingLocation, mis
spellingLength); | |
271 | |
272 // Remember first-encountered misspelling and its offset. | |
273 if (!firstMisspelling) { | |
274 firstMisspellingOffset = currentChunkOffset + misspellingLoc
ation; | |
275 firstMisspelling = it.substring(misspellingLocation, misspel
lingLength); | |
276 } | |
277 | |
278 // Store marker for misspelled word. | |
279 misspellingRange.document().markers().addMarker(misspellingRange
.startPosition(), misspellingRange.endPosition(), DocumentMarker::Spelling); | |
280 | |
281 // Bail out if we're marking only the first misspelling, and not
all instances. | |
282 if (!markAll) | |
283 break; | |
284 } | |
285 } | |
286 | |
287 currentChunkOffset += length; | |
288 it.advance(); | |
289 } | |
290 | |
291 return firstMisspelling; | |
292 } | |
293 | |
294 String TextCheckingHelper::findFirstMisspellingOrBadGrammar(int& outFirstFoundOf
fset) | 235 String TextCheckingHelper::findFirstMisspellingOrBadGrammar(int& outFirstFoundOf
fset) |
295 { | 236 { |
296 if (!unifiedTextCheckerEnabled()) | |
297 return ""; | |
298 | |
299 String firstFoundItem; | 237 String firstFoundItem; |
300 String misspelledWord; | 238 String misspelledWord; |
301 | 239 |
302 // Initialize out parameter; it will be updated if we find something to retu
rn. | 240 // Initialize out parameter; it will be updated if we find something to retu
rn. |
303 outFirstFoundOffset = 0; | 241 outFirstFoundOffset = 0; |
304 | 242 |
305 // Expand the search range to encompass entire paragraphs, since text checki
ng needs that much context. | 243 // Expand the search range to encompass entire paragraphs, since text checki
ng needs that much context. |
306 // Determine the character offset from the start of the paragraph to the sta
rt of the original search range, | 244 // Determine the character offset from the start of the paragraph to the sta
rt of the original search range, |
307 // since we will want to ignore results in this area. | 245 // since we will want to ignore results in this area. |
308 Position paragraphStart = startOfParagraph(createVisiblePosition(m_start)).t
oParentAnchoredPosition(); | 246 Position paragraphStart = startOfParagraph(createVisiblePosition(m_start)).t
oParentAnchoredPosition(); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 break; | 298 break; |
361 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); | 299 VisiblePosition newParagraphStart = startOfNextParagraph(createVisiblePo
sition(paragraphEnd)); |
362 paragraphStart = newParagraphStart.toParentAnchoredPosition(); | 300 paragraphStart = newParagraphStart.toParentAnchoredPosition(); |
363 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); | 301 paragraphEnd = endOfParagraph(newParagraphStart).toParentAnchoredPositio
n(); |
364 firstIteration = false; | 302 firstIteration = false; |
365 totalLengthProcessed += currentLength; | 303 totalLengthProcessed += currentLength; |
366 } | 304 } |
367 return firstFoundItem; | 305 return firstFoundItem; |
368 } | 306 } |
369 | 307 |
370 bool TextCheckingHelper::markAllMisspellings() | |
371 { | |
372 // Use the "markAll" feature of findFirstMisspelling. Ignore the return valu
e and the "out parameter"; | |
373 // all we need to do is mark every instance. | |
374 int ignoredOffset; | |
375 return findFirstMisspelling(ignoredOffset, true).isEmpty(); | |
376 } | |
377 | |
378 bool TextCheckingHelper::unifiedTextCheckerEnabled() const | |
379 { | |
380 DCHECK(m_start.isNotNull()); | |
381 Document& doc = m_start.computeContainerNode()->document(); | |
382 return blink::unifiedTextCheckerEnabled(doc.frame()); | |
383 } | |
384 | |
385 bool unifiedTextCheckerEnabled(const LocalFrame* frame) | |
386 { | |
387 if (!frame) | |
388 return false; | |
389 | |
390 const Settings* settings = frame->settings(); | |
391 if (!settings) | |
392 return false; | |
393 | |
394 return settings->unifiedTextCheckerEnabled(); | |
395 } | |
396 | |
397 } // namespace blink | 308 } // namespace blink |
OLD | NEW |