Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(442)

Side by Side Diff: third_party/WebKit/WebCore/editing/Editor.cpp

Issue 39293: WebKit merge 41447:41498 [third_party/WebKit] (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: remove CRLF Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008 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 853 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 startRoot->dispatchEvent(Event::create(eventNames().webkitEditableConten tChangedEvent, false, false), ec); 864 startRoot->dispatchEvent(Event::create(eventNames().webkitEditableConten tChangedEvent, false, false), ec);
865 if (endRoot && endRoot != startRoot) 865 if (endRoot && endRoot != startRoot)
866 endRoot->dispatchEvent(Event::create(eventNames().webkitEditableContentC hangedEvent, false, false), ec); 866 endRoot->dispatchEvent(Event::create(eventNames().webkitEditableContentC hangedEvent, false, false), ec);
867 } 867 }
868 868
869 void Editor::appliedEditing(PassRefPtr<EditCommand> cmd) 869 void Editor::appliedEditing(PassRefPtr<EditCommand> cmd)
870 { 870 {
871 dispatchEditableContentChangedEvents(*cmd); 871 dispatchEditableContentChangedEvents(*cmd);
872 872
873 VisibleSelection newSelection(cmd->endingSelection()); 873 VisibleSelection newSelection(cmd->endingSelection());
874 // If there is no selection change, don't bother sending shouldChangeSelecti on, but still call setSelection,
875 // because there is work that it must do in this situation.
876 // The old selection can be invalid here and calling shouldChangeSelection c an produce some strange calls.
877 // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ra nges for selections that are no longer valid
878 // Don't clear the typing style with this selection change. We do those thi ngs elsewhere if necessary. 874 // Don't clear the typing style with this selection change. We do those thi ngs elsewhere if necessary.
879 if (newSelection == m_frame->selection()->selection() || m_frame->shouldChan geSelection(newSelection)) 875 changeSelectionAfterCommand(newSelection, false, false, cmd.get());
880 m_frame->selection()->setSelection(newSelection, false, false);
881 876
882 if (!cmd->preservesTypingStyle()) 877 if (!cmd->preservesTypingStyle())
883 m_frame->setTypingStyle(0); 878 m_frame->setTypingStyle(0);
884 879
885 // Command will be equal to last edit command only in the case of typing 880 // Command will be equal to last edit command only in the case of typing
886 if (m_lastEditCommand.get() == cmd) 881 if (m_lastEditCommand.get() == cmd)
887 ASSERT(cmd->isTypingCommand()); 882 ASSERT(cmd->isTypingCommand());
888 else { 883 else {
889 // Only register a new undo command if the command passed in is 884 // Only register a new undo command if the command passed in is
890 // different from the last command 885 // different from the last command
891 m_lastEditCommand = cmd; 886 m_lastEditCommand = cmd;
892 if (client()) 887 if (client())
893 client()->registerCommandForUndo(m_lastEditCommand); 888 client()->registerCommandForUndo(m_lastEditCommand);
894 } 889 }
895 respondToChangedContents(newSelection); 890 respondToChangedContents(newSelection);
896 } 891 }
897 892
898 void Editor::unappliedEditing(PassRefPtr<EditCommand> cmd) 893 void Editor::unappliedEditing(PassRefPtr<EditCommand> cmd)
899 { 894 {
900 dispatchEditableContentChangedEvents(*cmd); 895 dispatchEditableContentChangedEvents(*cmd);
901 896
902 VisibleSelection newSelection(cmd->startingSelection()); 897 VisibleSelection newSelection(cmd->startingSelection());
903 // If there is no selection change, don't bother sending shouldChangeSelecti on, but still call setSelection, 898 changeSelectionAfterCommand(newSelection, true, true, cmd.get());
904 // because there is work that it must do in this situation.
905 // The old selection can be invalid here and calling shouldChangeSelection c an produce some strange calls.
906 // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ra nges for selections that are no longer valid
907 if (newSelection == m_frame->selection()->selection() || m_frame->shouldChan geSelection(newSelection))
908 m_frame->selection()->setSelection(newSelection, true);
909 899
910 m_lastEditCommand = 0; 900 m_lastEditCommand = 0;
911 if (client()) 901 if (client())
912 client()->registerCommandForRedo(cmd); 902 client()->registerCommandForRedo(cmd);
913 respondToChangedContents(newSelection); 903 respondToChangedContents(newSelection);
914 } 904 }
915 905
916 void Editor::reappliedEditing(PassRefPtr<EditCommand> cmd) 906 void Editor::reappliedEditing(PassRefPtr<EditCommand> cmd)
917 { 907 {
918 dispatchEditableContentChangedEvents(*cmd); 908 dispatchEditableContentChangedEvents(*cmd);
919 909
920 VisibleSelection newSelection(cmd->endingSelection()); 910 VisibleSelection newSelection(cmd->endingSelection());
921 // If there is no selection change, don't bother sending shouldChangeSelecti on, but still call setSelection, 911 changeSelectionAfterCommand(newSelection, true, true, cmd.get());
922 // because there is work that it must do in this situation.
923 // The old selection can be invalid here and calling shouldChangeSelection c an produce some strange calls.
924 // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ra nges for selections that are no longer valid
925 if (newSelection == m_frame->selection()->selection() || m_frame->shouldChan geSelection(newSelection))
926 m_frame->selection()->setSelection(newSelection, true);
927 912
928 m_lastEditCommand = 0; 913 m_lastEditCommand = 0;
929 if (client()) 914 if (client())
930 client()->registerCommandForUndo(cmd); 915 client()->registerCommandForUndo(cmd);
931 respondToChangedContents(newSelection); 916 respondToChangedContents(newSelection);
932 } 917 }
933 918
934 Editor::Editor(Frame* frame) 919 Editor::Editor(Frame* frame)
935 : m_frame(frame) 920 : m_frame(frame)
936 , m_deleteButtonController(new DeleteButtonController(frame)) 921 , m_deleteButtonController(new DeleteButtonController(frame))
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 // These results were all between the start of the paragraph and the sta rt of the search range; look 1529 // These results were all between the start of the paragraph and the sta rt of the search range; look
1545 // beyond this phrase. 1530 // beyond this phrase.
1546 startOffset = badGrammarPhraseLocation + badGrammarPhraseLength; 1531 startOffset = badGrammarPhraseLocation + badGrammarPhraseLength;
1547 } 1532 }
1548 1533
1549 return firstBadGrammarPhrase; 1534 return firstBadGrammarPhrase;
1550 } 1535 }
1551 1536
1552 #endif /* not BUILDING_ON_TIGER */ 1537 #endif /* not BUILDING_ON_TIGER */
1553 1538
1539 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD )
1540
1541 static String findFirstMisspellingOrBadGrammarInRange(EditorClient* client, Rang e* searchRange, bool checkGrammar, bool& outIsSpelling, int& outFirstFoundOffset , GrammarDetail& outGrammarDetail)
1542 {
1543 ASSERT_ARG(client, client);
1544 ASSERT_ARG(searchRange, searchRange);
1545
1546 String firstFoundItem;
1547 String misspelledWord;
1548 String badGrammarPhrase;
1549 ExceptionCode ec = 0;
1550
1551 // Initialize out parameters; these will be updated if we find something to return.
1552 outIsSpelling = true;
1553 outFirstFoundOffset = 0;
1554 outGrammarDetail.location = -1;
1555 outGrammarDetail.length = 0;
1556 outGrammarDetail.guesses.clear();
1557 outGrammarDetail.userDescription = "";
1558
1559 // Expand the search range to encompass entire paragraphs, since text checki ng needs that much context.
1560 // Determine the character offset from the start of the paragraph to the sta rt of the original search range,
1561 // since we will want to ignore results in this area.
1562 RefPtr<Range> paragraphRange = searchRange->cloneRange(ec);
1563 setStart(paragraphRange.get(), startOfParagraph(searchRange->startPosition() ));
1564 int totalRangeLength = TextIterator::rangeLength(paragraphRange.get());
1565 setEnd(paragraphRange.get(), endOfParagraph(searchRange->startPosition()));
1566
1567 RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(e c)->document(), paragraphRange->startPosition(), searchRange->startPosition());
1568 int searchRangeStartOffset = TextIterator::rangeLength(offsetAsRange.get());
1569 int totalLengthProcessed = 0;
1570
1571 bool firstIteration = true;
1572 bool lastIteration = false;
1573 while (totalLengthProcessed < totalRangeLength) {
1574 // Iterate through the search range by paragraphs, checking each one for spelling and grammar.
1575 int currentLength = TextIterator::rangeLength(paragraphRange.get());
1576 int currentStartOffset = firstIteration ? searchRangeStartOffset : 0;
1577 int currentEndOffset = currentLength;
1578 if (inSameParagraph(paragraphRange->startPosition(), searchRange->endPos ition())) {
1579 // Determine the character offset from the end of the original searc h range to the end of the paragraph,
1580 // since we will want to ignore results in this area.
1581 RefPtr<Range> endOffsetAsRange = Range::create(paragraphRange->start Container(ec)->document(), paragraphRange->startPosition(), searchRange->endPosi tion());
1582 currentEndOffset = TextIterator::rangeLength(endOffsetAsRange.get()) ;
1583 lastIteration = true;
1584 }
1585 if (currentStartOffset < currentEndOffset) {
1586 String paragraphString = plainText(paragraphRange.get());
1587 if (paragraphString.length() > 0) {
1588 bool foundGrammar = false;
1589 int spellingLocation = 0;
1590 int grammarPhraseLocation = 0;
1591 int grammarDetailLocation = 0;
1592 unsigned grammarDetailIndex = 0;
1593
1594 Vector<TextCheckingResult> results;
1595 client->checkSpellingAndGrammarOfParagraph(paragraphString.chara cters(), paragraphString.length(), checkGrammar, results);
1596
1597 for (unsigned i = 0; i < results.size(); i++) {
1598 const TextCheckingResult* result = &results[i];
1599 if (result->resultType == 1 && result->location >= currentSt artOffset && result->location + result->length <= currentEndOffset) {
1600 ASSERT(result->length > 0 && result->location >= 0);
1601 spellingLocation = result->location;
1602 misspelledWord = paragraphString.substring(result->locat ion, result->length);
1603 ASSERT(misspelledWord.length() != 0);
1604 break;
1605 } else if (checkGrammar && result->resultType == 2 && result ->location < currentEndOffset && result->location + result->length > currentStar tOffset) {
1606 ASSERT(result->length > 0 && result->location >= 0);
1607 // We can't stop after the first grammar result, since t here might still be a spelling result after
1608 // it begins but before the first detail in it, but we c an stop if we find a second grammar result.
1609 if (foundGrammar) break;
1610 for (unsigned j = 0; j < result->details.size(); j++) {
1611 const GrammarDetail* detail = &result->details[j];
1612 ASSERT(detail->length > 0 && detail->location >= 0);
1613 if (result->location + detail->location >= currentSt artOffset && result->location + detail->location + detail->length <= currentEndO ffset && (!foundGrammar || result->location + detail->location < grammarDetailLo cation)) {
1614 grammarDetailIndex = j;
1615 grammarDetailLocation = result->location + detai l->location;
1616 foundGrammar = true;
1617 }
1618 }
1619 if (foundGrammar) {
1620 grammarPhraseLocation = result->location;
1621 outGrammarDetail = result->details[grammarDetailInde x];
1622 badGrammarPhrase = paragraphString.substring(result- >location, result->length);
1623 ASSERT(badGrammarPhrase.length() != 0);
1624 }
1625 }
1626 }
1627
1628 if (!misspelledWord.isEmpty() && (!checkGrammar || badGrammarPhr ase.isEmpty() || spellingLocation <= grammarDetailLocation)) {
1629 int spellingOffset = spellingLocation - currentStartOffset;
1630 if (!firstIteration) {
1631 RefPtr<Range> paragraphOffsetAsRange = Range::create(par agraphRange->startContainer(ec)->document(), searchRange->startPosition(), parag raphRange->startPosition());
1632 spellingOffset += TextIterator::rangeLength(paragraphOff setAsRange.get());
1633 }
1634 outIsSpelling = true;
1635 outFirstFoundOffset = spellingOffset;
1636 firstFoundItem = misspelledWord;
1637 break;
1638 } else if (checkGrammar && !badGrammarPhrase.isEmpty()) {
1639 int grammarPhraseOffset = grammarPhraseLocation - currentSta rtOffset;
1640 if (!firstIteration) {
1641 RefPtr<Range> paragraphOffsetAsRange = Range::create(par agraphRange->startContainer(ec)->document(), searchRange->startPosition(), parag raphRange->startPosition());
1642 grammarPhraseOffset += TextIterator::rangeLength(paragra phOffsetAsRange.get());
1643 }
1644 outIsSpelling = false;
1645 outFirstFoundOffset = grammarPhraseOffset;
1646 firstFoundItem = badGrammarPhrase;
1647 break;
1648 }
1649 }
1650 }
1651 if (lastIteration || totalLengthProcessed + currentLength >= totalRangeL ength)
1652 break;
1653 setStart(paragraphRange.get(), startOfNextParagraph(paragraphRange->endP osition()));
1654 setEnd(paragraphRange.get(), endOfParagraph(paragraphRange->startPositio n()));
1655 firstIteration = false;
1656 totalLengthProcessed += currentLength;
1657 }
1658 return firstFoundItem;
1659 }
1660
1661 #endif
1662
1554 void Editor::advanceToNextMisspelling(bool startBeforeSelection) 1663 void Editor::advanceToNextMisspelling(bool startBeforeSelection)
1555 { 1664 {
1556 ExceptionCode ec = 0; 1665 ExceptionCode ec = 0;
1557 1666
1558 // The basic approach is to search in two phases - from the selection end to the end of the doc, and 1667 // The basic approach is to search in two phases - from the selection end to the end of the doc, and
1559 // then we wrap and search from the doc start to (approximately) where we st arted. 1668 // then we wrap and search from the doc start to (approximately) where we st arted.
1560 1669
1561 // Start at the end of the selection, search to edge of document. Starting at the selection end makes 1670 // Start at the end of the selection, search to edge of document. Starting at the selection end makes
1562 // repeated "check spelling" commands work. 1671 // repeated "check spelling" commands work.
1563 VisibleSelection selection(frame()->selection()->selection()); 1672 VisibleSelection selection(frame()->selection()->selection());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1611 if (!client()) 1720 if (!client())
1612 return; 1721 return;
1613 1722
1614 // We go to the end of our first range instead of the start of it, just to b e sure 1723 // We go to the end of our first range instead of the start of it, just to b e sure
1615 // we don't get foiled by any word boundary problems at the start. It means we might 1724 // we don't get foiled by any word boundary problems at the start. It means we might
1616 // do a tiny bit more searching. 1725 // do a tiny bit more searching.
1617 Node *searchEndNodeAfterWrap = spellingSearchRange->endContainer(ec); 1726 Node *searchEndNodeAfterWrap = spellingSearchRange->endContainer(ec);
1618 int searchEndOffsetAfterWrap = spellingSearchRange->endOffset(ec); 1727 int searchEndOffsetAfterWrap = spellingSearchRange->endOffset(ec);
1619 1728
1620 int misspellingOffset; 1729 int misspellingOffset;
1730 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD )
1731 RefPtr<Range> grammarSearchRange = spellingSearchRange->cloneRange(ec);
1732 String misspelledWord;
1733 String badGrammarPhrase;
1734 int grammarPhraseOffset = 0;
1735 bool isSpelling = true;
1736 int foundOffset = 0;
1737 GrammarDetail grammarDetail;
1738 String foundItem = findFirstMisspellingOrBadGrammarInRange(client(), spellin gSearchRange.get(), isGrammarCheckingEnabled(), isSpelling, foundOffset, grammar Detail);
1739 if (isSpelling) {
1740 misspelledWord = foundItem;
1741 misspellingOffset = foundOffset;
1742 } else {
1743 badGrammarPhrase = foundItem;
1744 grammarPhraseOffset = foundOffset;
1745 }
1746 #else
1621 String misspelledWord = findFirstMisspellingInRange(client(), spellingSearch Range.get(), misspellingOffset, false); 1747 String misspelledWord = findFirstMisspellingInRange(client(), spellingSearch Range.get(), misspellingOffset, false);
1622 1748
1623 String badGrammarPhrase; 1749 String badGrammarPhrase;
1624 1750
1625 #ifndef BUILDING_ON_TIGER 1751 #ifndef BUILDING_ON_TIGER
1626 int grammarPhraseOffset = 0; 1752 int grammarPhraseOffset = 0;
1627 GrammarDetail grammarDetail; 1753 GrammarDetail grammarDetail;
1628 1754
1629 // Search for bad grammar that occurs prior to the next misspelled word (if any) 1755 // Search for bad grammar that occurs prior to the next misspelled word (if any)
1630 RefPtr<Range> grammarSearchRange = spellingSearchRange->cloneRange(ec); 1756 RefPtr<Range> grammarSearchRange = spellingSearchRange->cloneRange(ec);
1631 if (!misspelledWord.isEmpty()) { 1757 if (!misspelledWord.isEmpty()) {
1632 // Stop looking at start of next misspelled word 1758 // Stop looking at start of next misspelled word
1633 CharacterIterator chars(grammarSearchRange.get()); 1759 CharacterIterator chars(grammarSearchRange.get());
1634 chars.advance(misspellingOffset); 1760 chars.advance(misspellingOffset);
1635 grammarSearchRange->setEnd(chars.range()->startContainer(ec), chars.rang e()->startOffset(ec), ec); 1761 grammarSearchRange->setEnd(chars.range()->startContainer(ec), chars.rang e()->startOffset(ec), ec);
1636 } 1762 }
1637 1763
1638 if (isGrammarCheckingEnabled()) 1764 if (isGrammarCheckingEnabled())
1639 badGrammarPhrase = findFirstBadGrammarInRange(client(), grammarSearchRan ge.get(), grammarDetail, grammarPhraseOffset, false); 1765 badGrammarPhrase = findFirstBadGrammarInRange(client(), grammarSearchRan ge.get(), grammarDetail, grammarPhraseOffset, false);
1640 #endif 1766 #endif
1767 #endif
1641 1768
1642 // If we found neither bad grammar nor a misspelled word, wrap and try again (but don't bother if we started at the beginning of the 1769 // If we found neither bad grammar nor a misspelled word, wrap and try again (but don't bother if we started at the beginning of the
1643 // block rather than at a selection). 1770 // block rather than at a selection).
1644 if (startedWithSelection && !misspelledWord && !badGrammarPhrase) { 1771 if (startedWithSelection && !misspelledWord && !badGrammarPhrase) {
1645 spellingSearchRange->setStart(topNode, 0, ec); 1772 spellingSearchRange->setStart(topNode, 0, ec);
1646 // going until the end of the very first chunk we tested is far enough 1773 // going until the end of the very first chunk we tested is far enough
1647 spellingSearchRange->setEnd(searchEndNodeAfterWrap, searchEndOffsetAfter Wrap, ec); 1774 spellingSearchRange->setEnd(searchEndNodeAfterWrap, searchEndOffsetAfter Wrap, ec);
1648 1775
1776 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD )
1777 grammarSearchRange = spellingSearchRange->cloneRange(ec);
1778 foundItem = findFirstMisspellingOrBadGrammarInRange(client(), spellingSe archRange.get(), isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDet ail);
1779 if (isSpelling) {
1780 misspelledWord = foundItem;
1781 misspellingOffset = foundOffset;
1782 } else {
1783 badGrammarPhrase = foundItem;
1784 grammarPhraseOffset = foundOffset;
1785 }
1786 #else
1649 misspelledWord = findFirstMisspellingInRange(client(), spellingSearchRan ge.get(), misspellingOffset, false); 1787 misspelledWord = findFirstMisspellingInRange(client(), spellingSearchRan ge.get(), misspellingOffset, false);
1650 1788
1651 #ifndef BUILDING_ON_TIGER 1789 #ifndef BUILDING_ON_TIGER
1652 grammarSearchRange = spellingSearchRange->cloneRange(ec); 1790 grammarSearchRange = spellingSearchRange->cloneRange(ec);
1653 if (!misspelledWord.isEmpty()) { 1791 if (!misspelledWord.isEmpty()) {
1654 // Stop looking at start of next misspelled word 1792 // Stop looking at start of next misspelled word
1655 CharacterIterator chars(grammarSearchRange.get()); 1793 CharacterIterator chars(grammarSearchRange.get());
1656 chars.advance(misspellingOffset); 1794 chars.advance(misspellingOffset);
1657 grammarSearchRange->setEnd(chars.range()->startContainer(ec), chars. range()->startOffset(ec), ec); 1795 grammarSearchRange->setEnd(chars.range()->startContainer(ec), chars. range()->startOffset(ec), ec);
1658 } 1796 }
1659 if (isGrammarCheckingEnabled()) 1797 if (isGrammarCheckingEnabled())
1660 badGrammarPhrase = findFirstBadGrammarInRange(client(), grammarSearc hRange.get(), grammarDetail, grammarPhraseOffset, false); 1798 badGrammarPhrase = findFirstBadGrammarInRange(client(), grammarSearc hRange.get(), grammarDetail, grammarPhraseOffset, false);
1661 #endif 1799 #endif
1800 #endif
1662 } 1801 }
1663 1802
1664 if (!badGrammarPhrase.isEmpty()) { 1803 if (!badGrammarPhrase.isEmpty()) {
1665 #ifdef BUILDING_ON_TIGER 1804 #ifdef BUILDING_ON_TIGER
1666 ASSERT_NOT_REACHED(); 1805 ASSERT_NOT_REACHED();
1667 #else 1806 #else
1668 // We found bad grammar. Since we only searched for bad grammar up to th e first misspelled word, the bad grammar 1807 // We found bad grammar. Since we only searched for bad grammar up to th e first misspelled word, the bad grammar
1669 // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling 1808 // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling
1670 // panel, and store a marker so we draw the green squiggle later. 1809 // panel, and store a marker so we draw the green squiggle later.
1671 1810
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1793 { 1932 {
1794 String selectedString = frame()->selectedText(); 1933 String selectedString = frame()->selectedText();
1795 ASSERT(selectedString.length() != 0); 1934 ASSERT(selectedString.length() != 0);
1796 1935
1797 Vector<String> guesses; 1936 Vector<String> guesses;
1798 if (client()) 1937 if (client())
1799 client()->getGuessesForWord(selectedString, guesses); 1938 client()->getGuessesForWord(selectedString, guesses);
1800 return guesses; 1939 return guesses;
1801 } 1940 }
1802 1941
1942 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD )
1943
1944 static Vector<String> guessesForMisspelledOrUngrammaticalRange(EditorClient* cli ent, Range *range, bool checkGrammar, bool& misspelled, bool& ungrammatical)
1945 {
1946 Vector<String> guesses;
1947 ExceptionCode ec;
1948 misspelled = false;
1949 ungrammatical = false;
1950
1951 if (!client || !range || range->collapsed(ec))
1952 return guesses;
1953
1954 // Expand the range to encompass entire paragraphs, since text checking need s that much context.
1955 int rangeStartOffset;
1956 String paragraphString;
1957 RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(range, rangeSta rtOffset, paragraphString);
1958 int rangeLength = TextIterator::rangeLength(range);
1959 if (rangeLength == 0 || paragraphString.length() == 0)
1960 return guesses;
1961
1962 Vector<TextCheckingResult> results;
1963 client->checkSpellingAndGrammarOfParagraph(paragraphString.characters(), par agraphString.length(), checkGrammar, results);
1964
1965 for (unsigned i = 0; i < results.size(); i++) {
1966 const TextCheckingResult* result = &results[i];
1967 if (result->resultType == 1 && result->location == rangeStartOffset && r esult->length == rangeLength) {
1968 String misspelledWord = paragraphString.substring(rangeStartOffset, rangeLength);
1969 ASSERT(misspelledWord.length() != 0);
1970 client->getGuessesForWord(misspelledWord, guesses);
1971 client->updateSpellingUIWithMisspelledWord(misspelledWord);
1972 misspelled = true;
1973 return guesses;
1974 }
1975 }
1976
1977 if (!checkGrammar)
1978 return guesses;
1979
1980 for (unsigned i = 0; i < results.size(); i++) {
1981 const TextCheckingResult* result = &results[i];
1982 if (result->resultType == 2 && result->location <= rangeStartOffset && r esult->location + result->length >= rangeStartOffset + rangeLength) {
1983 for (unsigned j = 0; j < result->details.size(); j++) {
1984 const GrammarDetail* detail = &result->details[j];
1985 ASSERT(detail->length > 0 && detail->location >= 0);
1986 if (result->location + detail->location == rangeStartOffset && d etail->length == rangeLength) {
1987 String badGrammarPhrase = paragraphString.substring(result-> location, result->length);
1988 ASSERT(badGrammarPhrase.length() != 0);
1989 for (unsigned k = 0; k < detail->guesses.size(); k++)
1990 guesses.append(detail->guesses[k]);
1991 client->updateSpellingUIWithGrammarString(badGrammarPhrase, *detail);
1992 ungrammatical = true;
1993 return guesses;
1994 }
1995 }
1996 }
1997 }
1998 return guesses;
1999 }
2000
2001 #endif
2002
2003 Vector<String> Editor::guessesForMisspelledOrUngrammaticalSelection(bool& misspe lled, bool& ungrammatical)
2004 {
2005 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD )
2006 return guessesForMisspelledOrUngrammaticalRange(client(), frame()->selection ()->toNormalizedRange().get(), isGrammarCheckingEnabled(), misspelled, ungrammat ical);
2007 #else
2008 misspelled = isSelectionMisspelled();
2009 if (misspelled) {
2010 ungrammatical = false;
2011 return guessesForMisspelledSelection();
2012 }
2013 if (isGrammarCheckingEnabled() && isSelectionUngrammatical()) {
2014 ungrammatical = true;
2015 return guessesForUngrammaticalSelection();
2016 }
2017 ungrammatical = false;
2018 return Vector<String>();
2019 #endif
2020 }
2021
1803 void Editor::showSpellingGuessPanel() 2022 void Editor::showSpellingGuessPanel()
1804 { 2023 {
1805 if (!client()) { 2024 if (!client()) {
1806 LOG_ERROR("No NSSpellChecker"); 2025 LOG_ERROR("No NSSpellChecker");
1807 return; 2026 return;
1808 } 2027 }
1809 2028
1810 #ifndef BUILDING_ON_TIGER 2029 #ifndef BUILDING_ON_TIGER
1811 // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone 2030 // Post-Tiger, this menu item is a show/hide toggle, to match AppKit. Leave Tiger behavior alone
1812 // to match rest of OS X. 2031 // to match rest of OS X.
(...skipping 12 matching lines...) Expand all
1825 if (!client()) 2044 if (!client())
1826 return false; 2045 return false;
1827 return client()->spellingUIIsShowing(); 2046 return client()->spellingUIIsShowing();
1828 } 2047 }
1829 2048
1830 void Editor::markMisspellingsAfterTypingToPosition(const VisiblePosition &p) 2049 void Editor::markMisspellingsAfterTypingToPosition(const VisiblePosition &p)
1831 { 2050 {
1832 if (!isContinuousSpellCheckingEnabled()) 2051 if (!isContinuousSpellCheckingEnabled())
1833 return; 2052 return;
1834 2053
2054 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD )
2055 VisibleSelection adjacentWords = VisibleSelection(startOfWord(p, LeftWordIfO nBoundary), endOfWord(p, RightWordIfOnBoundary));
2056 if (isGrammarCheckingEnabled()) {
2057 VisibleSelection selectedSentence = VisibleSelection(startOfSentence(p), endOfSentence(p));
2058 markMisspellingsAndBadGrammar(adjacentWords, true, selectedSentence);
2059 } else {
2060 markMisspellingsAndBadGrammar(adjacentWords, false, adjacentWords);
2061 }
2062 #else
1835 // Check spelling of one word 2063 // Check spelling of one word
1836 markMisspellings(VisibleSelection(startOfWord(p, LeftWordIfOnBoundary), endO fWord(p, RightWordIfOnBoundary))); 2064 markMisspellings(VisibleSelection(startOfWord(p, LeftWordIfOnBoundary), endO fWord(p, RightWordIfOnBoundary)));
1837 2065
1838 if (!isGrammarCheckingEnabled()) 2066 if (!isGrammarCheckingEnabled())
1839 return; 2067 return;
1840 2068
1841 // Check grammar of entire sentence 2069 // Check grammar of entire sentence
1842 markBadGrammar(VisibleSelection(startOfSentence(p), endOfSentence(p))); 2070 markBadGrammar(VisibleSelection(startOfSentence(p), endOfSentence(p)));
2071 #endif
1843 } 2072 }
1844 2073
1845 static void markAllMisspellingsInRange(EditorClient* client, Range* searchRange) 2074 static void markAllMisspellingsInRange(EditorClient* client, Range* searchRange)
1846 { 2075 {
1847 // Use the "markAll" feature of findFirstMisspellingInRange. Ignore the retu rn value and the "out parameter"; 2076 // Use the "markAll" feature of findFirstMisspellingInRange. Ignore the retu rn value and the "out parameter";
1848 // all we need to do is mark every instance. 2077 // all we need to do is mark every instance.
1849 int ignoredOffset; 2078 int ignoredOffset;
1850 findFirstMisspellingInRange(client, searchRange, ignoredOffset, true); 2079 findFirstMisspellingInRange(client, searchRange, ignoredOffset, true);
1851 } 2080 }
1852 2081
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1903 2132
1904 void Editor::markBadGrammar(const VisibleSelection& selection) 2133 void Editor::markBadGrammar(const VisibleSelection& selection)
1905 { 2134 {
1906 #ifndef BUILDING_ON_TIGER 2135 #ifndef BUILDING_ON_TIGER
1907 markMisspellingsOrBadGrammar(this, selection, false); 2136 markMisspellingsOrBadGrammar(this, selection, false);
1908 #else 2137 #else
1909 UNUSED_PARAM(selection); 2138 UNUSED_PARAM(selection);
1910 #endif 2139 #endif
1911 } 2140 }
1912 2141
2142 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD )
2143
2144 static void markAllMisspellingsAndBadGrammarInRanges(EditorClient* client, Range *spellingRange, bool markGrammar, Range *grammarRange)
2145 {
2146 // This function is called with selections already expanded to word boundari es.
2147 ExceptionCode ec;
2148 if (!client || !spellingRange || (markGrammar && !grammarRange))
2149 return;
2150
2151 // If we're not in an editable node, bail.
2152 Node* editableNode = spellingRange->startContainer();
2153 if (!editableNode || !editableNode->isContentEditable())
2154 return;
2155
2156 // Expand the range to encompass entire paragraphs, since text checking need s that much context.
2157 int spellingRangeStartOffset;
2158 int spellingRangeEndOffset;
2159 int grammarRangeStartOffset;
2160 int grammarRangeEndOffset;
2161 String paragraphString;
2162
2163 if (markGrammar) {
2164 // The spelling range should be contained in the paragraph-aligned exten sion of the grammar range.
2165 RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(grammarRang e, grammarRangeStartOffset, paragraphString);
2166 RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContain er(ec)->document(), paragraphRange->startPosition(), spellingRange->startPositio n());
2167 spellingRangeStartOffset = TextIterator::rangeLength(offsetAsRange.get() );
2168 grammarRangeEndOffset = grammarRangeStartOffset + TextIterator::rangeLen gth(grammarRange);
2169 } else {
2170 RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(spellingRan ge, spellingRangeStartOffset, paragraphString);
2171 }
2172 spellingRangeEndOffset = spellingRangeStartOffset + TextIterator::rangeLengt h(spellingRange);
2173 if (paragraphString.length() == 0 || (spellingRangeStartOffset >= spellingRa ngeEndOffset && (!markGrammar || grammarRangeStartOffset >= grammarRangeEndOffse t)))
2174 return;
2175
2176 Vector<TextCheckingResult> results;
2177 client->checkSpellingAndGrammarOfParagraph(paragraphString.characters(), par agraphString.length(), markGrammar, results);
2178
2179 for (unsigned i = 0; i < results.size(); i++) {
2180 const TextCheckingResult* result = &results[i];
2181 if (result->resultType == 1 && result->location >= spellingRangeStartOff set && result->location + result->length <= spellingRangeEndOffset) {
2182 ASSERT(result->length > 0 && result->location >= 0);
2183 RefPtr<Range> misspellingRange = TextIterator::subrange(spellingRang e, result->location - spellingRangeStartOffset, result->length);
2184 misspellingRange->startContainer(ec)->document()->addMarker(misspell ingRange.get(), DocumentMarker::Spelling);
2185 } else if (markGrammar && result->resultType == 2 && result->location < grammarRangeEndOffset && result->location + result->length > grammarRangeStartOf fset) {
2186 ASSERT(result->length > 0 && result->location >= 0);
2187 for (unsigned j = 0; j < result->details.size(); j++) {
2188 const GrammarDetail* detail = &result->details[j];
2189 ASSERT(detail->length > 0 && detail->location >= 0);
2190 if (result->location + detail->location >= grammarRangeStartOffs et && result->location + detail->location + detail->length <= grammarRangeEndOff set) {
2191 RefPtr<Range> badGrammarRange = TextIterator::subrange(gramm arRange, result->location + detail->location - grammarRangeStartOffset, detail-> length);
2192 grammarRange->startContainer(ec)->document()->addMarker(badG rammarRange.get(), DocumentMarker::Grammar, detail->userDescription);
2193 }
2194 }
2195 }
2196 }
2197 }
2198
2199 #endif
2200
2201 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelec tion, bool markGrammar, const VisibleSelection& grammarSelection)
2202 {
2203 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD )
2204 if (!isContinuousSpellCheckingEnabled())
2205 return;
2206 markAllMisspellingsAndBadGrammarInRanges(client(), spellingSelection.toNorma lizedRange().get(), markGrammar && isGrammarCheckingEnabled(), grammarSelection. toNormalizedRange().get());
2207 #else
2208 markMisspellings(spellingSelection);
2209 if (markGrammar)
2210 markBadGrammar(grammarSelection);
2211 #endif
2212 }
2213
1913 PassRefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint) 2214 PassRefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
1914 { 2215 {
1915 Document* document = m_frame->documentAtPoint(windowPoint); 2216 Document* document = m_frame->documentAtPoint(windowPoint);
1916 if (!document) 2217 if (!document)
1917 return 0; 2218 return 0;
1918 2219
1919 Frame* frame = document->frame(); 2220 Frame* frame = document->frame();
1920 ASSERT(frame); 2221 ASSERT(frame);
1921 FrameView* frameView = frame->view(); 2222 FrameView* frameView = frame->view();
1922 if (!frameView) 2223 if (!frameView)
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
2182 2483
2183 if (!wrapFlag) 2484 if (!wrapFlag)
2184 return Range::create(m_frame->document()); 2485 return Range::create(m_frame->document());
2185 2486
2186 if (forward) 2487 if (forward)
2187 return firstVisibleRange(target, caseFlag); 2488 return firstVisibleRange(target, caseFlag);
2188 2489
2189 return lastVisibleRange(target, caseFlag); 2490 return lastVisibleRange(target, caseFlag);
2190 } 2491 }
2191 2492
2493 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, b ool closeTyping, bool clearTypingStyle, EditCommand* cmd)
2494 {
2495 // If there is no selection change, don't bother sending shouldChangeSelecti on, but still call setSelection,
2496 // because there is work that it must do in this situation.
2497 // The old selection can be invalid here and calling shouldChangeSelection c an produce some strange calls.
2498 // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ra nges for selections that are no longer valid
2499 bool selectionDidNotChangeDOMPosition = newSelection == m_frame->selection() ->selection();
2500 if (selectionDidNotChangeDOMPosition || m_frame->shouldChangeSelection(newSe lection))
2501 m_frame->selection()->setSelection(newSelection, closeTyping, clearTypin gStyle);
2502
2503 // Some kinds of deletes and line break insertions change the selection's po sition within the document without
2504 // changing its position within the DOM. For example when you press return in the following (the caret is marked by ^):
2505 // <div contentEditable="true"><div>^Hello</div></div>
2506 // WebCore inserts <div><br></div> *before* the current block, which correct ly moves the paragraph down but which doesn't
2507 // change the caret's DOM position (["hello", 0]). In these situations the above SelectionController::setSelection call
2508 // does not call EditorClient::respondToChangedSelection(), which, on the Ma c, sends selection change notifications and
2509 // starts a new kill ring sequence, but we want to do these things (matches AppKit).
2510 if (selectionDidNotChangeDOMPosition && cmd->isTypingCommand())
2511 client()->respondToChangedSelection();
2512 }
2513
2192 } // namespace WebCore 2514 } // namespace WebCore
2193
2194
2195
2196
OLDNEW
« no previous file with comments | « third_party/WebKit/WebCore/editing/Editor.h ('k') | third_party/WebKit/WebCore/editing/TypingCommand.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698