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