3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
7 * \author Jürgen Spitzmüller
9 * Full author contact details are available in file CREDITS.
14 #include "Thesaurus.h"
16 #include "support/debug.h"
17 #include "support/gettext.h"
20 #include "support/FileNameList.h"
21 #include "support/filetools.h"
22 #include "support/lstrings.h"
23 #include "support/os.h"
24 #include "support/unicode.h"
26 #include "frontends/alert.h"
32 using namespace lyx::support
;
33 using namespace lyx::support::os
;
37 #ifndef HAVE_LIBMYTHES
38 #ifdef HAVE_LIBAIKSAURUS
41 Thesaurus::Thesaurus()
42 : thes_(new Aiksaurus
)
46 Thesaurus::~Thesaurus()
52 Thesaurus::Meanings
Thesaurus::lookup(docstring
const & t
, docstring
const &)
56 // aiksaurus is for english text only, therefore it does not work
57 // with non-ascii strings.
58 // The interface of the Thesaurus class uses docstring because a
59 // non-english thesaurus is possible in theory.
60 if (!support::isAscii(t
))
61 // to_ascii() would assert
64 string
const text
= to_ascii(t
);
66 docstring error
= from_ascii(thes_
->error());
68 static bool sent_error
= false;
70 frontend::Alert::error(_("Thesaurus failure"),
71 bformat(_("Aiksaurus returned the following error:\n\n%1$s."),
77 if (!thes_
->find(text
.c_str()))
82 int prev_meaning
= -1;
86 // correct, returns "" at the end
87 string ret
= thes_
->next(cur_meaning
);
89 while (!ret
.empty()) {
90 if (cur_meaning
!= prev_meaning
) {
91 meaning
= from_ascii(ret
);
92 ret
= thes_
->next(cur_meaning
);
93 prev_meaning
= cur_meaning
;
96 meanings
[meaning
].push_back(from_ascii(ret
));
99 ret
= thes_
->next(cur_meaning
);
102 for (Meanings::iterator it
= meanings
.begin();
103 it
!= meanings
.end(); ++it
)
104 sort(it
->second
.begin(), it
->second
.end());
110 bool Thesaurus::thesaurusAvailable(docstring
const & lang
) const
112 // we support English only
113 return prefixIs(lang
, from_ascii("en_"));
116 #endif // HAVE_LIBAIKSAURUS
117 #endif // !HAVE_LIBMYTHES
120 #ifdef HAVE_LIBMYTHES
124 string
const to_iconv_encoding(docstring
const & s
, string
const & encoding
)
126 std::vector
<char> const encoded
=
127 ucs4_to_eightbit(s
.data(), s
.length(), encoding
);
128 return string(encoded
.begin(), encoded
.end());
132 docstring
const from_iconv_encoding(string
const & s
, string
const & encoding
)
134 std::vector
<char_type
> const ucs4
=
135 eightbit_to_ucs4(s
.data(), s
.length(), encoding
);
136 return docstring(ucs4
.begin(), ucs4
.end());
142 Thesaurus::Thesaurus()
146 Thesaurus::~Thesaurus()
148 for (Thesauri::iterator it
= thes_
.begin();
149 it
!= thes_
.end(); ++it
) {
155 bool Thesaurus::addThesaurus(docstring
const & lang
)
157 string
const thes_path
= external_path(lyxrc
.thesaurusdir_path
);
158 LYXERR(Debug::FILES
, "thesaurus path: " << thes_path
);
159 if (thes_path
.empty())
162 if (thesaurusAvailable(lang
))
165 FileNameList
const idx_files
= FileName(thes_path
).dirList("idx");
166 FileNameList
const data_files
= FileName(thes_path
).dirList("dat");
170 for (FileNameList::const_iterator it
= idx_files
.begin();
171 it
!= idx_files
.end(); ++it
) {
172 LYXERR(Debug::FILES
, "found thesaurus idx file: " << it
->onlyFileName());
173 if (contains(it
->onlyFileName(), to_ascii(lang
))) {
174 idx
= it
->absFilename();
175 LYXERR(Debug::FILES
, "selected thesaurus idx file: " << idx
);
180 for (support::FileNameList::const_iterator it
= data_files
.begin();
181 it
!= data_files
.end(); ++it
) {
182 LYXERR(Debug::FILES
, "found thesaurus data file: " << it
->onlyFileName());
183 if (contains(it
->onlyFileName(), to_ascii(lang
))) {
184 data
= it
->absFilename();
185 LYXERR(Debug::FILES
, "selected thesaurus data file: " << data
);
190 if (idx
.empty() || data
.empty())
193 char const * af
= idx
.c_str();
194 char const * df
= data
.c_str();
195 thes_
[lang
] = new MyThes(af
, df
);
200 bool Thesaurus::thesaurusAvailable(docstring
const & lang
) const
202 for (Thesauri::const_iterator it
= thes_
.begin();
203 it
!= thes_
.end(); ++it
) {
204 if (it
->first
== lang
)
213 Thesaurus::Meanings
Thesaurus::lookup(docstring
const & t
, docstring
const & lang
)
218 if (!addThesaurus(lang
))
221 for (Thesauri::const_iterator it
= thes_
.begin();
222 it
!= thes_
.end(); ++it
) {
223 if (it
->first
== lang
) {
232 string
const encoding
= mythes
->get_th_encoding();
235 string
const text
= to_iconv_encoding(support::lowercase(t
), encoding
);
236 int len
= strlen(text
.c_str());
237 int count
= mythes
->Lookup(text
.c_str(), len
, &pmean
);
241 // don't change value of pmean or count
242 // they are needed for the CleanUpAfterLookup routine
246 for (int i
= 0; i
< count
; i
++) {
247 meaning
= from_iconv_encoding(string(pm
->defn
), encoding
);
249 if (support::prefixIs(meaning
, '-'))
250 meaning
= support::ltrim(meaning
, "- ");
251 for (int j
= 0; j
< pm
->count
; j
++) {
252 ret
= from_iconv_encoding(string(pm
->psyns
[j
]), encoding
);
254 meanings
[meaning
].push_back(ret
);
257 // now clean up all allocated memory
258 mythes
->CleanUpAfterLookup(&pmean
, count
);
260 for (Meanings::iterator it
= meanings
.begin();
261 it
!= meanings
.end(); ++it
)
262 sort(it
->second
.begin(), it
->second
.end());
268 #ifndef HAVE_LIBAIKSAURUS
269 Thesaurus::Thesaurus()
274 Thesaurus::~Thesaurus()
279 Thesaurus::Meanings
Thesaurus::lookup(docstring
const &, docstring
const &)
285 bool Thesaurus::thesaurusAvailable(docstring
const & lang
) const
291 #endif // HAVE_LIBMYTHES