]> git.lyx.org Git - lyx.git/blob - src/Thesaurus.cpp
fix compilation on F13 and binutils/gold by rewriting specialized X11 code
[lyx.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 "LyXRC.h"
17
18 #include "support/FileNameList.h"
19 #include "support/Package.h"
20 #include "support/debug.h"
21 #include "support/filetools.h"
22 #include "support/gettext.h"
23 #include "support/lstrings.h"
24 #include "support/os.h"
25
26 #include "support/mythes/mythes.hxx"
27
28 #include "frontends/alert.h"
29
30 #include <algorithm>
31 #include <cstring>
32
33 using namespace std;
34 using namespace lyx::support;
35 using namespace lyx::support::os;
36
37 namespace lyx {
38
39 namespace {
40
41 typedef std::map<docstring, MyThes *> Thesauri;
42
43 } // namespace anon
44
45 #ifndef THESAURUS_LOCATION
46 # define THESAURUS_LOCATION "thes"
47 #endif
48
49 struct Thesaurus::Private
50 {
51         ~Private()
52         {
53                 for (Thesauri::iterator it = thes_.begin();
54                      it != thes_.end(); ++it) {
55                         delete it->second;
56                 }
57         }
58         ///
59         bool thesaurusAvailable(docstring const & lang) const
60         {
61                 for (Thesauri::const_iterator it = thes_.begin();
62                         it != thes_.end(); ++it) {
63                                 if (it->first == lang)
64                                         if (it->second)
65                                                 return true;
66                 }
67                 return false;
68         }
69
70         ///
71         typedef std::pair<std::string, std::string> ThesFiles;
72         ///
73         ThesFiles getThesaurus(string const & path, docstring const & lang);
74         ThesFiles getThesaurus(docstring const & lang);
75         /// add a thesaurus to the list
76         bool addThesaurus(docstring const & lang);
77
78         /// the thesauri
79         Thesauri thes_;
80 };
81
82
83 pair<string,string> Thesaurus::Private::getThesaurus(string const & path, docstring const & lang)
84 {
85         FileName base(path);
86         if (!base.isDirectory()) {
87                 return make_pair(string(), string());
88         }
89         FileNameList const idx_files = base.dirList("idx");
90         FileNameList const data_files = base.dirList("dat");
91         string idx;
92         string data;
93
94         LYXERR(Debug::FILES, "thesaurus path: " << path);
95         for (FileNameList::const_iterator it = idx_files.begin(); it != idx_files.end(); ++it) {
96                 if (contains(it->onlyFileName(), to_ascii(lang))) {
97                         idx = it->absFileName();
98                         LYXERR(Debug::FILES, "selected thesaurus idx file: " << idx);
99                         break;
100                 }
101         }
102         if (idx.empty()) {
103                 return make_pair(string(), string());
104         }
105         for (support::FileNameList::const_iterator it = data_files.begin(); it != data_files.end(); ++it) {
106                 if (contains(it->onlyFileName(), to_ascii(lang))) {
107                         data = it->absFileName();
108                         LYXERR(Debug::FILES, "selected thesaurus data file: " << data);
109                         break;
110                 }
111         }
112         return make_pair(idx, data);
113 }
114
115
116 pair<string,string> Thesaurus::Private::getThesaurus(docstring const & lang)
117 {
118         string const thes_path = external_path(lyxrc.thesaurusdir_path);
119         pair<string,string> result ;
120
121         if (thesaurusAvailable(lang))
122                 return make_pair(string(), string());
123
124         if (!thes_path.empty()) {
125                 result = getThesaurus(thes_path, lang);
126         }
127         if (result.first.empty() || result.second.empty()) {
128                 string const sys_path = external_path(addName(lyx::support::package().system_support().absFileName(),THESAURUS_LOCATION)) ;
129                 result = getThesaurus(sys_path, lang);
130         }
131         if (result.first.empty() || result.second.empty()) {
132                 string const user_path = external_path(addName(lyx::support::package().user_support().absFileName(),THESAURUS_LOCATION)) ;
133                 result = getThesaurus(user_path, lang);
134         }
135         return result;
136 }
137
138
139 bool Thesaurus::Private::addThesaurus(docstring const & lang)
140 {
141         if (thesaurusAvailable(lang))
142                 return true;
143
144         ThesFiles files = getThesaurus(lang);
145         string const idx = files.first;
146         string const data = files.second;
147
148         if (idx.empty() || data.empty())
149                 return false;
150
151         char const * af = idx.c_str();
152         char const * df = data.c_str();
153         thes_[lang] = new MyThes(af, df);
154         return true;
155 }
156
157
158 bool Thesaurus::thesaurusAvailable(docstring const & lang) const
159 {
160         return d->thesaurusAvailable(lang);
161 }
162
163
164 bool Thesaurus::thesaurusInstalled(docstring const & lang) const
165 {
166         pair<string, string> files = d->getThesaurus(lang);
167         return (!files.first.empty() && !files.second.empty());
168 }
169
170
171 Thesaurus::Meanings Thesaurus::lookup(docstring const & t, docstring const & lang)
172 {
173         Meanings meanings;
174         MyThes * mythes = 0;
175
176         if (!d->addThesaurus(lang))
177                 return meanings;
178
179         for (Thesauri::const_iterator it = d->thes_.begin();
180              it != d->thes_.end(); ++it) {
181                 if (it->first == lang) {
182                         mythes = it->second;
183                         break;
184                 }
185         }
186
187         if (!mythes)
188                 return meanings;
189
190         string const encoding = mythes->get_th_encoding();
191         
192         mentry * pmean;
193         string const text = to_iconv_encoding(support::lowercase(t), encoding);
194         int len = strlen(text.c_str());
195         int count = mythes->Lookup(text.c_str(), len, &pmean);
196         if (!count)
197                 return meanings;
198
199         // don't change value of pmean or count
200         // they are needed for the CleanUpAfterLookup routine
201         mentry * pm = pmean;
202         docstring meaning;
203         docstring ret;
204         for (int i = 0; i < count; i++) {
205                 meaning = from_iconv_encoding(string(pm->defn), encoding);
206                 // remove silly item
207                 if (support::prefixIs(meaning, '-'))
208                         meaning = support::ltrim(meaning, "- ");
209                 for (int j = 0; j < pm->count; j++) {
210                         ret = from_iconv_encoding(string(pm->psyns[j]), encoding);
211                 }
212         meanings[meaning].push_back(ret);
213         pm++;
214         }
215         // now clean up all allocated memory
216         mythes->CleanUpAfterLookup(&pmean, count);
217
218         for (Meanings::iterator it = meanings.begin();
219              it != meanings.end(); ++it)
220                 sort(it->second.begin(), it->second.end());
221
222         return meanings;
223 }
224
225
226 Thesaurus::Thesaurus() : d(new Thesaurus::Private)
227 {
228 }
229
230
231 Thesaurus::~Thesaurus()
232 {
233         delete d;
234 }
235
236 // Global instance
237 Thesaurus thesaurus;
238
239
240 } // namespace lyx