⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 editor.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                ASSERT(ec == 0);            }        }                currentChunkOffset += len;        it.advance();    }        return firstMisspelling;}#ifndef BUILDING_ON_TIGERstatic PassRefPtr<Range> paragraphAlignedRangeForRange(Range* arbitraryRange, int& offsetIntoParagraphAlignedRange, String& paragraphString){    ASSERT_ARG(arbitraryRange, arbitraryRange);        ExceptionCode ec = 0;        // Expand range to paragraph boundaries    RefPtr<Range> paragraphRange = arbitraryRange->cloneRange(ec);    setStart(paragraphRange.get(), startOfParagraph(arbitraryRange->startPosition()));    setEnd(paragraphRange.get(), endOfParagraph(arbitraryRange->endPosition()));        // Compute offset from start of expanded range to start of original range    RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), arbitraryRange->startPosition());    offsetIntoParagraphAlignedRange = TextIterator::rangeLength(offsetAsRange.get());        // Fill in out parameter with string representing entire paragraph range.    // Someday we might have a caller that doesn't use this, but for now all callers do.    paragraphString = plainText(paragraphRange.get());    return paragraphRange;}static int findFirstGrammarDetailInRange(const Vector<GrammarDetail>& grammarDetails, int badGrammarPhraseLocation, int /*badGrammarPhraseLength*/, Range *searchRange, int startOffset, int endOffset, bool markAll){    // Found some bad grammar. Find the earliest detail range that starts in our search range (if any).    // Optionally add a DocumentMarker for each detail in the range.    int earliestDetailLocationSoFar = -1;    int earliestDetailIndex = -1;    for (unsigned i = 0; i < grammarDetails.size(); i++) {        const GrammarDetail* detail = &grammarDetails[i];        ASSERT(detail->length > 0 && detail->location >= 0);                int detailStartOffsetInParagraph = badGrammarPhraseLocation + detail->location;                // Skip this detail if it starts before the original search range        if (detailStartOffsetInParagraph < startOffset)            continue;                // Skip this detail if it starts after the original search range        if (detailStartOffsetInParagraph >= endOffset)            continue;                if (markAll) {            RefPtr<Range> badGrammarRange = TextIterator::subrange(searchRange, badGrammarPhraseLocation - startOffset + detail->location, detail->length);            ExceptionCode ec = 0;            badGrammarRange->startContainer(ec)->document()->addMarker(badGrammarRange.get(), DocumentMarker::Grammar, detail->userDescription);            ASSERT(ec == 0);        }                // Remember this detail only if it's earlier than our current candidate (the details aren't in a guaranteed order)        if (earliestDetailIndex < 0 || earliestDetailLocationSoFar > detail->location) {            earliestDetailIndex = i;            earliestDetailLocationSoFar = detail->location;        }    }        return earliestDetailIndex;}    static String findFirstBadGrammarInRange(EditorClient* client, Range* searchRange, GrammarDetail& outGrammarDetail, int& outGrammarPhraseOffset, bool markAll){    ASSERT_ARG(client, client);    ASSERT_ARG(searchRange, searchRange);        // Initialize out parameters; these will be updated if we find something to return.    outGrammarDetail.location = -1;    outGrammarDetail.length = 0;    outGrammarDetail.guesses.clear();    outGrammarDetail.userDescription = "";    outGrammarPhraseOffset = 0;        String firstBadGrammarPhrase;    // Expand the search range to encompass entire paragraphs, since grammar checking needs that much context.    // Determine the character offset from the start of the paragraph to the start of the original search range,    // since we will want to ignore results in this area.    int searchRangeStartOffset;    String paragraphString;    RefPtr<Range> paragraphRange = paragraphAlignedRangeForRange(searchRange, searchRangeStartOffset, paragraphString);            // Determine the character offset from the start of the paragraph to the end of the original search range,     // since we will want to ignore results in this area also.    int searchRangeEndOffset = searchRangeStartOffset + TextIterator::rangeLength(searchRange);            // Start checking from beginning of paragraph, but skip past results that occur before the start of the original search range.    int startOffset = 0;    while (startOffset < searchRangeEndOffset) {        Vector<GrammarDetail> grammarDetails;        int badGrammarPhraseLocation = -1;        int badGrammarPhraseLength = 0;        client->checkGrammarOfString(paragraphString.characters() + startOffset, paragraphString.length() - startOffset, grammarDetails, &badGrammarPhraseLocation, &badGrammarPhraseLength);                if (badGrammarPhraseLength == 0) {            ASSERT(badGrammarPhraseLocation == -1);            return String();        }        ASSERT(badGrammarPhraseLocation >= 0);        badGrammarPhraseLocation += startOffset;                // Found some bad grammar. Find the earliest detail range that starts in our search range (if any).        int badGrammarIndex = findFirstGrammarDetailInRange(grammarDetails, badGrammarPhraseLocation, badGrammarPhraseLength, searchRange, searchRangeStartOffset, searchRangeEndOffset, markAll);        if (badGrammarIndex >= 0) {            ASSERT(static_cast<unsigned>(badGrammarIndex) < grammarDetails.size());            outGrammarDetail = grammarDetails[badGrammarIndex];        }        // If we found a detail in range, then we have found the first bad phrase (unless we found one earlier but        // kept going so we could mark all instances).        if (badGrammarIndex >= 0 && firstBadGrammarPhrase.isEmpty()) {            outGrammarPhraseOffset = badGrammarPhraseLocation - searchRangeStartOffset;            firstBadGrammarPhrase = paragraphString.substring(badGrammarPhraseLocation, badGrammarPhraseLength);                        // Found one. We're done now, unless we're marking each instance.            if (!markAll)                break;        }        // These results were all between the start of the paragraph and the start of the search range; look        // beyond this phrase.        startOffset = badGrammarPhraseLocation + badGrammarPhraseLength;    }        return firstBadGrammarPhrase;}    #endif /* not BUILDING_ON_TIGER */#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)static String findFirstMisspellingOrBadGrammarInRange(EditorClient* client, Range* searchRange, bool checkGrammar, bool& outIsSpelling, int& outFirstFoundOffset, GrammarDetail& outGrammarDetail){    ASSERT_ARG(client, client);    ASSERT_ARG(searchRange, searchRange);        String firstFoundItem;    String misspelledWord;    String badGrammarPhrase;    ExceptionCode ec = 0;        // Initialize out parameters; these will be updated if we find something to return.    outIsSpelling = true;    outFirstFoundOffset = 0;    outGrammarDetail.location = -1;    outGrammarDetail.length = 0;    outGrammarDetail.guesses.clear();    outGrammarDetail.userDescription = "";        // Expand the search range to encompass entire paragraphs, since text checking needs that much context.    // Determine the character offset from the start of the paragraph to the start of the original search range,    // since we will want to ignore results in this area.    RefPtr<Range> paragraphRange = searchRange->cloneRange(ec);    setStart(paragraphRange.get(), startOfParagraph(searchRange->startPosition()));    int totalRangeLength = TextIterator::rangeLength(paragraphRange.get());    setEnd(paragraphRange.get(), endOfParagraph(searchRange->startPosition()));        RefPtr<Range> offsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), searchRange->startPosition());    int searchRangeStartOffset = TextIterator::rangeLength(offsetAsRange.get());    int totalLengthProcessed = 0;        bool firstIteration = true;    bool lastIteration = false;    while (totalLengthProcessed < totalRangeLength) {        // Iterate through the search range by paragraphs, checking each one for spelling and grammar.        int currentLength = TextIterator::rangeLength(paragraphRange.get());        int currentStartOffset = firstIteration ? searchRangeStartOffset : 0;        int currentEndOffset = currentLength;        if (inSameParagraph(paragraphRange->startPosition(), searchRange->endPosition())) {            // Determine the character offset from the end of the original search range to the end of the paragraph,            // since we will want to ignore results in this area.            RefPtr<Range> endOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), paragraphRange->startPosition(), searchRange->endPosition());            currentEndOffset = TextIterator::rangeLength(endOffsetAsRange.get());            lastIteration = true;        }        if (currentStartOffset < currentEndOffset) {            String paragraphString = plainText(paragraphRange.get());            if (paragraphString.length() > 0) {                bool foundGrammar = false;                int spellingLocation = 0;                int grammarPhraseLocation = 0;                int grammarDetailLocation = 0;                unsigned grammarDetailIndex = 0;                                Vector<TextCheckingResult> results;                client->checkSpellingAndGrammarOfParagraph(paragraphString.characters(), paragraphString.length(), checkGrammar, results);                                for (unsigned i = 0; i < results.size(); i++) {                    const TextCheckingResult* result = &results[i];                    if (result->resultType == 1 && result->location >= currentStartOffset && result->location + result->length <= currentEndOffset) {                        ASSERT(result->length > 0 && result->location >= 0);                        spellingLocation = result->location;                        misspelledWord = paragraphString.substring(result->location, result->length);                        ASSERT(misspelledWord.length() != 0);                        break;                    } else if (checkGrammar && result->resultType == 2 && result->location < currentEndOffset && result->location + result->length > currentStartOffset) {                        ASSERT(result->length > 0 && result->location >= 0);                        // We can't stop after the first grammar result, since there might still be a spelling result after                        // it begins but before the first detail in it, but we can stop if we find a second grammar result.                        if (foundGrammar) break;                        for (unsigned j = 0; j < result->details.size(); j++) {                            const GrammarDetail* detail = &result->details[j];                            ASSERT(detail->length > 0 && detail->location >= 0);                            if (result->location + detail->location >= currentStartOffset && result->location + detail->location + detail->length <= currentEndOffset && (!foundGrammar || result->location + detail->location < grammarDetailLocation)) {                                grammarDetailIndex = j;                                grammarDetailLocation = result->location + detail->location;                                foundGrammar = true;                            }                        }                        if (foundGrammar) {                            grammarPhraseLocation = result->location;                            outGrammarDetail = result->details[grammarDetailIndex];                            badGrammarPhrase = paragraphString.substring(result->location, result->length);                            ASSERT(badGrammarPhrase.length() != 0);                        }                    }                }                if (!misspelledWord.isEmpty() && (!checkGrammar || badGrammarPhrase.isEmpty() || spellingLocation <= grammarDetailLocation)) {                    int spellingOffset = spellingLocation - currentStartOffset;                    if (!firstIteration) {                        RefPtr<Range> paragraphOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), searchRange->startPosition(), paragraphRange->startPosition());                        spellingOffset += TextIterator::rangeLength(paragraphOffsetAsRange.get());                    }                    outIsSpelling = true;                    outFirstFoundOffset = spellingOffset;                    firstFoundItem = misspelledWord;                    break;                } else if (checkGrammar && !badGrammarPhrase.isEmpty()) {                    int grammarPhraseOffset = grammarPhraseLocation - currentStartOffset;                    if (!firstIteration) {                        RefPtr<Range> paragraphOffsetAsRange = Range::create(paragraphRange->startContainer(ec)->document(), searchRange->startPosition(), paragraphRange->startPosition());                        grammarPhraseOffset += TextIterator::rangeLength(paragraphOffsetAsRange.get());                    }                    outIsSpelling = false;                    outFirstFoundOffset = grammarPhraseOffset;                    firstFoundItem = badGrammarPhrase;                    break;                }            }        }        if (lastIteration || totalLengthProcessed + currentLength >= totalRangeLength)            break;        setStart(paragraphRange.get(), startOfNextParagraph(paragraphRange->endPosition()));        setEnd(paragraphRange.get(), endOfParagraph(paragraphRange->startPosition()));        firstIteration = false;        totalLengthProcessed += currentLength;    }    return firstFoundItem;}#endifvoid Editor::advanceToNextMisspelling(bool startBeforeSelection){    ExceptionCode ec = 0;    // The basic approach is to search in two phases - from the selection end to the end of the doc, and    // then we wrap and search from the doc start to (approximately) where we started.        // Start at the end of the selection, search to edge of document.  Starting at the selection end makes    // repeated "check spelling" commands work.    VisibleSelection selection(frame()->selection()->selection());    RefPtr<Range> spellingSearchRange(rangeOfContents(frame()->document()));    bool startedWithSelection = false;    if (selection.start().node()) {        startedWithSelection = true;        if (startBeforeSelection) {            VisiblePosition start(selection.visibleStart());            // We match AppKit's rule: Start 1 character before the selection.            VisiblePosition oneBeforeStart = start.previous();            setStart(spellingSearchRange.get(), oneBeforeStart.isNotNull() ? oneBeforeStart : start);        } else            setStart(spellingSearchRange.get(), selection.visibleEnd());    }    Position position = spellingSearchRange->startPosition();    if (!isEditablePosition(position)) {        // This shouldn't happen in very often because the Spelling menu items aren't enabled unless the        // selection is editable.        // This can happen in Mail for a mix of non-editable and editable content (like Stationary),         // when spell checking the whole document before sending the message.        // In that case the document might not be editable, but there are editable pockets that need to be spell checked.        position = firstEditablePositionAfterPositionInRoot(position, frame()->document()->documentElement()).deepEquivalent();        if (position.isNull())            return;                Position rangeCompliantPosition = rangeCompliantEquivalent(position);        spellingSearchRange->setStart(rangeCompliantPosition.node(), rangeCompliantPosition.offset(), ec);        startedWithSelection = false;   // won't need to wrap    }        // topNode defines the whole range we want to operate on     Node* topNode = highestEditableRoot(position);    spellingSearchRange->setEnd(topNode, maxDeepOffset(topNode), ec);    // If spellingSearchRange starts in the middle of a word, advance to the next word so we start checking    // at a word boundary. Going back by one char and then forward by a word does the trick.    if (startedWithSelection) {        VisiblePosition oneBeforeStart = startVisiblePosition(spellingSearchRange.get(), DOWNSTREAM).previous();        if (oneBeforeStart.isNotNull()) {            setStart(spellingSearchRange.get(), endOfWord(oneBeforeStart));        } // else we were already at the start of the editable node    }        if (spellingSearchRange->collapsed(ec))        return;       // nothing to search in        // Get the spell checker if it is available    if (!client())        return;            // We go to the end of our first range instead of the start of it, just to be sure    // we don't get foiled by any word boundary problems at the start.  It means we might    // do a tiny bit more searching.    Node *searchEndNodeAfterWrap = spellingSearchRange->endContainer(ec);    int searchEndOffsetAfterWrap = spellingSearchRange->endOffset(ec);        int misspellingOffset = 0;#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)    RefPtr<Range> grammarSearchRange = spellingSearchRange->cloneRange(ec);    String misspelledWord;    String badGrammarPhrase;    int grammarPhraseOffset = 0;    bool isSpelling = true;    int foundOffset = 0;    GrammarDetail grammarDetail;    String foundItem = findFirstMisspellingOrBadGrammarInRange(client(), spellingSearchRange.get(), isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);    if (isSpelling) {        misspelledWord = foundItem;        misspellingOffset = foundOffset;    } else {        badGrammarPhrase = foundItem;        grammarPhraseOffset = foundOffset

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -