diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp')
-rw-r--r-- | Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp | 260 |
1 files changed, 216 insertions, 44 deletions
diff --git a/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp b/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp index 6bc419079..2513cbd69 100644 --- a/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2010 Apple Inc. All rights reserved. * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. + * Copyright (C) 2011-2013 Samsung Electronics * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,119 +29,290 @@ #include "TextChecker.h" #include "TextCheckerState.h" -#include "WebTextChecker.h" +#include "WebProcessPool.h" #include <WebCore/NotImplemented.h> +#include <WebCore/TextCheckerEnchant.h> +#include <unicode/ubrk.h> +#include <wtf/NeverDestroyed.h> +#include <wtf/text/TextBreakIterator.h> using namespace WebCore; - + namespace WebKit { -static TextCheckerState textCheckerState; +#if ENABLE(SPELLCHECK) +static WebCore::TextCheckerEnchant& enchantTextChecker() +{ + static NeverDestroyed<WebCore::TextCheckerEnchant> checker; + return checker; +} +#endif -const TextCheckerState& TextChecker::state() +TextCheckerState& checkerState() { - static bool didInitializeState = false; - if (didInitializeState) - return textCheckerState; + static TextCheckerState textCheckerState; + static std::once_flag onceFlag; + std::call_once(onceFlag, [] { + textCheckerState.isContinuousSpellCheckingEnabled = false; + textCheckerState.isGrammarCheckingEnabled = false; + }); + + return textCheckerState; +} - WebTextCheckerClient& client = WebTextChecker::shared()->client(); - textCheckerState.isContinuousSpellCheckingEnabled = client.continuousSpellCheckingEnabled(); - textCheckerState.isGrammarCheckingEnabled = client.grammarCheckingEnabled(); +const TextCheckerState& TextChecker::state() +{ + return checkerState(); +} + +static bool testingModeEnabled = false; + +void TextChecker::setTestingMode(bool enabled) +{ + testingModeEnabled = enabled; +} - didInitializeState = true; +bool TextChecker::isTestingMode() +{ + return testingModeEnabled; +} - return textCheckerState; +#if ENABLE(SPELLCHECK) +static void updateStateForAllProcessPools() +{ + for (const auto& processPool : WebProcessPool::allProcessPools()) + processPool->textCheckerStateChanged(); } - +#endif + bool TextChecker::isContinuousSpellCheckingAllowed() { - return WebTextChecker::shared()->client().continuousSpellCheckingAllowed(); +#if ENABLE(SPELLCHECK) + return true; +#else + return false; +#endif } void TextChecker::setContinuousSpellCheckingEnabled(bool isContinuousSpellCheckingEnabled) { - if (state().isContinuousSpellCheckingEnabled == isContinuousSpellCheckingEnabled) +#if ENABLE(SPELLCHECK) + if (checkerState().isContinuousSpellCheckingEnabled == isContinuousSpellCheckingEnabled) return; - textCheckerState.isContinuousSpellCheckingEnabled = isContinuousSpellCheckingEnabled; - WebTextChecker::shared()->client().setContinuousSpellCheckingEnabled(isContinuousSpellCheckingEnabled); + checkerState().isContinuousSpellCheckingEnabled = isContinuousSpellCheckingEnabled; + updateStateForAllProcessPools(); +#else + UNUSED_PARAM(isContinuousSpellCheckingEnabled); +#endif } void TextChecker::setGrammarCheckingEnabled(bool isGrammarCheckingEnabled) { - if (state().isGrammarCheckingEnabled == isGrammarCheckingEnabled) +#if ENABLE(SPELLCHECK) + if (checkerState().isGrammarCheckingEnabled == isGrammarCheckingEnabled) return; - textCheckerState.isGrammarCheckingEnabled = isGrammarCheckingEnabled; - WebTextChecker::shared()->client().setGrammarCheckingEnabled(isGrammarCheckingEnabled); + checkerState().isGrammarCheckingEnabled = isGrammarCheckingEnabled; + updateStateForAllProcessPools(); +#else + UNUSED_PARAM(isGrammarCheckingEnabled); +#endif } void TextChecker::continuousSpellCheckingEnabledStateChanged(bool enabled) { - textCheckerState.isContinuousSpellCheckingEnabled = enabled; +#if ENABLE(SPELLCHECK) + checkerState().isContinuousSpellCheckingEnabled = enabled; +#else + UNUSED_PARAM(enabled); +#endif } void TextChecker::grammarCheckingEnabledStateChanged(bool enabled) { - textCheckerState.isGrammarCheckingEnabled = enabled; +#if ENABLE(SPELLCHECK) + checkerState().isGrammarCheckingEnabled = enabled; +#else + UNUSED_PARAM(enabled); +#endif } -int64_t TextChecker::uniqueSpellDocumentTag(WebPageProxy* page) +int64_t TextChecker::uniqueSpellDocumentTag(WebPageProxy*) { - return WebTextChecker::shared()->client().uniqueSpellDocumentTag(page); + return 0; } -void TextChecker::closeSpellDocumentWithTag(int64_t tag) +void TextChecker::closeSpellDocumentWithTag(int64_t /* tag */) { - WebTextChecker::shared()->client().closeSpellDocumentWithTag(tag); } -void TextChecker::checkSpellingOfString(int64_t spellDocumentTag, const UChar* text, uint32_t length, int32_t& misspellingLocation, int32_t& misspellingLength) +void TextChecker::checkSpellingOfString(int64_t /* spellDocumentTag */, StringView text, int32_t& misspellingLocation, int32_t& misspellingLength) { - WebTextChecker::shared()->client().checkSpellingOfString(spellDocumentTag, String(text, length), misspellingLocation, misspellingLength); +#if ENABLE(SPELLCHECK) + misspellingLocation = -1; + misspellingLength = 0; + enchantTextChecker().checkSpellingOfString(text.toStringWithoutCopying(), misspellingLocation, misspellingLength); +#else + UNUSED_PARAM(text); + UNUSED_PARAM(misspellingLocation); + UNUSED_PARAM(misspellingLength); +#endif } -void TextChecker::checkGrammarOfString(int64_t spellDocumentTag, const UChar* text, uint32_t length, Vector<WebCore::GrammarDetail>& grammarDetails, int32_t& badGrammarLocation, int32_t& badGrammarLength) +void TextChecker::checkGrammarOfString(int64_t /* spellDocumentTag */, StringView /* text */, Vector<WebCore::GrammarDetail>& /* grammarDetails */, int32_t& /* badGrammarLocation */, int32_t& /* badGrammarLength */) { - WebTextChecker::shared()->client().checkGrammarOfString(spellDocumentTag, String(text, length), grammarDetails, badGrammarLocation, badGrammarLength); } bool TextChecker::spellingUIIsShowing() { - return WebTextChecker::shared()->client().spellingUIIsShowing(); + return false; } void TextChecker::toggleSpellingUIIsShowing() { - WebTextChecker::shared()->client().toggleSpellingUIIsShowing(); } -void TextChecker::updateSpellingUIWithMisspelledWord(int64_t spellDocumentTag, const String& misspelledWord) +void TextChecker::updateSpellingUIWithMisspelledWord(int64_t /* spellDocumentTag */, const String& /* misspelledWord */) +{ +} + +void TextChecker::updateSpellingUIWithGrammarString(int64_t /* spellDocumentTag */, const String& /* badGrammarPhrase */, const GrammarDetail& /* grammarDetail */) { - WebTextChecker::shared()->client().updateSpellingUIWithMisspelledWord(spellDocumentTag, misspelledWord); } -void TextChecker::updateSpellingUIWithGrammarString(int64_t spellDocumentTag, const String& badGrammarPhrase, const GrammarDetail& grammarDetail) +void TextChecker::getGuessesForWord(int64_t /* spellDocumentTag */, const String& word, const String& /* context */, int32_t /* insertionPoint */, Vector<String>& guesses, bool) { - WebTextChecker::shared()->client().updateSpellingUIWithGrammarString(spellDocumentTag, badGrammarPhrase, grammarDetail); +#if ENABLE(SPELLCHECK) + guesses = enchantTextChecker().getGuessesForWord(word); +#else + UNUSED_PARAM(word); + UNUSED_PARAM(guesses); +#endif } -void TextChecker::getGuessesForWord(int64_t spellDocumentTag, const String& word, const String& context, Vector<String>& guesses) +void TextChecker::learnWord(int64_t /* spellDocumentTag */, const String& word) { - WebTextChecker::shared()->client().guessesForWord(spellDocumentTag, word, guesses); +#if ENABLE(SPELLCHECK) + enchantTextChecker().learnWord(word); +#else + UNUSED_PARAM(word); +#endif } -void TextChecker::learnWord(int64_t spellDocumentTag, const String& word) +void TextChecker::ignoreWord(int64_t /* spellDocumentTag */, const String& word) { - WebTextChecker::shared()->client().learnWord(spellDocumentTag, word); +#if ENABLE(SPELLCHECK) + enchantTextChecker().ignoreWord(word); +#else + UNUSED_PARAM(word); +#endif +} + +void TextChecker::requestCheckingOfString(PassRefPtr<TextCheckerCompletion> completion, int32_t insertionPoint) +{ +#if ENABLE(SPELLCHECK) + if (!completion) + return; + + TextCheckingRequestData request = completion->textCheckingRequestData(); + ASSERT(request.sequence() != unrequestedTextCheckingSequence); + ASSERT(request.mask() != TextCheckingTypeNone); + + completion->didFinishCheckingText(checkTextOfParagraph(completion->spellDocumentTag(), request.text(), insertionPoint, request.mask(), false)); +#else + UNUSED_PARAM(completion); +#endif +} + +#if USE(UNIFIED_TEXT_CHECKING) && ENABLE(SPELLCHECK) +static unsigned nextWordOffset(StringView text, unsigned currentOffset) +{ + // FIXME: avoid creating textIterator object here, it could be passed as a parameter. + // ubrk_isBoundary() leaves the iterator pointing to the first boundary position at + // or after "offset" (ubrk_isBoundary side effect). + // For many word separators, the method doesn't properly determine the boundaries + // without resetting the iterator. + UBreakIterator* textIterator = wordBreakIterator(text); + if (!textIterator) + return currentOffset; + + unsigned wordOffset = currentOffset; + while (wordOffset < text.length() && ubrk_isBoundary(textIterator, wordOffset)) + ++wordOffset; + + // Do not treat the word's boundary as a separator. + if (!currentOffset && wordOffset == 1) + return currentOffset; + + // Omit multiple separators. + if ((wordOffset - currentOffset) > 1) + --wordOffset; + + return wordOffset; +} +#endif + +#if USE(UNIFIED_TEXT_CHECKING) +Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, uint64_t checkingTypes, bool) +{ + UNUSED_PARAM(insertionPoint); +#if ENABLE(SPELLCHECK) + if (!(checkingTypes & TextCheckingTypeSpelling)) + return Vector<TextCheckingResult>(); + + UBreakIterator* textIterator = wordBreakIterator(text); + if (!textIterator) + return Vector<TextCheckingResult>(); + + // Omit the word separators at the beginning/end of the text to don't unnecessarily + // involve the client to check spelling for them. + unsigned offset = nextWordOffset(text, 0); + unsigned lengthStrip = text.length(); + while (lengthStrip > 0 && ubrk_isBoundary(textIterator, lengthStrip - 1)) + --lengthStrip; + + Vector<TextCheckingResult> paragraphCheckingResult; + while (offset < lengthStrip) { + int32_t misspellingLocation = -1; + int32_t misspellingLength = 0; + checkSpellingOfString(spellDocumentTag, text.substring(offset, lengthStrip - offset), misspellingLocation, misspellingLength); + if (!misspellingLength) + break; + + TextCheckingResult misspellingResult; + misspellingResult.type = TextCheckingTypeSpelling; + misspellingResult.location = offset + misspellingLocation; + misspellingResult.length = misspellingLength; + paragraphCheckingResult.append(misspellingResult); + offset += misspellingLocation + misspellingLength; + // Generally, we end up checking at the word separator, move to the adjacent word. + offset = nextWordOffset(text.substring(0, lengthStrip), offset); + } + return paragraphCheckingResult; +#else + UNUSED_PARAM(spellDocumentTag); + UNUSED_PARAM(text); + UNUSED_PARAM(checkingTypes); + return Vector<TextCheckingResult>(); +#endif // ENABLE(SPELLCHECK) } +#endif // USE(UNIFIED_TEXT_CHECKING) -void TextChecker::ignoreWord(int64_t spellDocumentTag, const String& word) +void TextChecker::setSpellCheckingLanguages(const Vector<String>& languages) { - WebTextChecker::shared()->client().ignoreWord(spellDocumentTag, word); +#if ENABLE(SPELLCHECK) + enchantTextChecker().updateSpellCheckingLanguages(languages); +#else + UNUSED_PARAM(languages); +#endif } -void TextChecker::requestCheckingOfString(PassRefPtr<TextCheckerCompletion>) +Vector<String> TextChecker::loadedSpellCheckingLanguages() { - notImplemented(); +#if ENABLE(SPELLCHECK) + return enchantTextChecker().loadedSpellCheckingLanguages(); +#else + return Vector<String>(); +#endif } } // namespace WebKit |