]> git.lyx.org Git - lyx.git/blob - src/support/os_unix.cpp
Account for old versions of Pygments
[lyx.git] / src / support / os_unix.cpp
1 /**
2  * \file os_unix.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Ruurd A. Reitsma
7  *
8  * Full author contact details are available in file CREDITS.
9  *
10  * Various OS specific functions
11  */
12
13 #include <config.h>
14
15 #include "LyXRC.h"
16
17 #include "support/os.h"
18 #include "support/docstring.h"
19 #include "support/environment.h"
20 #include "support/FileName.h"
21 #include "support/filetools.h"
22 #include "support/lstrings.h"
23 #include "support/lassert.h"
24
25 #include <limits.h>
26 #include <locale.h>
27 #include <stdlib.h>
28
29 #ifdef __APPLE__
30 #include <CoreServices/CoreServices.h>
31 #include <CoreFoundation/CoreFoundation.h>
32 #include <CoreFoundation/CFArray.h>
33 #endif
34
35 using namespace std;
36
37 namespace lyx {
38 namespace support {
39 namespace os {
40
41 namespace {
42
43 int argc_ = 0;
44 char ** argv_ = 0;
45
46 } // namespace anon
47
48 void init(int argc, char ** argv[])
49 {
50         argc_ = argc;
51         argv_ = *argv;
52
53         // Set environment's default locale
54         setlocale(LC_ALL, "");
55         setlocale(LC_NUMERIC, "C");
56 }
57
58
59 string utf8_argv(int i)
60 {
61         LASSERT(i < argc_, return "");
62         return to_utf8(from_local8bit(argv_[i]));
63 }
64
65
66 void remove_internal_args(int, int)
67 {}
68
69
70 string current_root()
71 {
72         return "/";
73 }
74
75
76 bool isFilesystemCaseSensitive()
77 {
78 #ifdef __APPLE__
79         return false;
80 #else
81         return true;
82 #endif
83 }
84
85
86 docstring::size_type common_path(docstring const & p1, docstring const & p2)
87 {
88         docstring::size_type i = 0;
89         docstring::size_type const p1_len = p1.length();
90         docstring::size_type const p2_len = p2.length();
91 #ifdef __APPLE__
92         while (i < p1_len && i < p2_len && uppercase(p1[i]) == uppercase(p2[i]))
93                 ++i;
94 #else
95         while (i < p1_len && i < p2_len && p1[i] == p2[i])
96                 ++i;
97 #endif
98         if ((i < p1_len && i < p2_len)
99             || (i < p1_len && p1[i] != '/' && i == p2_len)
100             || (i < p2_len && p2[i] != '/' && i == p1_len))
101         {
102                 if (i)
103                         --i;     // here was the last match
104                 while (i && p1[i] != '/')
105                         --i;
106         }
107         return i;
108 }
109
110
111 bool path_prefix_is(string const & path, string const & pre)
112 {
113 #ifdef __APPLE__
114         return path_prefix_is(const_cast<string &>(path), pre, CASE_UNCHANGED);
115 #else
116         return prefixIs(path, pre);
117 #endif
118 }
119
120
121 bool path_prefix_is(string & path, string const & pre, path_case how)
122 {
123 #ifdef __APPLE__
124         docstring const p1 = from_utf8(path);
125         docstring const p2 = from_utf8(pre);
126         docstring::size_type const p1_len = p1.length();
127         docstring::size_type const p2_len = p2.length();
128         docstring::size_type common_len = common_path(p1, p2);
129
130         if (p2[p2_len - 1] == '/' && p1_len != p2_len)
131                 ++common_len;
132
133         if (common_len != p2_len)
134                 return false;
135
136         if (how == CASE_ADJUSTED && !prefixIs(path, pre)) {
137                 if (p1_len < common_len)
138                         path = to_utf8(p2.substr(0, p1_len));
139                 else
140                         path = to_utf8(p2 + p1.substr(common_len,
141                                                         p1_len - common_len));
142         }
143
144         return true;
145 #else
146         // silence compiler warnings
147         (void)how;
148
149         return prefixIs(path, pre);
150 #endif
151 }
152
153
154 string external_path(string const & p)
155 {
156         return p;
157 }
158
159
160 string internal_path(string const & p)
161 {
162         return p;
163 }
164
165
166 string safe_internal_path(string const & p, file_access)
167 {
168         return p;
169 }
170
171
172 string external_path_list(string const & p)
173 {
174         return p;
175 }
176
177
178 string internal_path_list(string const & p)
179 {
180         return p;
181 }
182
183
184 string latex_path(string const & p)
185 {
186         return p;
187 }
188
189
190 string latex_path_list(string const & p)
191 {
192         return p;
193 }
194
195
196 bool is_valid_strftime(string const & p)
197 {
198         string::size_type pos = p.find_first_of('%');
199         while (pos != string::npos) {
200                 if (pos + 1 == string::npos)
201                         break;
202                 if (!containsOnly(p.substr(pos + 1, 1),
203                         "aAbBcCdDeEFgGhHIjklmMnOpPrRsStTuUVwWxXyYzZ%+"))
204                         return false;
205                 if (pos + 2 == string::npos)
206                       break;
207                 pos = p.find_first_of('%', pos + 2);
208         }
209         return true;
210 }
211
212
213 char const * popen_read_mode()
214 {
215         return "r";
216 }
217
218
219 string const & nulldev()
220 {
221         static string const nulldev_ = "/dev/null";
222         return nulldev_;
223 }
224
225
226 shell_type shell()
227 {
228         return UNIX;
229 }
230
231
232 char path_separator(path_type)
233 {
234         return ':';
235 }
236
237
238 void windows_style_tex_paths(bool)
239 {}
240
241 bool canAutoOpenFile(string const & ext, auto_open_mode const mode)
242 {
243 #ifdef __APPLE__
244 // Reference: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/
245         CFStringRef cfs_ext = CFStringCreateWithBytes(kCFAllocatorDefault,
246                                         (UInt8 *) ext.c_str(), ext.length(),
247                                         kCFStringEncodingISOLatin1, false);
248         // this is what we would like to do but it seems that the
249         // viewer for PDF is often quicktime...
250         //LSRolesMask role = (mode == VIEW) ? kLSRolesViewer :  kLSRolesEditor;
251         (void)mode;
252         LSRolesMask role = kLSRolesAll;
253         FSRef outAppRef;
254         OSStatus status =
255                 LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator,
256                                         cfs_ext, role, &outAppRef, NULL);
257         CFRelease(cfs_ext);
258
259         return status != kLSApplicationNotFoundErr;
260 #else
261         // silence compiler warnings
262         (void)ext;
263         (void)mode;
264
265         // currently, no default viewer is tried for non-windows system
266         // support for KDE/Gnome/Macintosh may be added later
267         return false;
268 #endif
269 }
270
271
272 bool autoOpenFile(string const & filename, auto_open_mode const mode,
273                   string const & path)
274 {
275 #ifdef __APPLE__
276 // Reference: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/
277         // this is what we would like to do but it seems that the
278         // viewer for PDF is often quicktime...
279         //LSRolesMask role = (mode == VIEW) ? kLSRolesViewer :  kLSRolesEditor;
280         (void)mode;
281         LSRolesMask role = kLSRolesAll;
282
283         CFURLRef docURL = CFURLCreateFromFileSystemRepresentation(
284                 NULL, (UInt8 *) filename.c_str(), filename.size(), false);
285         CFURLRef appURL;
286         OSStatus status = LSGetApplicationForURL(docURL, role, NULL, &appURL);
287         if (status == kLSApplicationNotFoundErr)
288                 return false;
289
290         CFURLRef docURLs[] = { docURL };
291         CFArrayRef launchItems = CFArrayCreate(
292                 NULL,
293                 (const void**)docURLs, sizeof(docURLs) / sizeof(CFURLRef),
294                 NULL);
295         LSLaunchURLSpec launchUrlSpec = {
296                 appURL, launchItems, NULL, kLSLaunchDefaults, NULL
297         };
298
299         string const texinputs = os::latex_path_list(
300                 replaceCurdirPath(path, lyxrc.texinputs_prefix));
301         string const otherinputs = os::latex_path_list(path);
302         string const oldtexinputs = getEnv("TEXINPUTS");
303         string const newtexinputs = ".:" + texinputs + ":" + oldtexinputs;
304         string const oldbibinputs = getEnv("BIBINPUTS");
305         string const newbibinputs = ".:" + otherinputs + ":" + oldbibinputs;
306         string const oldbstinputs = getEnv("BSTINPUTS");
307         string const newbstinputs = ".:" + otherinputs + ":" + oldbstinputs;
308         string const oldtexfonts = getEnv("TEXFONTS");
309         string const newtexfonts = ".:" + otherinputs + ":" + oldtexfonts;
310         if (!path.empty() && !lyxrc.texinputs_prefix.empty()) {
311                 setEnv("TEXINPUTS", newtexinputs);
312                 setEnv("BIBINPUTS", newbibinputs);
313                 setEnv("BSTINPUTS", newbstinputs);
314                 setEnv("TEXFONTS", newtexfonts);
315         }
316         status = LSOpenFromURLSpec (&launchUrlSpec, NULL);
317         CFRelease(launchItems);
318         if (!path.empty() && !lyxrc.texinputs_prefix.empty()) {
319                 setEnv("TEXINPUTS", oldtexinputs);
320                 setEnv("BIBINPUTS", oldbibinputs);
321                 setEnv("BSTINPUTS", oldbstinputs);
322                 setEnv("TEXFONTS", oldtexfonts);
323         }
324         return status == 0;
325 #else
326         // silence compiler warnings
327         (void)filename;
328         (void)mode;
329         (void)path;
330
331         // currently, no default viewer is tried for non-windows system
332         // support for KDE/Gnome/Macintosh may be added later
333         return false;
334 #endif
335 }
336
337
338 string real_path(string const & path)
339 {
340 #ifdef HAVE_DEF_PATH_MAX
341         char rpath[PATH_MAX + 1];
342         char * result = realpath(path.c_str(), rpath);
343         return FileName::fromFilesystemEncoding(result ? rpath : path).absFileName();
344 #else
345         char * result = realpath(path.c_str(), NULL);
346         string ret = FileName::fromFilesystemEncoding(result ? result : path).absFileName();
347         free(result);
348         return ret;
349 #endif
350 }
351
352 } // namespace os
353 } // namespace support
354 } // namespace lyx