]> git.lyx.org Git - features.git/blob - src/Thesaurus.cpp
Fix bug 3522.
[features.git] / src / Thesaurus.cpp
1 /**
2  * \file Thesaurus.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
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 "Thesaurus.h"
15
16 #include "debug.h"
17 #include "support/lstrings.h"
18 #include "support/unicode.h"
19
20 #include <algorithm>
21
22
23 namespace lyx {
24
25 using std::sort;
26 using std::string;
27 using std::endl;
28
29
30 #ifndef HAVE_LIBMYTHES
31 #ifdef HAVE_LIBAIKSAURUS
32 Thesaurus::Thesaurus()
33         : thes_(new Aiksaurus)
34 {}
35
36
37 Thesaurus::~Thesaurus()
38 {
39         delete thes_;
40 }
41
42
43 Thesaurus::Meanings Thesaurus::lookup(docstring const & t)
44 {
45         Meanings meanings;
46
47         // aiksaurus is for english text only, therefore it does not work
48         // with non-ascii strings.
49         // The interface of the Thesaurus class uses docstring because a
50         // non-english thesaurus is possible in theory.
51         if (!support::isAscii(t))
52                 // to_ascii() would assert
53                 return meanings;
54
55         string const text = to_ascii(t);
56         if (!thes_->find(text.c_str()))
57                 return meanings;
58
59         // weird api, but ...
60
61         int prev_meaning = -1;
62         int cur_meaning;
63         docstring meaning;
64
65         // correct, returns "" at the end
66         string ret = thes_->next(cur_meaning);
67
68         while (!ret.empty()) {
69                 if (cur_meaning != prev_meaning) {
70                         meaning = from_ascii(ret);
71                         ret = thes_->next(cur_meaning);
72                         prev_meaning = cur_meaning;
73                 } else {
74                         if (ret != text)
75                                 meanings[meaning].push_back(from_ascii(ret));
76                 }
77
78                 ret = thes_->next(cur_meaning);
79         }
80
81         for (Meanings::iterator it = meanings.begin();
82              it != meanings.end(); ++it)
83                 sort(it->second.begin(), it->second.end());
84
85         return meanings;
86 }
87
88 #endif // HAVE_LIBAIKSAURUS
89 #endif // !HAVE_LIBMYTHES
90
91
92 #ifdef HAVE_LIBMYTHES
93
94 namespace {
95
96 string const to_iconv_encoding(docstring const & s, string const & encoding)
97 {
98         std::vector<char> const encoded =
99                 ucs4_to_eightbit(s.data(), s.length(), encoding);
100         return string(encoded.begin(), encoded.end());
101 }
102
103
104 docstring const from_iconv_encoding(string const & s, string const & encoding)
105 {
106         std::vector<char_type> const ucs4 =
107                 eightbit_to_ucs4(s.data(), s.length(), encoding);
108         return docstring(ucs4.begin(), ucs4.end());
109 }
110
111 } // namespace anon
112
113
114 Thesaurus::Thesaurus()
115 {
116         string const idx("/home/juergen/updates/MyThes-1.0/th_de_DE_v2.idx");
117         string const data("/home/juergen/updates/MyThes-1.0/th_de_DE_v2.dat");
118         char const * af = idx.c_str();
119         char const * df = data.c_str();
120         thes_ = new MyThes(af, df);
121 }
122
123
124 Thesaurus::~Thesaurus()
125 {
126         if (thes_)
127                 delete thes_;
128 }
129
130
131 Thesaurus::Meanings Thesaurus::lookup(docstring const & t)
132 {
133         Meanings meanings;
134
135         string const encoding = thes_->get_th_encoding();
136         
137         mentry * pmean;
138         string const text = to_iconv_encoding(support::lowercase(t), encoding);
139         int len = strlen(text.c_str());
140         int count = thes_->Lookup(text.c_str(), len, &pmean);
141         if (!count)
142                 return meanings;
143
144         // don't change value of pmean or count
145         // they are needed for the CleanUpAfterLookup routine
146         mentry * pm = pmean;
147         docstring meaning;
148         docstring ret;
149         for (int i = 0; i < count; i++) {
150                 meaning = from_iconv_encoding(string(pm->defn), encoding);
151                 // remove silly item
152                 if (support::prefixIs(meaning, '-'))
153                         meaning = support::ltrim(meaning, "- ");
154                 for (int j = 0; j < pm->count; j++) {
155                         ret = from_iconv_encoding(string(pm->psyns[j]), encoding);
156                 }
157         meanings[meaning].push_back(ret);
158         pm++;
159         }
160         // now clean up all allocated memory
161         thes_->CleanUpAfterLookup(&pmean, count);
162
163         for (Meanings::iterator it = meanings.begin();
164              it != meanings.end(); ++it)
165                 sort(it->second.begin(), it->second.end());
166
167         return meanings;
168 }
169
170 #else
171
172 Thesaurus::Thesaurus()
173 {
174 }
175
176
177 Thesaurus::~Thesaurus()
178 {
179 }
180
181
182 Thesaurus::Meanings Thesaurus::lookup(docstring const &)
183 {
184         return Meanings();
185 }
186
187 #endif // HAVE_LIBMYTHES
188
189 // Global instance
190 Thesaurus thesaurus;
191
192
193 } // namespace lyx