diff options
Diffstat (limited to 'extra/kdeplasma-addons/fix-spell-crash.patch')
-rw-r--r-- | extra/kdeplasma-addons/fix-spell-crash.patch | 267 |
1 files changed, 0 insertions, 267 deletions
diff --git a/extra/kdeplasma-addons/fix-spell-crash.patch b/extra/kdeplasma-addons/fix-spell-crash.patch deleted file mode 100644 index 75c26c6ad..000000000 --- a/extra/kdeplasma-addons/fix-spell-crash.patch +++ /dev/null @@ -1,267 +0,0 @@ -commit 124e35885b8cd1b593b7b83a070bd0bdb5758661 -Author: Simeon Bird <bladud@gmail.com> -Date: Fri Oct 19 21:16:34 2012 -0400 - - Fix the plasma spellchecker's 'foreign language' support. - Previously this caused segfaults (even if not used) because - it called setLanguage(), which is not thread-safe, in match(). - - Instead, this patch constructs a new speller safely for each new - language, without deleting the old one. Old spellers are instead - deleted on the teardown() signal. - - While we're at it, amend the language detection so that the user - can type natural language names (eg, 'german') and have the - spell-checker find the right language. - - REVIEW: 106244 - BUG: 303831 - BUG: 264779 - FIXED-IN: 4.9.3 - -diff --git a/runners/spellchecker/spellcheck.cpp b/runners/spellchecker/spellcheck.cpp -index 672732d..cc6aeb2 100644 ---- a/runners/spellchecker/spellcheck.cpp -+++ b/runners/spellchecker/spellcheck.cpp -@@ -24,6 +24,7 @@ - // #include <KDebug> - #include <KGlobal> - #include <KIcon> -+#include <QSet> - - SpellCheckRunner::SpellCheckRunner(QObject* parent, const QVariantList &args) - : Plasma::AbstractRunner(parent, args) -@@ -43,13 +44,64 @@ void SpellCheckRunner::init() - { - Plasma::AbstractRunner::init(); - -- //store all language names, makes it posible to type "spell german TERM" if english locale is set -+ //Connect prepare and teardown signals -+ connect(this, SIGNAL(prepare()), this, SLOT(loaddata())); -+ connect(this, SIGNAL(teardown()), this, SLOT(destroydata())); -+} -+ -+//Load a default dictionary and some locale names -+void SpellCheckRunner::loaddata() -+{ -+ //Load the default speller, with the default language -+ if (!m_spellers.contains("")) { -+ m_spellers[""] = QSharedPointer<Sonnet::Speller> (new Sonnet::Speller("")); -+ } -+ //store all language names, makes it possible to type "spell german TERM" if english locale is set -+ //Need to construct a map between natual language names and names the spell-check recognises. - KLocale *locale = KGlobal::locale(); -- QStringList codes = locale->allLanguagesList(); -- foreach (const QString &code, codes) { -- const QString name = locale->languageCodeToName(code); -- m_languages[name.toLower()] = code; -+ const QStringList avail = m_spellers[""]->availableLanguages(); -+ //We need to filter the available languages so that we associate the natural language -+ //name (eg. 'german') with one sub-code. -+ QSet<QString> families; -+ //First get the families -+ foreach (const QString &code, avail) { -+ families +=code.left(2); -+ } -+ //Now for each family figure out which is the main code. -+ foreach (const QString &fcode,families) { -+ QStringList family = avail.filter(fcode); -+ QString code; -+ //If we only have one code, use it. -+ //If a string is the default language, use it -+ if (family.contains(m_spellers[""]->language())) { -+ code = m_spellers[""]->language(); -+ } else if (fcode == QLatin1String("en")) { -+ //If the family is english, default to en_US. -+ if (family.contains("en_US")) { -+ code = QLatin1String("en_US"); -+ } -+ } else if (family.contains(fcode+QLatin1String("_")+fcode.toUpper())) { -+ //If we have a speller of the form xx_XX, try that. -+ //This gets us most European languages with more than one spelling. -+ code = fcode+QLatin1String("_")+fcode.toUpper(); -+ } else { -+ //Otherwise, pick the first value as it is highest priority. -+ code = family.first(); -+ } -+ //Finally, add code to the map. -+ const QString name = locale->languageCodeToName(fcode); -+ if (!name.isEmpty()) { -+ m_languages[name.toLower()] = code; -+ } -+// kDebug() << "SPELL lang: " << fcode<< "::"<< name << " : " << code; - } -+ -+} -+ -+void SpellCheckRunner::destroydata() -+{ -+ //Clear the data arrays to save memory -+ m_spellers.clear(); - } - - void SpellCheckRunner::reloadConfiguration() -@@ -73,13 +125,52 @@ void SpellCheckRunner::reloadConfiguration() - setSyntaxes(syns); - } - -+/* Take the input query, split into a list, and see if it contains a language to spell in. -+ * Return the empty string if we can't match a language. */ -+QString SpellCheckRunner::findlang(const QStringList& terms) -+{ -+ //If first term is a language code (like en_GB), set it as the spell-check language -+ if (terms.count() >= 1 && m_spellers[""]->availableLanguages().contains(terms[0])) { -+ return terms[0]; -+ } -+ //If we have two terms and the first is a language name (eg 'french'), -+ //set it as the available language -+ else if (terms.count() >=2) { -+ QString code; -+ { -+ //Is this a descriptive language name? -+ QMap<QString, QString>::const_iterator it = m_languages.constFind(terms[0].toLower()); -+ if (it != m_languages.constEnd()) { -+ code = *it; -+ } -+ //Maybe it is a subset of a language code? -+ else { -+ QStringList codes = QStringList(m_languages.values()).filter(terms[0]); -+ if (!codes.isEmpty()) { -+ code = codes.first(); -+ } -+ } -+ } -+ -+ if (!code.isEmpty()) { -+ //We found a valid language! Check still available -+ const QStringList avail = m_spellers[""]->availableLanguages(); -+ //Does the spell-checker like it? -+ if (avail.contains(code)) { -+ return code; -+ } -+ } -+ //FIXME: Support things like 'british english' or 'canadian french' -+ } -+ return QLatin1String(""); -+} -+ - void SpellCheckRunner::match(Plasma::RunnerContext &context) - { - if (!context.isValid()) { - return; - } - -- - const QString term = context.query(); - QString query = term; - -@@ -88,53 +179,46 @@ void SpellCheckRunner::match(Plasma::RunnerContext &context) - if (query.left(len) != m_triggerWord) { - return; - } -- -- QString language = m_speller.defaultLanguage(); - query = query.mid(len).trimmed(); -- QStringList terms = query.split(' '); -- -- //two terms specified, check if first is a language -- QString customLanguage; -- if (terms.count() == 2) { -- customLanguage = terms[0]; -- query = terms[1]; -- } -- //three terms specified, check if first two are a language, e.g. "american english" -- if (terms.count() == 3) { -- customLanguage = terms[0] + ' ' + terms[1]; -- query = terms[2]; -- } -- -- if (!customLanguage.isEmpty()) { -- language = customLanguage; -- m_speller.setLanguage(language); -+ } - -- //not valid, maybe it is a language name, not a code -- if (!m_speller.isValid()) { -- QHash<QString, QString>::const_iterator it = m_languages.constFind(language.toLower()); -- //is a valid language name -- if (it != m_languages.constEnd()) { -- language = *it; -+ //Pointer to speller object with our chosen language -+ QSharedPointer<Sonnet::Speller> speller = m_spellers[""]; -+ -+ if (speller->isValid()) { -+ QStringList terms = query.split(' ', QString::SkipEmptyParts); -+ QString lang = findlang(terms); -+ //If we found a language, create a new speller object using it. -+ if (!lang.isEmpty()) { -+ //First term is the language -+ terms.removeFirst(); -+ //New speller object if we don't already have one -+ if (!m_spellers.contains(lang)) { -+ QMutexLocker lock (&m_spellLock); -+ //Check nothing happened while we were acquiring the lock -+ if (!m_spellers.contains(lang)) { -+ m_spellers[lang] = QSharedPointer<Sonnet::Speller>(new Sonnet::Speller(lang)); - } - } -+ speller = m_spellers[lang]; -+ //Rejoin the strings -+ query = terms.join(QLatin1String(" ")); - } -- -- m_speller.setLanguage(language); - } - -- if (query.size() < 3) { -+ if (query.size() < 2) { - return; - } - - Plasma::QueryMatch match(this); - match.setType(Plasma::QueryMatch::InformationalMatch); - -- if (m_speller.isValid()) { -+ if (speller->isValid()) { - QStringList suggestions; -- const bool correct = m_speller.checkAndSuggest(query,suggestions); -+ const bool correct = speller->checkAndSuggest(query,suggestions); - if (correct) { - match.setIcon(KIcon(QLatin1String( "checkbox" ))); -- match.setText(i18n("Correct")); -+ match.setText(i18n("Correct")+QLatin1String(": ")+query); - } else { - match.setIcon(KIcon(QLatin1String( "edit-delete" ))); - const QString recommended = i18n("Suggested words: %1", suggestions.join(i18nc("seperator for a list of words", ", "))); -diff --git a/runners/spellchecker/spellcheck.h b/runners/spellchecker/spellcheck.h -index 492c370..ca65452 100644 ---- a/runners/spellchecker/spellcheck.h -+++ b/runners/spellchecker/spellcheck.h -@@ -22,6 +22,7 @@ - #include <sonnet/speller.h> - - #include <plasma/abstractrunner.h> -+#include <QSharedPointer> - - /** - * This checks the spelling of query -@@ -41,12 +42,17 @@ public: - - protected slots: - void init(); -+ void loaddata(); -+ void destroydata(); - - private: -+ QString findlang(const QStringList &terms); -+ - QString m_triggerWord; -- QHash<QString, QString> m_languages;//key=language name, value=language code -+ QMap<QString, QString> m_languages;//key=language name, value=language code - bool m_requireTriggerWord; -- Sonnet::Speller m_speller; -+ QMap<QString, QSharedPointer<Sonnet::Speller> > m_spellers; //spellers -+ QMutex m_spellLock; //Lock held when constructing a new speller - }; - - K_EXPORT_PLASMA_RUNNER(spellcheckrunner, SpellCheckRunner) |