OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 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 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 applyCommand(ReplaceSelectionCommand::create(m_frame->document(), fragment,
options, EditActionPaste)); | 414 applyCommand(ReplaceSelectionCommand::create(m_frame->document(), fragment,
options, EditActionPaste)); |
415 revealSelectionAfterEditingOperation(); | 415 revealSelectionAfterEditingOperation(); |
416 | 416 |
417 if (m_frame->selection()->isInPasswordField() || !isContinuousSpellCheckingE
nabled()) | 417 if (m_frame->selection()->isInPasswordField() || !isContinuousSpellCheckingE
nabled()) |
418 return; | 418 return; |
419 Node* nodeToCheck = m_frame->selection()->rootEditableElement(); | 419 Node* nodeToCheck = m_frame->selection()->rootEditableElement(); |
420 if (!nodeToCheck) | 420 if (!nodeToCheck) |
421 return; | 421 return; |
422 | 422 |
423 RefPtr<Range> rangeToCheck = Range::create(m_frame->document(), firstPositio
nInNode(nodeToCheck), lastPositionInNode(nodeToCheck)); | 423 RefPtr<Range> rangeToCheck = Range::create(m_frame->document(), firstPositio
nInNode(nodeToCheck), lastPositionInNode(nodeToCheck)); |
424 m_spellChecker->requestCheckingFor(SpellCheckRequest::create(resolveTextChec
kingTypeMask(TextCheckingTypeSpelling | TextCheckingTypeGrammar), TextCheckingPr
ocessBatch, rangeToCheck, rangeToCheck)); | 424 markAllMisspellingsAndBadGrammarInRanges(resolveTextCheckingTypeMask(TextChe
ckingTypeSpelling | TextCheckingTypeGrammar), rangeToCheck.get(), rangeToCheck.g
et()); |
425 } | 425 } |
426 | 426 |
427 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement
, bool smartReplace) | 427 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement
, bool smartReplace) |
428 { | 428 { |
429 replaceSelectionWithFragment(createFragmentFromText(selectedRange().get(), t
ext), selectReplacement, smartReplace, true); | 429 replaceSelectionWithFragment(createFragmentFromText(selectedRange().get(), t
ext), selectReplacement, smartReplace, true); |
430 } | 430 } |
431 | 431 |
432 PassRefPtr<Range> Editor::selectedRange() | 432 PassRefPtr<Range> Editor::selectedRange() |
433 { | 433 { |
434 if (!m_frame) | 434 if (!m_frame) |
(...skipping 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1479 | 1479 |
1480 void Editor::markBadGrammar(const VisibleSelection& selection) | 1480 void Editor::markBadGrammar(const VisibleSelection& selection) |
1481 { | 1481 { |
1482 RefPtr<Range> firstMisspellingRange; | 1482 RefPtr<Range> firstMisspellingRange; |
1483 markMisspellingsOrBadGrammar(selection, false, firstMisspellingRange); | 1483 markMisspellingsOrBadGrammar(selection, false, firstMisspellingRange); |
1484 } | 1484 } |
1485 | 1485 |
1486 void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textC
heckingOptions, Range* spellingRange, Range* grammarRange) | 1486 void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textC
heckingOptions, Range* spellingRange, Range* grammarRange) |
1487 { | 1487 { |
1488 ASSERT(m_frame); | 1488 ASSERT(m_frame); |
1489 ASSERT(unifiedTextCheckerEnabled()); | |
1490 | 1489 |
1491 bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar; | 1490 bool shouldMarkGrammar = (textCheckingOptions & TextCheckingTypeGrammar) &&
isGrammarCheckingEnabled(); |
| 1491 bool shouldMarkSpellling = (textCheckingOptions & TextCheckingTypeSpelling)
&& isContinuousSpellCheckingEnabled(); |
| 1492 |
| 1493 if (!shouldMarkSpellling && !shouldMarkGrammar) |
| 1494 return; |
1492 | 1495 |
1493 // This function is called with selections already expanded to word boundari
es. | 1496 // This function is called with selections already expanded to word boundari
es. |
1494 if (!client() || !spellingRange || (shouldMarkGrammar && !grammarRange)) | 1497 if (!client() || !spellingRange || (shouldMarkGrammar && !grammarRange)) |
1495 return; | 1498 return; |
1496 | 1499 |
1497 // If we're not in an editable node, bail. | 1500 // If we're not in an editable node, bail. |
1498 Node* editableNode = spellingRange->startContainer(); | 1501 Node* editableNode = spellingRange->startContainer(); |
1499 if (!editableNode || !editableNode->rendererIsEditable()) | 1502 if (!editableNode || !editableNode->rendererIsEditable()) |
1500 return; | 1503 return; |
1501 | 1504 |
1502 if (!isSpellCheckingEnabledFor(editableNode)) | 1505 if (!isSpellCheckingEnabledFor(editableNode)) |
1503 return; | 1506 return; |
1504 | 1507 |
1505 Range* rangeToCheck = shouldMarkGrammar ? grammarRange : spellingRange; | 1508 Range* rangeToCheck = shouldMarkGrammar ? grammarRange : spellingRange; |
1506 TextCheckingParagraph paragraphToCheck(rangeToCheck); | 1509 TextCheckingParagraph fullParagraphToCheck(rangeToCheck); |
1507 if (paragraphToCheck.isRangeEmpty() || paragraphToCheck.isEmpty()) | 1510 if (fullParagraphToCheck.isRangeEmpty() || fullParagraphToCheck.isEmpty()) |
1508 return; | 1511 return; |
1509 RefPtr<Range> paragraphRange = paragraphToCheck.paragraphRange(); | |
1510 | 1512 |
| 1513 // Since the text may be quite big chunk it up and adjust to the sentence bo
undary. |
| 1514 const int kChunkSize = 16 * 1024; |
| 1515 int start = fullParagraphToCheck.checkingStart(); |
| 1516 int end = fullParagraphToCheck.checkingEnd(); |
| 1517 start = std::min(start, end); |
| 1518 end = std::max(start, end); |
1511 bool asynchronous = m_frame && m_frame->settings() && m_frame->settings()->a
synchronousSpellCheckingEnabled(); | 1519 bool asynchronous = m_frame && m_frame->settings() && m_frame->settings()->a
synchronousSpellCheckingEnabled(); |
| 1520 const int kNumChunksToCheck = asynchronous ? (end - start + kChunkSize - 1)
/ (kChunkSize) : 1; |
| 1521 int currentChunkStart = start; |
| 1522 for (int iter = 0; iter < kNumChunksToCheck; ++iter) { |
| 1523 RefPtr<Range> checkRange = fullParagraphToCheck.subrange(currentChunkSta
rt, kChunkSize); |
| 1524 setStart(checkRange.get(), startOfSentence(checkRange->startPosition()))
; |
| 1525 setEnd(checkRange.get(), endOfSentence(checkRange->endPosition())); |
| 1526 TextCheckingParagraph sentenceToCheck(checkRange, checkRange); |
1512 | 1527 |
1513 // In asynchronous mode, we intentionally check paragraph-wide sentence. | 1528 currentChunkStart += sentenceToCheck.checkingLength(); |
1514 RefPtr<SpellCheckRequest> request = SpellCheckRequest::create(resolveTextChe
ckingTypeMask(textCheckingOptions), TextCheckingProcessIncremental, asynchronous
? paragraphRange : rangeToCheck, paragraphRange); | |
1515 | 1529 |
1516 if (asynchronous) { | 1530 RefPtr<SpellCheckRequest> request = SpellCheckRequest::create(resolveTex
tCheckingTypeMask(textCheckingOptions), TextCheckingProcessBatch, checkRange, ch
eckRange, iter); |
1517 m_spellChecker->requestCheckingFor(request); | 1531 |
1518 return; | 1532 if (asynchronous) { |
| 1533 m_spellChecker->requestCheckingFor(request); |
| 1534 continue; |
| 1535 } |
| 1536 |
| 1537 Vector<TextCheckingResult> results; |
| 1538 checkTextOfParagraph(textChecker(), sentenceToCheck.text(), resolveTextC
heckingTypeMask(textCheckingOptions), results); |
| 1539 markAndReplaceFor(request, results); |
1519 } | 1540 } |
1520 | |
1521 Vector<TextCheckingResult> results; | |
1522 checkTextOfParagraph(textChecker(), paragraphToCheck.text(), resolveTextChec
kingTypeMask(textCheckingOptions), results); | |
1523 markAndReplaceFor(request, results); | |
1524 } | 1541 } |
1525 | 1542 |
1526 void Editor::markAndReplaceFor(PassRefPtr<SpellCheckRequest> request, const Vect
or<TextCheckingResult>& results) | 1543 void Editor::markAndReplaceFor(PassRefPtr<SpellCheckRequest> request, const Vect
or<TextCheckingResult>& results) |
1527 { | 1544 { |
1528 ASSERT(request); | 1545 ASSERT(request); |
1529 | 1546 |
1530 TextCheckingTypeMask textCheckingOptions = request->data().mask(); | 1547 TextCheckingTypeMask textCheckingOptions = request->data().mask(); |
1531 TextCheckingParagraph paragraph(request->checkingRange(), request->paragraph
Range()); | 1548 TextCheckingParagraph paragraph(request->checkingRange(), request->paragraph
Range()); |
1532 | 1549 |
1533 bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; | 1550 bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling; |
(...skipping 15 matching lines...) Expand all Loading... |
1549 if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) >
paragraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newli
neCharacter)) | 1566 if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) >
paragraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newli
neCharacter)) |
1550 adjustSelectionForParagraphBoundaries = true; | 1567 adjustSelectionForParagraphBoundaries = true; |
1551 if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <=
paragraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(
selectionOffset - 1))) | 1568 if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <=
paragraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(
selectionOffset - 1))) |
1552 ambiguousBoundaryOffset = selectionOffset - 1; | 1569 ambiguousBoundaryOffset = selectionOffset - 1; |
1553 } | 1570 } |
1554 } | 1571 } |
1555 | 1572 |
1556 for (unsigned i = 0; i < results.size(); i++) { | 1573 for (unsigned i = 0; i < results.size(); i++) { |
1557 int spellingRangeEndOffset = paragraph.checkingEnd(); | 1574 int spellingRangeEndOffset = paragraph.checkingEnd(); |
1558 const TextCheckingResult* result = &results[i]; | 1575 const TextCheckingResult* result = &results[i]; |
1559 int resultLocation = result->location; | 1576 int resultLocation = result->location + paragraph.checkingStart(); |
1560 int resultLength = result->length; | 1577 int resultLength = result->length; |
1561 bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 && res
ultLocation + resultLength == ambiguousBoundaryOffset; | 1578 bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 && res
ultLocation + resultLength == ambiguousBoundaryOffset; |
1562 | 1579 |
1563 // Only mark misspelling if: | 1580 // Only mark misspelling if: |
1564 // 1. Current text checking isn't done for autocorrection, in which case
shouldMarkSpelling is false. | 1581 // 1. Current text checking isn't done for autocorrection, in which case
shouldMarkSpelling is false. |
1565 // 2. Result falls within spellingRange. | 1582 // 2. Result falls within spellingRange. |
1566 // 3. The word in question doesn't end at an ambiguous boundary. For ins
tance, we would not mark | 1583 // 3. The word in question doesn't end at an ambiguous boundary. For ins
tance, we would not mark |
1567 // "wouldn'" as misspelled right after apostrophe is typed. | 1584 // "wouldn'" as misspelled right after apostrophe is typed. |
1568 if (shouldMarkSpelling && result->type == TextCheckingTypeSpelling && re
sultLocation >= paragraph.checkingStart() && resultLocation + resultLength <= sp
ellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) { | 1585 if (shouldMarkSpelling && result->type == TextCheckingTypeSpelling && re
sultLocation >= paragraph.checkingStart() && resultLocation + resultLength <= sp
ellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) { |
1569 ASSERT(resultLength > 0 && resultLocation >= 0); | 1586 ASSERT(resultLength > 0 && resultLocation >= 0); |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2178 return WebCore::unifiedTextCheckerEnabled(m_frame); | 2195 return WebCore::unifiedTextCheckerEnabled(m_frame); |
2179 } | 2196 } |
2180 | 2197 |
2181 void Editor::toggleOverwriteModeEnabled() | 2198 void Editor::toggleOverwriteModeEnabled() |
2182 { | 2199 { |
2183 m_overwriteModeEnabled = !m_overwriteModeEnabled; | 2200 m_overwriteModeEnabled = !m_overwriteModeEnabled; |
2184 frame()->selection()->setShouldShowBlockCursor(m_overwriteModeEnabled); | 2201 frame()->selection()->setShouldShowBlockCursor(m_overwriteModeEnabled); |
2185 }; | 2202 }; |
2186 | 2203 |
2187 } // namespace WebCore | 2204 } // namespace WebCore |
OLD | NEW |