]> git.lyx.org Git - lyx.git/blob - src/support/os_unix.cpp
Fix some warnings
[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
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 char const * popen_read_mode()
197 {
198         return "r";
199 }
200
201
202 string const & nulldev()
203 {
204         static string const nulldev_ = "/dev/null";
205         return nulldev_;
206 }
207
208
209 shell_type shell()
210 {
211         return UNIX;
212 }
213
214
215 char path_separator(path_type)
216 {
217         return ':';
218 }
219
220
221 void windows_style_tex_paths(bool)
222 {}
223
224
225 #ifdef __APPLE__
226 bool canAutoOpenFile(CFStringRef cfs_uti, LSRolesMask role)
227 {
228         // Reference:
229         // https://developer.apple.com/reference/coreservices/1447734-lscopydefaultapplicationurlforco
230         CFURLRef outAppRef = LSCopyDefaultApplicationURLForContentType(cfs_uti, role, NULL);
231
232         if (outAppRef == NULL) return false;
233         CFRelease(outAppRef);
234         return true;
235 }
236 #endif
237
238 bool canAutoOpenFile(string const & ext, auto_open_mode const mode)
239 {
240 #ifdef __APPLE__
241         // References:
242         // https://developer.apple.com/reference/coreservices/1447734-lscopydefaultapplicationurlforco
243         CFStringRef cfs_ext = CFStringCreateWithBytes(kCFAllocatorDefault,
244                                         (UInt8 *) ext.c_str(), ext.length(),
245                                         kCFStringEncodingISOLatin1, false);
246         CFStringRef cfs_uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, cfs_ext, NULL);
247         CFRelease(cfs_ext);
248         if (cfs_uti == NULL) return false;
249
250         LSRolesMask role = (mode == VIEW) ? kLSRolesViewer :  kLSRolesEditor;
251         bool result = canAutoOpenFile(cfs_uti, role);
252         if (!result && mode == VIEW)
253                 result = canAutoOpenFile(cfs_uti, kLSRolesEditor);
254
255         CFRelease(cfs_uti);
256         return result;
257 #else
258         // silence compiler warnings
259         (void)ext;
260         (void)mode;
261
262         // currently, no default viewer is tried for non-apple system
263         // support for KDE/Gnome may be added later
264         return false;
265 #endif
266 }
267
268
269 bool autoOpenFile(string const & filename, auto_open_mode const mode,
270                   string const & path)
271 {
272 #ifdef __APPLE__
273 // Reference: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/
274         // this is what we would like to do but it seems that the
275         // viewer for PDF is often quicktime...
276         //LSRolesMask role = (mode == VIEW) ? kLSRolesViewer :  kLSRolesEditor;
277         (void)mode;
278         LSRolesMask role = (mode == VIEW) ? kLSRolesAll :  kLSRolesEditor;
279
280         CFURLRef docURL = CFURLCreateFromFileSystemRepresentation(
281                 NULL, (UInt8 *) filename.c_str(), filename.size(), false);
282         CFURLRef appURL = LSCopyDefaultApplicationURLForURL(docURL, role, NULL);
283
284         CFURLRef docURLs[] = { docURL };
285         CFArrayRef launchItems = CFArrayCreate(
286                 NULL,
287                 (const void**)docURLs, sizeof(docURLs) / sizeof(CFURLRef),
288                 NULL);
289         LSLaunchURLSpec launchUrlSpec = {
290                 appURL, launchItems, NULL, kLSLaunchDefaults, NULL
291         };
292
293         string const texinputs = os::latex_path_list(
294                 replaceCurdirPath(path, lyxrc.texinputs_prefix));
295         string const otherinputs = os::latex_path_list(path);
296         string const oldtexinputs = getEnv("TEXINPUTS");
297         string const newtexinputs = ".:" + texinputs + ":" + oldtexinputs;
298         string const oldbibinputs = getEnv("BIBINPUTS");
299         string const newbibinputs = ".:" + otherinputs + ":" + oldbibinputs;
300         string const oldbstinputs = getEnv("BSTINPUTS");
301         string const newbstinputs = ".:" + otherinputs + ":" + oldbstinputs;
302         string const oldtexfonts = getEnv("TEXFONTS");
303         string const newtexfonts = ".:" + otherinputs + ":" + oldtexfonts;
304         if (!path.empty() && !lyxrc.texinputs_prefix.empty()) {
305                 setEnv("TEXINPUTS", newtexinputs);
306                 setEnv("BIBINPUTS", newbibinputs);
307                 setEnv("BSTINPUTS", newbstinputs);
308                 setEnv("TEXFONTS", newtexfonts);
309         }
310         OSStatus const status = LSOpenFromURLSpec (&launchUrlSpec, NULL);
311         CFRelease(launchItems);
312         if (!path.empty() && !lyxrc.texinputs_prefix.empty()) {
313                 setEnv("TEXINPUTS", oldtexinputs);
314                 setEnv("BIBINPUTS", oldbibinputs);
315                 setEnv("BSTINPUTS", oldbstinputs);
316                 setEnv("TEXFONTS", oldtexfonts);
317         }
318         return status == 0;
319 #else
320         // silence compiler warnings
321         (void)filename;
322         (void)mode;
323         (void)path;
324
325         // currently, no default viewer is tried for non-apple system
326         // support for KDE/Gnome may be added later
327         return false;
328 #endif
329 }
330
331
332 string real_path(string const & path)
333 {
334 #ifdef HAVE_DEF_PATH_MAX
335         char rpath[PATH_MAX + 1];
336         char * result = realpath(path.c_str(), rpath);
337         return FileName::fromFilesystemEncoding(result ? rpath : path).absFileName();
338 #else
339         char * result = realpath(path.c_str(), NULL);
340         string ret = FileName::fromFilesystemEncoding(result ? result : path).absFileName();
341         free(result);
342         return ret;
343 #endif
344 }
345
346 } // namespace os
347 } // namespace support
348 } // namespace lyx