| /* |
| * Copyright (C) 2012 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| * THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #import "config.h" |
| #import "TextChecker.h" |
| |
| #if PLATFORM(IOS_FAMILY) |
| |
| #import "TextCheckerState.h" |
| #import "UIKitSPI.h" |
| #import <WebCore/NotImplemented.h> |
| #import <wtf/HashMap.h> |
| #import <wtf/NeverDestroyed.h> |
| #import <wtf/RetainPtr.h> |
| #import <wtf/text/StringView.h> |
| |
| namespace WebKit { |
| using namespace WebCore; |
| |
| static TextCheckerState& mutableState() |
| { |
| static NeverDestroyed<TextCheckerState> state = makeNeverDestroyed([] { |
| TextCheckerState initialState; |
| initialState.isContinuousSpellCheckingEnabled = TextChecker::isContinuousSpellCheckingAllowed(); |
| initialState.isGrammarCheckingEnabled = false; |
| return initialState; |
| }()); |
| return state; |
| } |
| |
| const TextCheckerState& TextChecker::state() |
| { |
| return mutableState(); |
| } |
| |
| bool TextChecker::isContinuousSpellCheckingAllowed() |
| { |
| #if USE(UNIFIED_TEXT_CHECKING) |
| return true; |
| #else |
| return false; |
| #endif |
| } |
| |
| bool TextChecker::setContinuousSpellCheckingEnabled(bool enabled) |
| { |
| if (state().isContinuousSpellCheckingEnabled == enabled) |
| return false; |
| |
| mutableState().isContinuousSpellCheckingEnabled = enabled; |
| return true; |
| } |
| |
| void TextChecker::setGrammarCheckingEnabled(bool) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::setAutomaticSpellingCorrectionEnabled(bool) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::setAutomaticQuoteSubstitutionEnabled(bool) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::setAutomaticDashSubstitutionEnabled(bool) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::setAutomaticLinkDetectionEnabled(bool) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::setAutomaticTextReplacementEnabled(bool) |
| { |
| notImplemented(); |
| } |
| |
| static bool testingModeEnabled = false; |
| |
| void TextChecker::setTestingMode(bool enabled) |
| { |
| testingModeEnabled = enabled; |
| } |
| |
| bool TextChecker::isTestingMode() |
| { |
| return testingModeEnabled; |
| } |
| |
| bool TextChecker::isSmartInsertDeleteEnabled() |
| { |
| return [[UIKeyboardImpl sharedInstance] smartInsertDeleteIsEnabled]; |
| } |
| |
| void TextChecker::setSmartInsertDeleteEnabled(bool) |
| { |
| notImplemented(); |
| } |
| |
| bool TextChecker::substitutionsPanelIsShowing() |
| { |
| notImplemented(); |
| return false; |
| } |
| |
| void TextChecker::toggleSubstitutionsPanelIsShowing() |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::continuousSpellCheckingEnabledStateChanged(bool enabled) |
| { |
| mutableState().isContinuousSpellCheckingEnabled = enabled; |
| } |
| |
| void TextChecker::grammarCheckingEnabledStateChanged(bool) |
| { |
| notImplemented(); |
| } |
| |
| #if USE(UNIFIED_TEXT_CHECKING) |
| |
| static HashMap<SpellDocumentTag, RetainPtr<UITextChecker>>& spellDocumentTagMap() |
| { |
| static NeverDestroyed<HashMap<SpellDocumentTag, RetainPtr<UITextChecker>>> tagMap; |
| return tagMap; |
| } |
| |
| #endif |
| |
| SpellDocumentTag TextChecker::uniqueSpellDocumentTag(WebPageProxy*) |
| { |
| #if USE(UNIFIED_TEXT_CHECKING) |
| static SpellDocumentTag nextSpellDocumentTag; |
| return ++nextSpellDocumentTag; |
| #else |
| return { }; |
| #endif |
| } |
| |
| void TextChecker::closeSpellDocumentWithTag(SpellDocumentTag spellDocumentTag) |
| { |
| #if USE(UNIFIED_TEXT_CHECKING) |
| spellDocumentTagMap().remove(spellDocumentTag); |
| #else |
| UNUSED_PARAM(spellDocumentTag); |
| #endif |
| } |
| |
| #if USE(UNIFIED_TEXT_CHECKING) |
| |
| static RetainPtr<UITextChecker> textCheckerFor(SpellDocumentTag spellDocumentTag) |
| { |
| auto addResult = spellDocumentTagMap().add(spellDocumentTag, nullptr); |
| if (addResult.isNewEntry) |
| addResult.iterator->value = adoptNS([[UITextChecker alloc] _initWithAsynchronousLoading:YES]); |
| return addResult.iterator->value; |
| } |
| |
| Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(SpellDocumentTag spellDocumentTag, StringView text, int32_t /* insertionPoint */, OptionSet<TextCheckingType> checkingTypes, bool /* initialCapitalizationEnabled */) |
| { |
| Vector<TextCheckingResult> results; |
| if (!checkingTypes.contains(TextCheckingType::Spelling)) |
| return results; |
| |
| auto textChecker = textCheckerFor(spellDocumentTag); |
| if (![textChecker _doneLoading]) |
| return results; |
| |
| NSArray<NSString *> *keyboardLanguages = @[ ]; |
| auto *currentInputMode = [UIKeyboardInputModeController sharedInputModeController].currentInputMode; |
| if (currentInputMode.multilingualLanguages.count) |
| keyboardLanguages = currentInputMode.multilingualLanguages; |
| else if (currentInputMode.primaryLanguage) |
| keyboardLanguages = @[ currentInputMode.languageWithRegion ]; |
| |
| auto stringToCheck = text.createNSStringWithoutCopying(); |
| auto range = NSMakeRange(0, [stringToCheck length]); |
| NSUInteger offsetSoFar = 0; |
| do { |
| auto misspelledRange = [textChecker rangeOfMisspelledWordInString:stringToCheck.get() range:range startingAt:offsetSoFar wrap:NO languages:keyboardLanguages]; |
| if (misspelledRange.location == NSNotFound) |
| break; |
| |
| TextCheckingResult result; |
| result.type = TextCheckingType::Spelling; |
| result.range = misspelledRange; |
| results.append(WTFMove(result)); |
| |
| offsetSoFar = misspelledRange.location + misspelledRange.length; |
| } while (offsetSoFar < [stringToCheck length]); |
| return results; |
| } |
| |
| #endif |
| |
| void TextChecker::checkSpellingOfString(SpellDocumentTag, StringView, int32_t&, int32_t&) |
| { |
| // iOS uses checkTextOfParagraph() instead. |
| notImplemented(); |
| } |
| |
| void TextChecker::checkGrammarOfString(SpellDocumentTag, StringView, Vector<WebCore::GrammarDetail>&, int32_t&, int32_t&) |
| { |
| // iOS uses checkTextOfParagraph() instead. |
| notImplemented(); |
| } |
| |
| bool TextChecker::spellingUIIsShowing() |
| { |
| notImplemented(); |
| return false; |
| } |
| |
| void TextChecker::toggleSpellingUIIsShowing() |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::updateSpellingUIWithMisspelledWord(SpellDocumentTag, const String&) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::updateSpellingUIWithGrammarString(SpellDocumentTag, const String&, const GrammarDetail&) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::getGuessesForWord(SpellDocumentTag, const String&, const String&, int32_t, Vector<String>&, bool) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::learnWord(SpellDocumentTag, const String&) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::ignoreWord(SpellDocumentTag, const String&) |
| { |
| notImplemented(); |
| } |
| |
| void TextChecker::requestCheckingOfString(Ref<TextCheckerCompletion>&&, int32_t) |
| { |
| notImplemented(); |
| } |
| |
| } // namespace WebKit |
| |
| #endif // PLATFORM(IOS_FAMILY) |