]> git.lyx.org Git - lyx.git/blob - src/support/Messages.cpp
Revert qprocess code. Revisions reverted: 22026, 22030, 22044, 22048,
[lyx.git] / src / support / Messages.cpp
1 /* \file Messages.cpp
2  * This file is part of LyX, the document processor.
3  * Licence details can be found in the file COPYING.
4  *
5  * \author Lars Gullik Bjønnes
6  *
7  * Full author contact details are available in file CREDITS.
8  */
9
10 #include <config.h>
11
12 #include "support/Messages.h"
13
14 #include "support/debug.h"
15 #include "support/docstring.h"
16 #include "support/environment.h"
17 #include "support/Package.h"
18 #include "support/unicode.h"
19
20 #include <boost/assert.hpp>
21
22 #include <cerrno>
23
24 using namespace std;
25
26 namespace {
27
28 using lyx::docstring;
29 using lyx::from_ascii;
30
31 void cleanTranslation(docstring & trans) 
32 {
33         /*
34           Some english words have different translations, depending on
35           context. In these cases the original string is augmented by
36           context information (e.g. "To:[[as in 'From page x to page
37           y']]" and "To:[[as in 'From format x to format y']]". This
38           means that we need to filter out everything in double square
39           brackets at the end of the string, otherwise the user sees
40           bogus messages. If we are unable to honour the request we
41           just return what we got in.
42         */
43         size_t const pos1 = trans.find(from_ascii("[["));
44         if (pos1 != docstring::npos) {
45                 size_t const pos2 = trans.find(from_ascii("]]"), pos1);
46                 if (pos2 != docstring::npos) 
47                         trans.erase(pos1, pos2 - pos1 + 2);
48         }
49 }
50
51 }
52
53
54 #ifdef ENABLE_NLS
55
56 #  ifdef HAVE_LOCALE_H
57 #    include <locale.h>
58 #  endif
59
60 #  if HAVE_GETTEXT
61 #    include <libintl.h>      // use the header already in the system *EK*
62 #  else
63 #    include "../intl/libintl.h"
64 #  endif
65
66 namespace lyx {
67
68 using support::package;
69 using support::getEnv;
70 using support::setEnv;
71
72
73 // This version use the traditional gettext.
74 Messages::Messages(string const & l)
75         : lang_(l), warned_(false)
76 {
77         // strip off any encoding suffix, i.e., assume 8-bit po files
78         size_t i = lang_.find(".");
79         lang_ = lang_.substr(0, i);
80         LYXERR(Debug::DEBUG, "language(" << lang_ << ")");
81 }
82
83
84 void Messages::init()
85 {
86         errno = 0;
87         string const locale_dir = package().locale_dir().toFilesystemEncoding();
88         char const * c = bindtextdomain(PACKAGE, locale_dir.c_str());
89         int e = errno;
90         if (e) {
91                 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
92                         << "Directory : " << package().locale_dir().absFilename() << '\n'
93                         << "Rtn value : " << c);
94         }
95
96         if (!bind_textdomain_codeset(PACKAGE, ucs4_codeset)) {
97                 LYXERR(Debug::DEBUG, "Error code: " << errno << '\n'
98                         << "Codeset   : " << ucs4_codeset);
99         }
100
101         textdomain(PACKAGE);
102 }
103
104
105 docstring const Messages::get(string const & m) const
106 {
107         if (m.empty())
108                 return docstring();
109
110         // Look for the translated string in the cache.
111         TranslationCache::iterator it = cache_.find(m);
112         if (it != cache_.end())
113                 return it->second;
114
115         // The string was not found, use gettext to generate it
116
117         string const oldLANGUAGE = getEnv("LANGUAGE");
118         string const oldLC_ALL = getEnv("LC_ALL");
119         if (!lang_.empty()) {
120                 // This GNU extension overrides any language locale
121                 // wrt gettext.
122                 setEnv("LANGUAGE", lang_);
123                 // However, setting LANGUAGE does nothing when the
124                 // locale is "C". Therefore we set the locale to
125                 // something that is believed to exist on most
126                 // systems. The idea is that one should be able to
127                 // load German documents even without having de_DE
128                 // installed.
129                 setEnv("LC_ALL", "en_US");
130 #ifdef HAVE_LC_MESSAGES
131                 setlocale(LC_MESSAGES, "");
132 #endif
133         }
134
135         char const * m_c = m.c_str();
136         char const * trans_c = gettext(m_c);
137         docstring trans;
138         if (!trans_c)
139                 LYXERR0("Undefined result from gettext");
140         else if (trans_c == m_c) {
141                 LYXERR(Debug::DEBUG, "Same as entered returned");
142                 trans = from_ascii(m);
143         } else {
144                 LYXERR(Debug::DEBUG, "We got a translation");
145                 // m is actually not a char const * but ucs4 data
146                 trans = reinterpret_cast<char_type const *>(trans_c);
147         }
148
149         cleanTranslation(trans);
150
151         // Reset environment variables as they were.
152         if (!lang_.empty()) {
153                 // Reset everything as it was.
154                 setEnv("LANGUAGE", oldLANGUAGE);
155                 setEnv("LC_ALL", oldLC_ALL);
156 #ifdef HAVE_LC_MESSAGES
157                 setlocale(LC_MESSAGES, "");
158 #endif
159         }
160
161         std::pair<TranslationCache::iterator, bool> result =
162                 cache_.insert(std::make_pair(m, trans));
163
164         BOOST_ASSERT(result.second);
165
166         return result.first->second;
167 }
168
169 } // namespace lyx
170
171 #else // ENABLE_NLS
172 // This is the dummy variant.
173
174 namespace lyx {
175
176 Messages::Messages(string const & l) {}
177
178 void Messages::init()
179 {
180 }
181
182
183 docstring const Messages::get(string const & m) const
184 {
185         docstring trans = from_ascii(m);
186         cleanTranslation(trans);
187         return trans;
188 }
189
190 } // namespace lyx
191
192 #endif
193
194 #if 0
195
196 -#include <locale>
197
198 namespace lyx {
199
200 // This version of the Pimpl utilizes the message capability of
201 // libstdc++ that is distributed with GNU G++.
202 class Messages::Pimpl {
203 public:
204         typedef std::messages<char>::catalog catalog;
205
206         Pimpl(string const & l)
207                 : lang_(l),
208                   loc_gl(lang_.c_str()),
209                   mssg_gl(std::use_facet<std::messages<char> >(loc_gl))
210         {
211                 //LYXERR("Messages: language(" << l << ") in dir(" << dir << ")");
212
213                 string const locale_dir = package().locale_dir().toFilesystemEncoding();
214                 cat_gl = mssg_gl.open(PACKAGE, loc_gl, locale_dir.c_str());
215
216         }
217
218         ~Pimpl()
219         {
220                 mssg_gl.close(cat_gl);
221         }
222
223         docstring const get(string const & msg) const
224         {
225                 return mssg_gl.get(cat_gl, 0, 0, msg);
226         }
227 private:
228         ///
229         string lang_;
230         ///
231         std::locale loc_gl;
232         ///
233         std::messages<char> const & mssg_gl;
234         ///
235         catalog cat_gl;
236 };
237
238 } // namespace lyx
239
240 #endif