]> git.lyx.org Git - lyx.git/blob - src/EnchantChecker.cpp
6b53d2bac568626869012ebad9b43ea03b33b558
[lyx.git] / src / EnchantChecker.cpp
1 /**
2  * \file EnchantChecker.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Caolán McNamara
7  * \author Jürgen Spitzmüller
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include <enchant++.h>
15
16 #include "EnchantChecker.h"
17 #include "LyXRC.h"
18 #include "WordLangTuple.h"
19
20 #include "support/lassert.h"
21 #include "support/debug.h"
22 #include "support/docstring_list.h"
23
24 #include <map>
25 #include <string>
26
27 using namespace std;
28
29 namespace lyx {
30
31 namespace {
32
33 struct Speller {
34         enchant::Dict * speller;
35 };
36
37 typedef map<string, Speller> Spellers;
38   
39 } // anon namespace
40
41 struct EnchantChecker::Private
42 {
43         Private()
44         {}
45
46         ~Private();
47
48         /// add a speller of the given language
49         enchant::Dict * addSpeller(string const & lang);
50
51         ///
52         enchant::Dict * speller(string const & lang);
53
54         /// the spellers
55         Spellers spellers_;
56 };
57
58
59 EnchantChecker::Private::~Private()
60 {
61         Spellers::iterator it = spellers_.begin();
62         Spellers::iterator end = spellers_.end();
63
64         for (; it != end; ++it)
65                 delete it->second.speller;
66 }
67
68
69 enchant::Dict * EnchantChecker::Private::addSpeller(string const & lang)
70 {
71         enchant::Broker * instance = enchant::Broker::instance();
72         Speller m;
73
74         try {
75                 LYXERR(Debug::FILES, "request enchant speller for language " << lang);
76                 m.speller = instance->request_dict(lang);
77         }
78         catch (const enchant::Exception & e) {
79                 // FIXME error handling?
80                 // unfortunately the message of enchant::Exception is unreachable
81                 LYXERR(Debug::FILES, "cannot add enchant speller, unspecified enchant exception in request_dict().");
82                 m.speller = 0;
83         }
84         spellers_[lang] = m;
85         return m.speller;
86 }
87
88
89 enchant::Dict * EnchantChecker::Private::speller(string const & lang)
90 {
91         Spellers::iterator it = spellers_.find(lang);
92         if (it != spellers_.end())
93                 return it->second.speller;
94         
95         return addSpeller(lang);
96 }
97
98
99 EnchantChecker::EnchantChecker()
100         : d(new Private)
101 {}
102
103
104 EnchantChecker::~EnchantChecker()
105 {
106         delete d;
107 }
108
109
110 SpellChecker::Result EnchantChecker::check(WordLangTuple const & word)
111 {
112         enchant::Dict * m = d->speller(word.lang()->code());
113
114         if (!m)
115                 return NO_DICTIONARY;
116
117         if (word.word().empty())
118                 return WORD_OK;
119
120         string utf8word = to_utf8(word.word());
121
122         if (m->check(utf8word))
123                 return WORD_OK;
124
125         return UNKNOWN_WORD;
126 }
127
128
129 void EnchantChecker::advanceChangeNumber()
130 {
131         nextChangeNumber();
132 }
133
134
135 void EnchantChecker::insert(WordLangTuple const & word)
136 {
137         enchant::Dict * m = d->speller(word.lang()->code());
138         if (m) {
139                 m->add(to_utf8(word.word()));
140                 advanceChangeNumber();
141         }
142 }
143         
144         
145 void EnchantChecker::remove(WordLangTuple const & word)
146 {
147         enchant::Dict * m = d->speller(word.lang()->code());
148         if (m) {
149                 m->remove(to_utf8(word.word()));
150                 advanceChangeNumber();
151         }
152 }
153
154
155 void EnchantChecker::accept(WordLangTuple const & word)
156 {
157         enchant::Dict * m = d->speller(word.lang()->code());
158         if (m) {
159                 m->add_to_session(to_utf8(word.word()));
160                 advanceChangeNumber();
161         }
162 }
163
164
165 void EnchantChecker::suggest(WordLangTuple const & wl,
166         docstring_list & suggestions)
167 {
168         suggestions.clear();
169         enchant::Dict * m = d->speller(wl.lang()->code());
170
171         if (!m)
172                 return;
173
174         string utf8word = to_utf8(wl.word());
175
176         vector<string> suggs = m->suggest(utf8word);
177         vector<string>::const_iterator it = suggs.begin();
178         
179         for (; it != suggs.end(); ++it)
180                 suggestions.push_back(from_utf8(*it));
181 }
182
183
184 bool EnchantChecker::hasDictionary(Language const * lang) const
185 {
186         if (!lang)
187                 return false;
188         enchant::Broker * instance = enchant::Broker::instance();
189         return (instance->dict_exists(lang->code()));
190 }
191
192
193 int EnchantChecker::numDictionaries() const
194 {
195         return d->spellers_.size();
196 }
197         
198
199 docstring const EnchantChecker::error()
200 {
201         return docstring();
202 }
203
204
205 } // namespace lyx