2011-02-19 Ryuan Choi <ryuan.choi@samsung.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Feb 2011 21:06:04 +0000 (21:06 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Feb 2011 21:06:04 +0000 (21:06 +0000)
        Reviewed by Martin Robinson.

        [GTK] Remove mandatory Enchant dependency
        https://bugs.webkit.org/show_bug.cgi?id=51587

        Add enable-spellcheck option which decides whether to use enchant.
        If disabled, WebKitGTK+ will not use enchant library.

        * configure.ac:
2011-02-19  Ryuan Choi  <ryuan.choi@samsung.com>

        Reviewed by Martin Robinson.

        [GTK] Remove mandatory Enchant dependency
        https://bugs.webkit.org/show_bug.cgi?id=51587

        Extract TextCheckerClientEnchant From EditorClientGtk and remove
        enchant dependency from other files.

        * GNUmakefile.am:
        * WebCoreSupport/EditorClientGtk.cpp:
        (WebKit::EditorClient::EditorClient):
        * WebCoreSupport/EditorClientGtk.h:
        (WebKit::EditorClient::textChecker):
        * WebCoreSupport/TextCheckerClientEnchant.cpp: Added.
        (WebKit::TextCheckerClientEnchant::TextCheckerClientEnchant):
        (WebKit::TextCheckerClientEnchant::~TextCheckerClientEnchant):
        (WebKit::TextCheckerClientEnchant::ignoreWordInSpellDocument):
        (WebKit::TextCheckerClientEnchant::learnWord):
        (WebKit::TextCheckerClientEnchant::checkSpellingOfString):
        (WebKit::TextCheckerClientEnchant::getAutoCorrectSuggestionForMisspelledWord):
        (WebKit::TextCheckerClientEnchant::checkGrammarOfString):
        (WebKit::TextCheckerClientEnchant::getGuessesForWord):
        (WebKit::getAvailableDictionariesCallback):
        (WebKit::TextCheckerClientEnchant::updateSpellCheckingLanguage):
        (WebKit::TextCheckerClientEnchant::freeSpellCheckingLanguage):
        * WebCoreSupport/TextCheckerClientEnchant.h: Added.
        (WebKit::TextCheckerClientEnchant::requestCheckingOfString):
        * webkit/webkitwebsettings.cpp:
        (webkit_web_settings_finalize):
        (webkit_web_settings_set_property):
        * webkit/webkitwebview.cpp:
        (webkit_web_view_settings_notify):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@79130 268f45cc-cd09-0410-ab3c-d52691b4dbfc

ChangeLog
Source/WebKit/gtk/ChangeLog
Source/WebKit/gtk/GNUmakefile.am
Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp
Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h
Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.cpp [new file with mode: 0644]
Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.h [new file with mode: 0644]
Source/WebKit/gtk/webkit/webkitwebsettings.cpp
Source/WebKit/gtk/webkit/webkitwebview.cpp
configure.ac

index 65fa638..4bd2f46 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-02-19  Ryuan Choi  <ryuan.choi@samsung.com>
+
+        Reviewed by Martin Robinson.
+
+        [GTK] Remove mandatory Enchant dependency
+        https://bugs.webkit.org/show_bug.cgi?id=51587
+
+        Add enable-spellcheck option which decides whether to use enchant.
+        If disabled, WebKitGTK+ will not use enchant library.
+
+        * configure.ac:
+
 2011-02-18  Zan Dobersek  <zandobersek@gmail.com>
 
         Reviewed by Martin Robinson.
index 97f0157..deed866 100644 (file)
@@ -1,3 +1,38 @@
+2011-02-19  Ryuan Choi  <ryuan.choi@samsung.com>
+
+        Reviewed by Martin Robinson.
+
+        [GTK] Remove mandatory Enchant dependency
+        https://bugs.webkit.org/show_bug.cgi?id=51587
+
+        Extract TextCheckerClientEnchant From EditorClientGtk and remove
+        enchant dependency from other files.
+
+        * GNUmakefile.am:
+        * WebCoreSupport/EditorClientGtk.cpp:
+        (WebKit::EditorClient::EditorClient):
+        * WebCoreSupport/EditorClientGtk.h:
+        (WebKit::EditorClient::textChecker):
+        * WebCoreSupport/TextCheckerClientEnchant.cpp: Added.
+        (WebKit::TextCheckerClientEnchant::TextCheckerClientEnchant):
+        (WebKit::TextCheckerClientEnchant::~TextCheckerClientEnchant):
+        (WebKit::TextCheckerClientEnchant::ignoreWordInSpellDocument):
+        (WebKit::TextCheckerClientEnchant::learnWord):
+        (WebKit::TextCheckerClientEnchant::checkSpellingOfString):
+        (WebKit::TextCheckerClientEnchant::getAutoCorrectSuggestionForMisspelledWord):
+        (WebKit::TextCheckerClientEnchant::checkGrammarOfString):
+        (WebKit::TextCheckerClientEnchant::getGuessesForWord):
+        (WebKit::getAvailableDictionariesCallback):
+        (WebKit::TextCheckerClientEnchant::updateSpellCheckingLanguage):
+        (WebKit::TextCheckerClientEnchant::freeSpellCheckingLanguage):
+        * WebCoreSupport/TextCheckerClientEnchant.h: Added.
+        (WebKit::TextCheckerClientEnchant::requestCheckingOfString):
+        * webkit/webkitwebsettings.cpp:
+        (webkit_web_settings_finalize):
+        (webkit_web_settings_set_property):
+        * webkit/webkitwebview.cpp:
+        (webkit_web_view_settings_notify):
+
 2011-02-19  Charlie Reis  <creis@chromium.org>
 
         Reviewed by Mihai Parparita.
index d207e00..e3a0326 100644 (file)
@@ -29,6 +29,15 @@ libwebkitgtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CFLA
        $(SYMBOL_VISIBILITY) \
        $(global_cflags)
 
+if ENABLE_SPELLCHECK
+webkitgtk_cppflags += \
+       -DENABLE_SPELLCHECK=1
+
+webkitgtk_sources += \
+       Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.cpp \
+       Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.h
+endif
+
 # When building WebCore/WebKit, we want WebCore/config.h and NOT JavaScriptCore/config.h,
 # hence, it's important that WebCore/ should come first before JavaScriptCore in the
 # include path.
@@ -47,6 +56,7 @@ libwebkitgtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CPPF
        $(webcore_cppflags) \
        $(webcoregtk_cppflags) \
        $(javascriptcore_cppflags) \
+       $(webkitgtk_cppflags) \
        -fno-strict-aliasing \
        $(HILDON_CPPFLAGS) \
        $(COVERAGE_CFLAGS) \
index cd39522..7151f54 100644 (file)
@@ -27,7 +27,6 @@
 #include "DataObjectGtk.h"
 #include "EditCommand.h"
 #include "Editor.h"
-#include <enchant.h>
 #include "EventNames.h"
 #include "FocusController.h"
 #include "Frame.h"
@@ -842,6 +841,9 @@ void EditorClient::handleInputMethodMousePress()
 
 EditorClient::EditorClient(WebKitWebView* webView)
     : m_isInRedo(false)
+#if ENABLE(SPELLCHECK)
+    , m_textCheckerClient(webView)
+#endif
     , m_webView(webView)
     , m_preventNextCompositionCommit(false)
     , m_treatContextCommitAsKeyEvent(false)
@@ -897,100 +899,6 @@ void EditorClient::textDidChangeInTextArea(Element*)
     notImplemented();
 }
 
-void EditorClient::ignoreWordInSpellDocument(const String& text)
-{
-    GSList* dicts = webkitWebViewGetEnchantDicts(m_webView);
-
-    for (; dicts; dicts = dicts->next) {
-        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
-
-        enchant_dict_add_to_session(dict, text.utf8().data(), -1);
-    }
-}
-
-void EditorClient::learnWord(const String& text)
-{
-    GSList* dicts = webkitWebViewGetEnchantDicts(m_webView);
-
-    for (; dicts; dicts = dicts->next) {
-        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
-
-        enchant_dict_add_to_personal(dict, text.utf8().data(), -1);
-    }
-}
-
-void EditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
-{
-    GSList* dicts = webkitWebViewGetEnchantDicts(m_webView);
-    if (!dicts)
-        return;
-
-    gchar* ctext = g_utf16_to_utf8(const_cast<gunichar2*>(text), length, 0, 0, 0);
-    int utflen = g_utf8_strlen(ctext, -1);
-
-    PangoLanguage* language = pango_language_get_default();
-    PangoLogAttr* attrs = g_new(PangoLogAttr, utflen+1);
-
-    // pango_get_log_attrs uses an aditional position at the end of the text.
-    pango_get_log_attrs(ctext, -1, -1, language, attrs, utflen+1);
-
-    for (int i = 0; i < length+1; i++) {
-        // We go through each character until we find an is_word_start,
-        // then we get into an inner loop to find the is_word_end corresponding
-        // to it.
-        if (attrs[i].is_word_start) {
-            int start = i;
-            int end = i;
-            int wordLength;
-
-            while (attrs[end].is_word_end < 1)
-                end++;
-
-            wordLength = end - start;
-            // Set the iterator to be at the current word end, so we don't
-            // check characters twice.
-            i = end;
-
-            for (; dicts; dicts = dicts->next) {
-                EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
-                gchar* cstart = g_utf8_offset_to_pointer(ctext, start);
-                gint bytes = static_cast<gint>(g_utf8_offset_to_pointer(ctext, end) - cstart);
-                gchar* word = g_new0(gchar, bytes+1);
-                int result;
-
-                g_utf8_strncpy(word, cstart, end - start);
-
-                result = enchant_dict_check(dict, word, -1);
-                g_free(word);
-                if (result) {
-                    *misspellingLocation = start;
-                    *misspellingLength = wordLength;
-                } else {
-                    // Stop checking, this word is ok in at least one dict.
-                    *misspellingLocation = -1;
-                    *misspellingLength = 0;
-                    break;
-                }
-            }
-        }
-    }
-
-    g_free(attrs);
-    g_free(ctext);
-}
-
-String EditorClient::getAutoCorrectSuggestionForMisspelledWord(const String& inputWord)
-{
-    // This method can be implemented using customized algorithms for the particular browser.
-    // Currently, it computes an empty string.
-    return String();
-}
-
-void EditorClient::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
-{
-    notImplemented();
-}
-
 void EditorClient::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&)
 {
     notImplemented();
@@ -1012,24 +920,4 @@ bool EditorClient::spellingUIIsShowing()
     return false;
 }
 
-void EditorClient::getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses)
-{
-    GSList* dicts = webkitWebViewGetEnchantDicts(m_webView);
-    guesses.clear();
-
-    for (; dicts; dicts = dicts->next) {
-        size_t numberOfSuggestions;
-        size_t i;
-
-        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
-        gchar** suggestions = enchant_dict_suggest(dict, word.utf8().data(), -1, &numberOfSuggestions);
-
-        for (i = 0; i < numberOfSuggestions && i < 10; i++)
-            guesses.append(String::fromUTF8(suggestions[i]));
-
-        if (numberOfSuggestions > 0)
-            enchant_dict_free_suggestions(dict, suggestions);
-    }
-}
-
 }
index 279474e..d83a7d2 100644 (file)
 #include <wtf/gobject/GOwnPtr.h>
 #include <wtf/gobject/GRefPtr.h>
 
+#if ENABLE(SPELLCHECK)
+#include "TextCheckerClientEnchant.h"
+#else
+#include "EmptyClients.h"
+#endif
+
 typedef struct _WebKitWebView WebKitWebView;
 
 namespace WebCore {
@@ -48,7 +54,7 @@ class KeyboardEvent;
 
 namespace WebKit {
 
-class EditorClient : public WebCore::EditorClient,  public WebCore::TextCheckerClient {
+class EditorClient : public WebCore::EditorClient {
     protected:
         bool m_isInRedo;
 
@@ -123,23 +129,21 @@ class EditorClient : public WebCore::EditorClient,  public WebCore::TextCheckerC
         virtual void textWillBeDeletedInTextField(WebCore::Element*);
         virtual void textDidChangeInTextArea(WebCore::Element*);
 
-        virtual WebCore::TextCheckerClient* textChecker() { return this; }
+        virtual WebCore::TextCheckerClient* textChecker() { return &m_textCheckerClient; }
 
-        virtual void ignoreWordInSpellDocument(const WTF::String&);
-        virtual void learnWord(const WTF::String&);
-        virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength);
-        virtual WTF::String getAutoCorrectSuggestionForMisspelledWord(const WTF::String&);
-        virtual void checkGrammarOfString(const UChar*, int length, WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength);
         virtual void updateSpellingUIWithGrammarString(const WTF::String&, const WebCore::GrammarDetail&);
         virtual void updateSpellingUIWithMisspelledWord(const WTF::String&);
         virtual void showSpellingUI(bool show);
         virtual bool spellingUIIsShowing();
-        virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses);
         virtual void willSetInputMethodState();
         virtual void setInputMethodState(bool enabled);
-        virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {}
 
     private:
+#if ENABLE(SPELLCHECK)
+        TextCheckerClientEnchant m_textCheckerClient;
+#else
+        WebCore::EmptyTextCheckerClient m_textCheckerClient;
+#endif
         WebKitWebView* m_webView;
         bool m_preventNextCompositionCommit;
         bool m_treatContextCommitAsKeyEvent;
diff --git a/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.cpp b/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.cpp
new file mode 100644 (file)
index 0000000..ee1b11a
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ *  Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *  Copyright (C) 2008 Nuanti Ltd.
+ *  Copyright (C) 2009 Diego Escalante Urrelo <diegoe@gnome.org>
+ *  Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ *  Copyright (C) 2009, 2010 Igalia S.L.
+ *  Copyright (C) 2010, Martin Robinson <mrobinson@webkit.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "TextCheckerClientEnchant.h"
+
+#include "NotImplemented.h"
+#include "webkitwebsettingsprivate.h"
+#include "webkitwebviewprivate.h"
+#include <enchant.h>
+#include <glib.h>
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+EnchantBroker* TextCheckerClientEnchant::broker = 0;
+
+TextCheckerClientEnchant::TextCheckerClientEnchant(WebKitWebView* webView)
+    : m_webView(webView)
+    , m_enchantDicts(0)
+{
+}
+
+TextCheckerClientEnchant::~TextCheckerClientEnchant()
+{
+    g_slist_foreach(m_enchantDicts, freeSpellCheckingLanguage, 0);
+    g_slist_free(m_enchantDicts);
+}
+
+void TextCheckerClientEnchant::ignoreWordInSpellDocument(const String& text)
+{
+    GSList* dicts = m_enchantDicts;
+
+    for (; dicts; dicts = dicts->next) {
+        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
+
+        enchant_dict_add_to_session(dict, text.utf8().data(), -1);
+    }
+}
+
+void TextCheckerClientEnchant::learnWord(const String& text)
+{
+    GSList* dicts = m_enchantDicts;
+
+    for (; dicts; dicts = dicts->next) {
+        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
+
+        enchant_dict_add_to_personal(dict, text.utf8().data(), -1);
+    }
+}
+
+void TextCheckerClientEnchant::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
+{
+    GSList* dicts = m_enchantDicts;
+    if (!dicts)
+        return;
+
+    gchar* ctext = g_utf16_to_utf8(const_cast<gunichar2*>(text), length, 0, 0, 0);
+    int utflen = g_utf8_strlen(ctext, -1);
+
+    GOwnPtr<PangoLanguage> language(pango_language_get_default());
+    GOwnPtr<PangoLogAttr> attrs(g_new(PangoLogAttr, utflen+1));
+
+    // pango_get_log_attrs uses an aditional position at the end of the text.
+    pango_get_log_attrs(ctext, -1, -1, language.get(), attrs.get(), utflen+1);
+
+    for (int i = 0; i < length+1; i++) {
+        // We go through each character until we find an is_word_start,
+        // then we get into an inner loop to find the is_word_end corresponding
+        // to it.
+        if (attrs.get()[i].is_word_start) {
+            int start = i;
+            int end = i;
+            int wordLength;
+
+            while (attrs.get()[end].is_word_end < 1)
+                end++;
+
+            wordLength = end - start;
+            // Set the iterator to be at the current word end, so we don't
+            // check characters twice.
+            i = end;
+
+            for (; dicts; dicts = dicts->next) {
+                EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
+                gchar* cstart = g_utf8_offset_to_pointer(ctext, start);
+                gint bytes = static_cast<gint>(g_utf8_offset_to_pointer(ctext, end) - cstart);
+                gchar* word = g_new0(gchar, bytes+1);
+                int result;
+
+                g_utf8_strncpy(word, cstart, end - start);
+
+                result = enchant_dict_check(dict, word, -1);
+                g_free(word);
+                if (result) {
+                    *misspellingLocation = start;
+                    *misspellingLength = wordLength;
+                } else {
+                    // Stop checking, this word is ok in at least one dict.
+                    *misspellingLocation = -1;
+                    *misspellingLength = 0;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+String TextCheckerClientEnchant::getAutoCorrectSuggestionForMisspelledWord(const String& inputWord)
+{
+    // This method can be implemented using customized algorithms for the particular browser.
+    // Currently, it computes an empty string.
+    return String();
+}
+
+void TextCheckerClientEnchant::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
+{
+    notImplemented();
+}
+
+void TextCheckerClientEnchant::getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses)
+{
+    GSList* dicts = m_enchantDicts;
+    guesses.clear();
+
+    for (; dicts; dicts = dicts->next) {
+        size_t numberOfSuggestions;
+        size_t i;
+
+        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
+        gchar** suggestions = enchant_dict_suggest(dict, word.utf8().data(), -1, &numberOfSuggestions);
+
+        for (i = 0; i < numberOfSuggestions && i < 10; i++)
+            guesses.append(String::fromUTF8(suggestions[i]));
+
+        if (numberOfSuggestions > 0)
+            enchant_dict_free_suggestions(dict, suggestions);
+    }
+}
+
+static void getAvailableDictionariesCallback(const char* const languageTag, const char* const, const char* const, const char* const, void* data)
+{
+    Vector<CString>* dicts = static_cast<Vector<CString>*>(data);
+
+    dicts->append(languageTag);
+}
+
+void TextCheckerClientEnchant::updateSpellCheckingLanguage(const char* spellCheckingLanguages)
+{
+    EnchantDict* dict;
+    GSList* spellDictionaries = 0;
+
+    if (!broker)
+        broker = enchant_broker_init();
+
+    if (spellCheckingLanguages) {
+        char** langs = g_strsplit(spellCheckingLanguages, ",", -1);
+        for (int i = 0; langs[i]; i++) {
+            if (enchant_broker_dict_exists(broker, langs[i])) {
+                dict = enchant_broker_request_dict(broker, langs[i]);
+                spellDictionaries = g_slist_append(spellDictionaries, dict);
+            }
+        }
+        g_strfreev(langs);
+    } else {
+        const char* language = pango_language_to_string(gtk_get_default_language());
+        if (enchant_broker_dict_exists(broker, language)) {
+            dict = enchant_broker_request_dict(broker, language);
+            spellDictionaries = g_slist_append(spellDictionaries, dict);
+        } else {
+            // No dictionaries selected, we get one from the list
+            Vector<CString> allDictionaries;
+            enchant_broker_list_dicts(broker, getAvailableDictionariesCallback, &allDictionaries);
+            if (!allDictionaries.isEmpty()) {
+                dict = enchant_broker_request_dict(broker, allDictionaries[0].data());
+                spellDictionaries = g_slist_append(spellDictionaries, dict);
+            }
+        }
+    }
+    g_slist_foreach(m_enchantDicts, freeSpellCheckingLanguage, 0);
+    g_slist_free(m_enchantDicts);
+    m_enchantDicts = spellDictionaries;
+}
+
+void TextCheckerClientEnchant::freeSpellCheckingLanguage(gpointer data, gpointer)
+{
+    if (!broker)
+        broker = enchant_broker_init();
+
+    EnchantDict* dict = static_cast<EnchantDict*>(data);
+    enchant_broker_free_dict(broker, dict);
+}
+
+}
diff --git a/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.h b/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientEnchant.h
new file mode 100644 (file)
index 0000000..c294a3d
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org>
+ *
+ * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef TextCheckerClientEnchant_h
+#define TextCheckerClientEnchant_h
+
+#include "TextCheckerClient.h"
+
+typedef struct _GSList GSList;
+typedef struct _WebKitWebView WebKitWebView;
+typedef struct str_enchant_broker EnchantBroker;
+
+namespace WebKit {
+
+class TextCheckerClientEnchant : public WebCore::TextCheckerClient {
+    public:
+        TextCheckerClientEnchant(WebKitWebView*);
+        ~TextCheckerClientEnchant();
+        virtual void ignoreWordInSpellDocument(const WTF::String&);
+        virtual void learnWord(const WTF::String&);
+        virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength);
+        virtual WTF::String getAutoCorrectSuggestionForMisspelledWord(const WTF::String&);
+        virtual void checkGrammarOfString(const UChar*, int length, WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength);
+        virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses);
+        virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {}
+
+        void updateSpellCheckingLanguage(const char*);
+        static void freeSpellCheckingLanguage(gpointer, gpointer);
+    private:
+        WebKitWebView* m_webView;
+        GSList* m_enchantDicts;
+        static EnchantBroker* broker;
+    };
+}
+#endif
+
index ff5289b..d098103 100644 (file)
@@ -34,7 +34,6 @@
 #include "webkitglobalsprivate.h"
 #include "webkitversion.h"
 #include "webkitwebsettingsprivate.h"
-#include <enchant.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/StringConcatenate.h>
 #include <glib/gi18n-lib.h>
@@ -90,7 +89,6 @@ struct _WebKitWebSettingsPrivate {
     gboolean enable_private_browsing;
     gboolean enable_spell_checking;
     gchar* spell_checking_languages;
-    GSList* enchant_dicts;
     gboolean enable_caret_browsing;
     gboolean enable_html5_database;
     gboolean enable_html5_local_storage;
@@ -920,23 +918,6 @@ static void webkit_web_settings_init(WebKitWebSettings* web_settings)
     web_settings->priv = G_TYPE_INSTANCE_GET_PRIVATE(web_settings, WEBKIT_TYPE_WEB_SETTINGS, WebKitWebSettingsPrivate);
 }
 
-static EnchantBroker* get_enchant_broker()
-{
-    static EnchantBroker* broker = 0;
-    if (!broker)
-        broker = enchant_broker_init();
-
-    return broker;
-}
-
-static void free_spell_checking_language(gpointer data, gpointer user_data)
-{
-    EnchantDict* dict = static_cast<EnchantDict*>(data);
-    EnchantBroker* broker = get_enchant_broker();
-
-    enchant_broker_free_dict(broker, dict);
-}
-
 static void webkit_web_settings_finalize(GObject* object)
 {
     WebKitWebSettings* web_settings = WEBKIT_WEB_SETTINGS(object);
@@ -952,28 +933,15 @@ static void webkit_web_settings_finalize(GObject* object)
     g_free(priv->user_stylesheet_uri);
     g_free(priv->spell_checking_languages);
 
-    g_slist_foreach(priv->enchant_dicts, free_spell_checking_language, 0);
-    g_slist_free(priv->enchant_dicts);
-
     g_free(priv->user_agent);
 
     G_OBJECT_CLASS(webkit_web_settings_parent_class)->finalize(object);
 }
 
-static void getAvailableDictionariesCallback(const char* const languageTag, const char* const, const char* const, const char* const, void* data)
-{
-    Vector<CString>* dicts = static_cast<Vector<CString>*>(data);
-
-    dicts->append(languageTag);
-}
-
 static void webkit_web_settings_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
 {
     WebKitWebSettings* web_settings = WEBKIT_WEB_SETTINGS(object);
     WebKitWebSettingsPrivate* priv = web_settings->priv;
-    EnchantBroker* broker;
-    EnchantDict* dict;
-    GSList* spellDictionaries = 0;
 
     switch(prop_id) {
     case PROP_DEFAULT_ENCODING:
@@ -1065,35 +1033,6 @@ static void webkit_web_settings_set_property(GObject* object, guint prop_id, con
     case PROP_SPELL_CHECKING_LANGUAGES:
         g_free(priv->spell_checking_languages);
         priv->spell_checking_languages = g_strdup(g_value_get_string(value));
-
-        broker = get_enchant_broker();
-        if (priv->spell_checking_languages) {
-            char** langs = g_strsplit(priv->spell_checking_languages, ",", -1);
-            for (int i = 0; langs[i]; i++) {
-                if (enchant_broker_dict_exists(broker, langs[i])) {
-                    dict = enchant_broker_request_dict(broker, langs[i]);
-                    spellDictionaries = g_slist_append(spellDictionaries, dict);
-                }
-            }
-            g_strfreev(langs);
-        } else {
-            const char* language = pango_language_to_string(gtk_get_default_language());
-            if (enchant_broker_dict_exists(broker, language)) {
-                dict = enchant_broker_request_dict(broker, language);
-                spellDictionaries = g_slist_append(spellDictionaries, dict);
-            } else {
-                // No dictionaries selected, we get one from the list
-                Vector<CString> allDictionaries;
-                enchant_broker_list_dicts(broker, getAvailableDictionariesCallback, &allDictionaries);
-                if (!allDictionaries.isEmpty()) {
-                    dict = enchant_broker_request_dict(broker, allDictionaries[0].data());
-                    spellDictionaries = g_slist_append(spellDictionaries, dict);
-                }
-            }
-        }
-        g_slist_foreach(priv->enchant_dicts, free_spell_checking_language, 0);
-        g_slist_free(priv->enchant_dicts);
-        priv->enchant_dicts = spellDictionaries;
         break;
     case PROP_ENABLE_XSS_AUDITOR:
         priv->enable_xss_auditor = g_value_get_boolean(value);
@@ -1421,15 +1360,6 @@ G_CONST_RETURN gchar* webkit_web_settings_get_user_agent(WebKitWebSettings* webS
     return priv->user_agent;
 }
 
-GSList* webkitWebViewGetEnchantDicts(WebKitWebView* webView)
-{
-    g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
-
-    WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
-
-    return settings->priv->enchant_dicts;
-}
-
 namespace WebKit {
 
 WebCore::EditingBehaviorType core(WebKitEditingBehavior type)
index d2b0ae0..bbf6c24 100644 (file)
@@ -3485,6 +3485,12 @@ static void webkit_web_view_settings_notify(WebKitWebSettings* webSettings, GPar
         settings->setJavaEnabled(g_value_get_boolean(&value));
     else if (name == g_intern_string("enable-hyperlink-auditing"))
         settings->setHyperlinkAuditingEnabled(g_value_get_boolean(&value));
+#if ENABLE(SPELLCHECK)
+    else if (name == g_intern_string("spell-checking-languages")) {
+        WebKit::EditorClient* client = static_cast<WebKit::EditorClient*>(core(webView)->editorClient());
+        static_cast<WebKit::TextCheckerClientEnchant*>(client->textChecker())->updateSpellCheckingLanguage(g_value_get_string(&value));
+    }
+#endif
     else if (!g_object_class_find_property(G_OBJECT_GET_CLASS(webSettings), name))
         g_warning("Unexpected setting '%s'", name);
     g_value_unset(&value);
index cf6ac76..d42d185 100644 (file)
@@ -286,9 +286,17 @@ PKG_CHECK_MODULES(PANGO,
 AC_SUBST(PANGO_CFLAGS)
 AC_SUBST(PANGO_LIBS)
 
-PKG_CHECK_MODULES(ENCHANT, enchant >= $ENCHANT_REQUIRED_VERSION)
+AC_MSG_CHECKING([whether to enable spellcheck support])
+AC_ARG_ENABLE([spellcheck],
+  [AS_HELP_STRING([--enable-spellcheck],[enable support for spellcheck])],
+  [],[enable_spellcheck="yes"])
+AC_MSG_RESULT([$enable_spellcheck])
+
+if test "$enable_spellcheck" = "yes"; then
+PKG_CHECK_MODULES(ENCHANT, enchant >= $ENCHANT_REQUIRED_VERSION, [], [enable_spellcheck="no"])
 AC_SUBST(ENCHANT_CFLAGS)
 AC_SUBST(ENCHANT_LIBS)
+fi
 
 PKG_CHECK_MODULES(GAIL, $GAIL_PC_NAME >= $GAIL_REQUIRED_VERSION)
 AC_SUBST(GAIL_CFLAGS)
@@ -1042,6 +1050,7 @@ AM_CONDITIONAL([ENABLE_WEB_AUDIO],[test "$enable_web_audio" = "yes"])
 AM_CONDITIONAL([ENABLE_WEB_TIMING],[test "$enable_web_timing" = "yes"])
 AM_CONDITIONAL([ENABLE_OPCODE_STATS],[test "$enable_opcode_stats" = "yes"])
 AM_CONDITIONAL([ENABLE_WEBKIT2],[test "$enable_webkit2" = "yes"])
+AM_CONDITIONAL([ENABLE_SPELLCHECK],[test "$enable_spellcheck" = "yes"])
 
 # Gtk conditionals
 AM_CONDITIONAL([ENABLE_INTROSPECTION],[test "$enable_introspection" = "yes"])
@@ -1131,6 +1140,7 @@ Features:
  XHTML-MP support                                         : $enable_xhtmlmp
  XPATH support                                            : $enable_xpath
  XSLT support                                             : $enable_xslt
+ Spellcheck support                                       : $enable_spellcheck
 
 GTK+ configuration:
  GTK+ version                                             : $with_gtk