Title: [124207] trunk/Source
Revision
124207
Author
ma...@webkit.org
Date
2012-07-31 08:51:29 -0700 (Tue, 31 Jul 2012)

Log Message

[GTK] Add a new and reusable enchant-based spellchecker in WebCore
https://bugs.webkit.org/show_bug.cgi?id=90269

Reviewed by Martin Robinson.

Source/WebCore:

Move enchant specific code down to WebCore, into a new class
TextCheckerEnchant, that we can use from WK1 and WK2.

* GNUmakefile.am: Add flags to handle the SPELLCHECK feature.
* GNUmakefile.list.am: Added new files.
* platform/text/gtk/TextCheckerEnchant.cpp: Added.
(getAvailableDictionariesCallback):
(TextCheckerEnchant::TextCheckerEnchant):
(TextCheckerEnchant::~TextCheckerEnchant):
(TextCheckerEnchant::ignoreWord):
(TextCheckerEnchant::learnWord):
(TextCheckerEnchant::checkSpellingOfString):
(TextCheckerEnchant::getGuessesForWord):
(TextCheckerEnchant::updateSpellCheckingLanguages):
(TextCheckerEnchant::freeEnchantBrokerDictionaries):
* platform/text/gtk/TextCheckerEnchant.h: Added.
(WebCore):
(TextCheckerEnchant):
(WebCore::TextCheckerEnchant::create):

Source/WebKit/gtk:

Remove enchant specific code from WebKitSpellCheckerEnchant and
implement it relying in the new TextCheckerEnchant class in WebCore.

* webkit/webkitspellcheckerenchant.cpp:
(_WebKitSpellCheckerEnchantPrivate):
(webkit_spell_checker_enchant_finalize):
(webkit_spell_checker_enchant_class_init):
(webkit_spell_checker_enchant_init):
(checkSpellingOfString):
(getGuessesForWord):
(updateSpellCheckingLanguages):
(learnWord):
(ignoreWord):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (124206 => 124207)


--- trunk/Source/WebCore/ChangeLog	2012-07-31 15:44:32 UTC (rev 124206)
+++ trunk/Source/WebCore/ChangeLog	2012-07-31 15:51:29 UTC (rev 124207)
@@ -1,3 +1,30 @@
+2012-07-31  Mario Sanchez Prada  <msanc...@igalia.com>
+
+        [GTK] Add a new and reusable enchant-based spellchecker in WebCore
+        https://bugs.webkit.org/show_bug.cgi?id=90269
+
+        Reviewed by Martin Robinson.
+
+        Move enchant specific code down to WebCore, into a new class
+        TextCheckerEnchant, that we can use from WK1 and WK2.
+
+        * GNUmakefile.am: Add flags to handle the SPELLCHECK feature.
+        * GNUmakefile.list.am: Added new files.
+        * platform/text/gtk/TextCheckerEnchant.cpp: Added.
+        (getAvailableDictionariesCallback):
+        (TextCheckerEnchant::TextCheckerEnchant):
+        (TextCheckerEnchant::~TextCheckerEnchant):
+        (TextCheckerEnchant::ignoreWord):
+        (TextCheckerEnchant::learnWord):
+        (TextCheckerEnchant::checkSpellingOfString):
+        (TextCheckerEnchant::getGuessesForWord):
+        (TextCheckerEnchant::updateSpellCheckingLanguages):
+        (TextCheckerEnchant::freeEnchantBrokerDictionaries):
+        * platform/text/gtk/TextCheckerEnchant.h: Added.
+        (WebCore):
+        (TextCheckerEnchant):
+        (WebCore::TextCheckerEnchant::create):
+
 2012-07-31  Joe Mason  <jma...@rim.com>
 
         [BlackBerry] Support Negotiate auth

Modified: trunk/Source/WebCore/GNUmakefile.am (124206 => 124207)


--- trunk/Source/WebCore/GNUmakefile.am	2012-07-31 15:44:32 UTC (rev 124206)
+++ trunk/Source/WebCore/GNUmakefile.am	2012-07-31 15:51:29 UTC (rev 124207)
@@ -117,7 +117,8 @@
 	-I$(srcdir)/Source/WebCore/platform/graphics/gstreamer \
 	-I$(srcdir)/Source/WebCore/platform/graphics/gtk \
 	-I$(srcdir)/Source/WebCore/platform/gtk \
-	-I$(srcdir)/Source/WebCore/platform/network/soup
+	-I$(srcdir)/Source/WebCore/platform/network/soup \
+	-I$(srcdir)/Source/WebCore/platform/text/gtk
 
 # ---
 # Features enabled by default at compilation time
@@ -748,6 +749,14 @@
 webcore_cppflags += -DENABLE_LINK_PREFETCH=1
 endif  # END ENABLE_LINK_PREFETCH
 
+# ---
+# Spell check support
+# ---
+if ENABLE_SPELLCHECK
+FEATURE_DEFINES += ENABLE_SPELLCHECK=1
+webcore_cppflags += -DENABLE_SPELLCHECK=1
+endif  # END ENABLE_SPELLCHECK
+
 DerivedSources/WebCore/CSSPropertyNames.cpp: DerivedSources/WebCore/CSSPropertyNames.h
 DerivedSources/WebCore/CSSPropertyNames.h: $(WEBCORE_CSS_PROPERTY_NAMES) $(WebCore)/css/makeprop.pl
 	$(AM_V_GEN)

Modified: trunk/Source/WebCore/GNUmakefile.list.am (124206 => 124207)


--- trunk/Source/WebCore/GNUmakefile.list.am	2012-07-31 15:44:32 UTC (rev 124206)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2012-07-31 15:51:29 UTC (rev 124207)
@@ -6299,3 +6299,13 @@
 	$(WebCore)/Modules/quota/StorageInfoUsageCallback.idl
 
 endif  # END ENABLE_QUOTA
+
+# ----
+# Spell check support
+# ----
+if ENABLE_SPELLCHECK
+webcore_sources += \
+	Source/WebCore/platform/text/gtk/TextCheckerEnchant.h \
+	Source/WebCore/platform/text/gtk/TextCheckerEnchant.cpp
+endif # END ENABLE_SPELLCHECK
+

Added: trunk/Source/WebCore/platform/text/gtk/TextCheckerEnchant.cpp (0 => 124207)


--- trunk/Source/WebCore/platform/text/gtk/TextCheckerEnchant.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/text/gtk/TextCheckerEnchant.cpp	2012-07-31 15:51:29 UTC (rev 124207)
@@ -0,0 +1,196 @@
+/*
+ *  Copyright (C) 2012 Igalia S.L.
+ *
+ *  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 "TextCheckerEnchant.h"
+
+#if ENABLE(SPELLCHECK)
+
+#include <pango/pango.h>
+#include <wtf/gobject/GOwnPtr.h>
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+
+static const size_t maximumNumberOfSuggestions = 10;
+
+static void getAvailableDictionariesCallback(const char* const languageTag, const char* const, const char* const, const char* const, void* data)
+{
+    Vector<CString>* dictionaries = static_cast<Vector<CString>*>(data);
+    dictionaries->append(languageTag);
+}
+
+static bool wordEndIsAContractionApostrophe(const char* string, long offset)
+{
+    if (g_utf8_get_char(g_utf8_offset_to_pointer(string, offset)) != g_utf8_get_char("'"))
+        return false;
+
+    // If this is the last character in the string, it cannot be the apostrophe part of a contraction.
+    if (offset == g_utf8_strlen(string, -1))
+        return false;
+
+    return g_unichar_isalpha(g_utf8_get_char(g_utf8_offset_to_pointer(string, offset + 1)));
+}
+
+TextCheckerEnchant::TextCheckerEnchant()
+    : m_broker(enchant_broker_init())
+    , m_enchantDictionaries(0)
+{
+}
+
+TextCheckerEnchant::~TextCheckerEnchant()
+{
+    if (!m_broker)
+        return;
+
+    freeEnchantBrokerDictionaries();
+    enchant_broker_free(m_broker);
+}
+
+void TextCheckerEnchant::ignoreWord(const String& word)
+{
+    for (Vector<EnchantDict*>::const_iterator iter = m_enchantDictionaries.begin(); iter != m_enchantDictionaries.end(); ++iter)
+        enchant_dict_add_to_session(*iter, word.utf8().data(), -1);
+}
+
+void TextCheckerEnchant::learnWord(const String& word)
+{
+    for (Vector<EnchantDict*>::const_iterator iter = m_enchantDictionaries.begin(); iter != m_enchantDictionaries.end(); ++iter)
+        enchant_dict_add_to_personal(*iter, word.utf8().data(), -1);
+}
+
+void TextCheckerEnchant::checkSpellingOfString(const String& string, int& misspellingLocation, int& misspellingLength)
+{
+    if (m_enchantDictionaries.isEmpty())
+        return;
+    Vector<EnchantDict*>::const_iterator dictIter = m_enchantDictionaries.begin();
+
+    GOwnPtr<gchar> cString(g_strdup(string.utf8().data()));
+    size_t length = string.utf8().length();
+
+    PangoLanguage* language(pango_language_get_default());
+    GOwnPtr<PangoLogAttr> attrs(g_new(PangoLogAttr, length + 1));
+
+    // pango_get_log_attrs uses an aditional position at the end of the text.
+    pango_get_log_attrs(cString.get(), -1, -1, language, attrs.get(), length + 1);
+
+    for (size_t 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  || wordEndIsAContractionApostrophe(cString.get(), end))
+                end++;
+
+            wordLength = end - start;
+            // Set the iterator to be at the current word end, so we don't
+            // check characters twice.
+            i = end;
+
+            gchar* cstart = g_utf8_offset_to_pointer(cString.get(), start);
+            gint bytes = static_cast<gint>(g_utf8_offset_to_pointer(cString.get(), end) - cstart);
+            GOwnPtr<gchar> word(g_new0(gchar, bytes + 1));
+
+            g_utf8_strncpy(word.get(), cstart, wordLength);
+
+            for (; dictIter != m_enchantDictionaries.end(); ++dictIter) {
+                if (enchant_dict_check(*dictIter, word.get(), wordLength)) {
+                    misspellingLocation = start;
+                    misspellingLength = wordLength;
+                } else {
+                    // Stop checking, this word is ok in at least one dict.
+                    misspellingLocation = -1;
+                    misspellingLength = 0;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+Vector<String> TextCheckerEnchant::getGuessesForWord(const String& word)
+{
+    Vector<String> guesses;
+    if (m_enchantDictionaries.isEmpty())
+        return guesses;
+
+    for (Vector<EnchantDict*>::const_iterator iter = m_enchantDictionaries.begin(); iter != m_enchantDictionaries.end(); ++iter) {
+        size_t numberOfSuggestions;
+        size_t i;
+
+        gchar** suggestions = enchant_dict_suggest(*iter, word.utf8().data(), -1, &numberOfSuggestions);
+        if (numberOfSuggestions <= 0)
+            continue;
+
+        if (numberOfSuggestions > maximumNumberOfSuggestions)
+            numberOfSuggestions = maximumNumberOfSuggestions;
+
+        for (i = 0; i < numberOfSuggestions; i++)
+            guesses.append(String(suggestions[i]));
+
+        enchant_dict_free_suggestions(*iter, suggestions);
+    }
+
+    return guesses;
+}
+
+void TextCheckerEnchant::updateSpellCheckingLanguages(const String& languages)
+{
+    Vector<EnchantDict*> spellDictionaries;
+
+    if (!languages.isEmpty()) {
+        Vector<String> languagesVector;
+        languages.split(static_cast<UChar>(','), languagesVector);
+        for (Vector<String>::const_iterator iter = languagesVector.begin(); iter != languagesVector.end(); ++iter) {
+            GOwnPtr<gchar> currentLanguage(g_strdup(iter->utf8().data()));
+            if (enchant_broker_dict_exists(m_broker, currentLanguage.get())) {
+                EnchantDict* dict = enchant_broker_request_dict(m_broker, currentLanguage.get());
+                spellDictionaries.append(dict);
+            }
+        }
+    } else {
+        const char* language = pango_language_to_string(pango_language_get_default());
+        if (enchant_broker_dict_exists(m_broker, language)) {
+            EnchantDict* dict = enchant_broker_request_dict(m_broker, language);
+            spellDictionaries.append(dict);
+        } else {
+            // No dictionaries selected, we get one from the list.
+            Vector<CString> allDictionaries;
+            enchant_broker_list_dicts(m_broker, getAvailableDictionariesCallback, &allDictionaries);
+            if (!allDictionaries.isEmpty()) {
+                EnchantDict* dict = enchant_broker_request_dict(m_broker, allDictionaries[0].data());
+                spellDictionaries.append(dict);
+            }
+        }
+    }
+    freeEnchantBrokerDictionaries();
+    m_enchantDictionaries = spellDictionaries;
+}
+
+void TextCheckerEnchant::freeEnchantBrokerDictionaries()
+{
+    for (Vector<EnchantDict*>::const_iterator iter = m_enchantDictionaries.begin(); iter != m_enchantDictionaries.end(); ++iter)
+        enchant_broker_free_dict(m_broker, *iter);
+}
+
+#endif // ENABLE(SPELLCHECK)
+

Added: trunk/Source/WebCore/platform/text/gtk/TextCheckerEnchant.h (0 => 124207)


--- trunk/Source/WebCore/platform/text/gtk/TextCheckerEnchant.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/text/gtk/TextCheckerEnchant.h	2012-07-31 15:51:29 UTC (rev 124207)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TextCheckerEnchant_h
+#define TextCheckerEnchant_h
+
+#if ENABLE(SPELLCHECK)
+
+#include <enchant.h>
+#include <wtf/FastAllocBase.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class TextCheckerEnchant {
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    static PassOwnPtr<TextCheckerEnchant> create() { return adoptPtr(new TextCheckerEnchant); }
+    virtual ~TextCheckerEnchant();
+
+    void ignoreWord(const String&);
+    void learnWord(const String&);
+    void checkSpellingOfString(const String&, int& misspellingLocation, int& misspellingLength);
+    Vector<String> getGuessesForWord(const String&);
+    void updateSpellCheckingLanguages(const String& languages);
+
+private:
+    TextCheckerEnchant();
+    void freeEnchantBrokerDictionaries();
+
+    EnchantBroker* m_broker;
+    Vector<EnchantDict*> m_enchantDictionaries;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SPELLCHECK)
+
+#endif

Modified: trunk/Source/WebKit/gtk/ChangeLog (124206 => 124207)


--- trunk/Source/WebKit/gtk/ChangeLog	2012-07-31 15:44:32 UTC (rev 124206)
+++ trunk/Source/WebKit/gtk/ChangeLog	2012-07-31 15:51:29 UTC (rev 124207)
@@ -1,3 +1,24 @@
+2012-07-31  Mario Sanchez Prada  <msanc...@igalia.com>
+
+        [GTK] Add a new and reusable enchant-based spellchecker in WebCore
+        https://bugs.webkit.org/show_bug.cgi?id=90269
+
+        Reviewed by Martin Robinson.
+
+        Remove enchant specific code from WebKitSpellCheckerEnchant and
+        implement it relying in the new TextCheckerEnchant class in WebCore.
+
+        * webkit/webkitspellcheckerenchant.cpp:
+        (_WebKitSpellCheckerEnchantPrivate):
+        (webkit_spell_checker_enchant_finalize):
+        (webkit_spell_checker_enchant_class_init):
+        (webkit_spell_checker_enchant_init):
+        (checkSpellingOfString):
+        (getGuessesForWord):
+        (updateSpellCheckingLanguages):
+        (learnWord):
+        (ignoreWord):
+
 2012-07-30  Martin Robinson  <mrobin...@igalia.com>
 
         [GTK] New lines automatically and repeatedly added to list items in Etherpad

Modified: trunk/Source/WebKit/gtk/webkit/webkitspellcheckerenchant.cpp (124206 => 124207)


--- trunk/Source/WebKit/gtk/webkit/webkitspellcheckerenchant.cpp	2012-07-31 15:44:32 UTC (rev 124206)
+++ trunk/Source/WebKit/gtk/webkit/webkitspellcheckerenchant.cpp	2012-07-31 15:51:29 UTC (rev 124207)
@@ -21,12 +21,15 @@
 
 #if ENABLE(SPELLCHECK)
 
+#include "TextCheckerEnchant.h"
 #include "webkitspellchecker.h"
-#include <enchant.h>
 #include <gtk/gtk.h>
+#include <wtf/OwnPtr.h>
 #include <wtf/gobject/GOwnPtr.h>
 #include <wtf/text/CString.h>
 
+using namespace WebCore;
+
 /**
  * SECTION:webkitspellcheckerenchant
  * @short_description: the default spell checking implementation for WebKitGTK+.
@@ -35,10 +38,9 @@
  * WebKitGTK+. It uses the Enchant dictionaries installed on the system to
  * correct spelling.
  */
-static EnchantBroker* broker = 0;
 
 struct _WebKitSpellCheckerEnchantPrivate {
-    GSList* enchantDicts;
+    OwnPtr<TextCheckerEnchant> textCheckerEnchant;
 };
 
 static void webkit_spell_checker_enchant_spell_checker_interface_init(WebKitSpellCheckerInterface* interface);
@@ -47,35 +49,16 @@
                         G_IMPLEMENT_INTERFACE(WEBKIT_TYPE_SPELL_CHECKER,
                                               webkit_spell_checker_enchant_spell_checker_interface_init))
 
-static void createEnchantBrokerIfNeeded()
-{
-    if (!broker)
-        broker = enchant_broker_init();
-}
-
-static void freeSpellCheckingLanguage(gpointer data, gpointer)
-{
-    createEnchantBrokerIfNeeded();
-
-    enchant_broker_free_dict(broker, static_cast<EnchantDict*>(data));
-}
-
 static void webkit_spell_checker_enchant_finalize(GObject* object)
 {
     WebKitSpellCheckerEnchantPrivate* priv = WEBKIT_SPELL_CHECKER_ENCHANT(object)->priv;
-
-    g_slist_foreach(priv->enchantDicts, freeSpellCheckingLanguage, 0);
-    g_slist_free(priv->enchantDicts);
-
-    WEBKIT_SPELL_CHECKER_ENCHANT(object)->priv->~WebKitSpellCheckerEnchantPrivate();
+    priv->~WebKitSpellCheckerEnchantPrivate();
 }
 
 static void webkit_spell_checker_enchant_class_init(WebKitSpellCheckerEnchantClass* klass)
 {
     GObjectClass* objectClass = G_OBJECT_CLASS(klass);
-
     objectClass->finalize = webkit_spell_checker_enchant_finalize;
-
     g_type_class_add_private(klass, sizeof(WebKitSpellCheckerEnchantPrivate));
 }
 
@@ -85,149 +68,38 @@
     checker->priv = priv;
     new (priv) WebKitSpellCheckerEnchantPrivate();
 
-    priv->enchantDicts = 0;
+    priv->textCheckerEnchant = TextCheckerEnchant::create();
 }
 
-static bool wordEndIsAContractionApostrophe(const char* string, long offset)
-{
-    if (g_utf8_get_char(g_utf8_offset_to_pointer(string, offset)) != g_utf8_get_char("'"))
-        return false;
-
-    // If this is the last character in the string, it cannot be the apostrophe part of a contraction.
-    if (offset == g_utf8_strlen(string, -1))
-        return false;
-
-    return g_unichar_isalpha(g_utf8_get_char(g_utf8_offset_to_pointer(string, offset + 1)));
-}
-
 static void checkSpellingOfString(WebKitSpellChecker* checker, const char* string, int* misspellingLocation, int* misspellingLength)
 {
     WebKitSpellCheckerEnchantPrivate* priv = WEBKIT_SPELL_CHECKER_ENCHANT(checker)->priv;
-
-    GSList* dicts = priv->enchantDicts;
-    if (!dicts)
-        return;
-
-    int length = g_utf8_strlen(string, -1);
-
-    PangoLanguage* language(pango_language_get_default());
-    GOwnPtr<PangoLogAttr> attrs(g_new(PangoLogAttr, length + 1));
-
-    // pango_get_log_attrs uses an aditional position at the end of the text.
-    pango_get_log_attrs(string, -1, -1, language, attrs.get(), length + 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 || wordEndIsAContractionApostrophe(string, end))
-                end++;
-
-            wordLength = end - start;
-            // Set the iterator to be at the current word end, so we don't
-            // check characters twice.
-            i = end;
-
-            gchar* cstart = g_utf8_offset_to_pointer(string, start);
-            gint bytes = static_cast<gint>(g_utf8_offset_to_pointer(string, end) - cstart);
-            GOwnPtr<gchar> word(g_new0(gchar, bytes + 1));
-
-            g_utf8_strncpy(word.get(), cstart, wordLength);
-
-            for (; dicts; dicts = dicts->next) {
-                EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
-                if (enchant_dict_check(dict, word.get(), wordLength)) {
-                    *misspellingLocation = start;
-                    *misspellingLength = wordLength;
-                } else {
-                    // Stop checking, this word is ok in at least one dict.
-                    *misspellingLocation = -1;
-                    *misspellingLength = 0;
-                    break;
-                }
-            }
-        }
-    }
+    priv->textCheckerEnchant->checkSpellingOfString(String::fromUTF8(string), *misspellingLocation, *misspellingLength);
 }
 
 static char** getGuessesForWord(WebKitSpellChecker* checker, const char* word, const char* context)
 {
     WebKitSpellCheckerEnchantPrivate* priv = WEBKIT_SPELL_CHECKER_ENCHANT(checker)->priv;
 
-    GSList* dicts = priv->enchantDicts;
-    char** guesses = 0;
+    Vector<String> guesses = priv->textCheckerEnchant->getGuessesForWord(String::fromUTF8(word));
 
-    for (; dicts; dicts = dicts->next) {
-        size_t numberOfSuggestions;
-        size_t i;
+    if (guesses.isEmpty())
+        return 0;
 
-        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
-        gchar** suggestions = enchant_dict_suggest(dict, word, -1, &numberOfSuggestions);
+    int i = 0;
+    int numberOfGuesses = guesses.size();
+    char** guessesArray = static_cast<char**>(g_malloc0((numberOfGuesses + 1) * sizeof(char*)));
+    for (Vector<String>::const_iterator iter = guesses.begin(); iter != guesses.end(); ++iter)
+        guessesArray[i++] = g_strdup(iter->utf8().data());
+    guessesArray[i] = 0;
 
-        if (numberOfSuggestions > 0) {
-            if (numberOfSuggestions > 10)
-                numberOfSuggestions = 10;
-
-            guesses = static_cast<char**>(g_malloc0((numberOfSuggestions + 1) * sizeof(char*)));
-            for (i = 0; i < numberOfSuggestions && i < 10; i++)
-                guesses[i] = g_strdup(suggestions[i]);
-
-            guesses[i] = 0;
-
-            enchant_dict_free_suggestions(dict, suggestions);
-        }
-    }
-
-    return guesses;
+    return guessesArray;
 }
 
-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 updateSpellCheckingLanguages(WebKitSpellChecker* checker, const char* languages)
 {
-    GSList* spellDictionaries = 0;
-
     WebKitSpellCheckerEnchantPrivate* priv = WEBKIT_SPELL_CHECKER_ENCHANT(checker)->priv;
-
-    createEnchantBrokerIfNeeded();
-
-    if (languages) {
-        char** langs = g_strsplit(languages, ",", -1);
-        for (int i = 0; langs[i]; i++) {
-            if (enchant_broker_dict_exists(broker, langs[i])) {
-                EnchantDict* 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)) {
-            EnchantDict* 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()) {
-                EnchantDict* dict = enchant_broker_request_dict(broker, allDictionaries[0].data());
-                spellDictionaries = g_slist_append(spellDictionaries, dict);
-            }
-        }
-    }
-    g_slist_foreach(priv->enchantDicts, freeSpellCheckingLanguage, 0);
-    g_slist_free(priv->enchantDicts);
-    priv->enchantDicts = spellDictionaries;
+    priv->textCheckerEnchant->updateSpellCheckingLanguages(String::fromUTF8(languages));
 }
 
 static char* getAutocorrectSuggestionsForMisspelledWord(WebKitSpellChecker* checker, const char* word)
@@ -238,25 +110,13 @@
 static void learnWord(WebKitSpellChecker* checker, const char* word)
 {
     WebKitSpellCheckerEnchantPrivate* priv = WEBKIT_SPELL_CHECKER_ENCHANT(checker)->priv;
-    GSList* dicts = priv->enchantDicts;
-
-    for (; dicts; dicts = dicts->next) {
-        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
-
-        enchant_dict_add_to_personal(dict, word, -1);
-    }
+    priv->textCheckerEnchant->learnWord(String::fromUTF8(word));
 }
 
 static void ignoreWord(WebKitSpellChecker* checker, const char* word)
 {
     WebKitSpellCheckerEnchantPrivate* priv = WEBKIT_SPELL_CHECKER_ENCHANT(checker)->priv;
-    GSList* dicts = priv->enchantDicts;
-
-    for (; dicts; dicts = dicts->next) {
-        EnchantDict* dict = static_cast<EnchantDict*>(dicts->data);
-
-        enchant_dict_add_to_session(dict, word, -1);
-    }
+    priv->textCheckerEnchant->ignoreWord(String::fromUTF8(word));
 }
 
 static void webkit_spell_checker_enchant_spell_checker_interface_init(WebKitSpellCheckerInterface* interface)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to