]> git.lyx.org Git - lyx.git/blob - src/support/os_unix.cpp
Account for the weird case where p2 is longer than p1, such as p1 == "path"
[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 "support/os.h"
16 #include "support/docstring.h"
17 #include "support/FileName.h"
18 #include "support/lstrings.h"
19
20 #include <limits.h>
21 #include <stdlib.h>
22
23 #ifdef __APPLE__
24 #include <Carbon/Carbon.h>
25 #endif
26
27 using namespace std;
28
29 namespace lyx {
30 namespace support {
31 namespace os {
32
33 void init(int, char *[])
34 {}
35
36
37 string current_root()
38 {
39         return "/";
40 }
41
42
43 bool isFilesystemCaseSensitive()
44 {
45 #ifdef __APPLE__
46         return false;
47 #else
48         return true;
49 #endif
50 }
51
52
53 docstring::size_type common_path(docstring const & p1, docstring const & p2)
54 {
55         docstring::size_type i = 0;
56         docstring::size_type const p1_len = p1.length();
57         docstring::size_type const p2_len = p2.length();
58 #ifdef __APPLE__
59         while (i < p1_len && i < p2_len && uppercase(p1[i]) == uppercase(p2[i]))
60                 ++i;
61 #else
62         while (i < p1_len && i < p2_len && p1[i] == p2[i])
63                 ++i;
64 #endif
65         if ((i < p1_len && i < p2_len)
66             || (i < p1_len && p1[i] != '/' && i == p2_len)
67             || (i < p2_len && p2[i] != '/' && i == p1_len))
68         {
69                 if (i)
70                         --i;     // here was the last match
71                 while (i && p1[i] != '/')
72                         --i;
73         }
74         return i;
75 }
76
77
78 bool path_prefix_is(string const & path, string const & pre)
79 {
80 #ifdef __APPLE__
81         return path_prefix_is(const_cast<string &>(path), pre, CASE_UNCHANGED);
82 #else
83         return prefixIs(path, pre);
84 #endif
85 }
86
87
88 bool path_prefix_is(string & path, string const & pre, path_case how)
89 {
90 #ifdef __APPLE__
91         docstring const p1 = from_utf8(path);
92         docstring const p2 = from_utf8(pre);
93         docstring::size_type const p1_len = p1.length();
94         docstring::size_type const p2_len = p2.length();
95         docstring::size_type common_len = common_path(p1, p2);
96
97         if (p2[p2_len - 1] == '/' && p1_len != p2_len)
98                 ++common_len;
99
100         if (common_len != p2_len)
101                 return false;
102
103         if (how == CASE_ADJUSTED && !prefixIs(path, pre)) {
104                 if (p1_len < common_len)
105                         path = to_utf8(p2.substr(0, p1_len));
106                 else
107                         path = to_utf8(p2 + p1.substr(common_len,
108                                                         p1_len - common_len));
109         }
110
111         return true;
112 #else
113         // silence compiler warnings
114         (void)how;
115
116         return prefixIs(path, pre);
117 #endif
118 }
119
120
121 string external_path(string const & p)
122 {
123         return p;
124 }
125
126
127 string internal_path(string const & p)
128 {
129         return p;
130 }
131
132
133 string external_path_list(string const & p)
134 {
135         return p;
136 }
137
138
139 string internal_path_list(string const & p)
140 {
141         return p;
142 }
143
144
145 string latex_path(string const & p)
146 {
147         return p;
148 }
149
150
151 bool is_valid_strftime(string const & p)
152 {
153         string::size_type pos = p.find_first_of('%');
154         while (pos != string::npos) {
155                 if (pos + 1 == string::npos)
156                         break;
157                 if (!containsOnly(p.substr(pos + 1, 1),
158                         "aAbBcCdDeEFgGhHIjklmMnOpPrRsStTuUVwWxXyYzZ%+"))
159                         return false;
160                 if (pos + 2 == string::npos)
161                       break;
162                 pos = p.find_first_of('%', pos + 2);
163         }
164         return true;
165 }
166
167
168 char const * popen_read_mode()
169 {
170         return "r";
171 }
172
173
174 string const & nulldev()
175 {
176         static string const nulldev_ = "/dev/null";
177         return nulldev_;
178 }
179
180
181 bool is_terminal(io_channel channel)
182 {
183         return isatty(channel);
184 }
185
186
187 shell_type shell()
188 {
189         return UNIX;
190 }
191
192
193 char path_separator()
194 {
195         return ':';
196 }
197
198
199 void windows_style_tex_paths(bool)
200 {}
201
202 bool canAutoOpenFile(string const & ext, auto_open_mode const mode)
203 {
204 #ifdef __APPLE__
205 // Reference: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/
206         CFStringRef cfs_ext = CFStringCreateWithBytes(kCFAllocatorDefault,
207                                         (UInt8 *) ext.c_str(), ext.length(),
208                                         kCFStringEncodingISOLatin1, false);
209         // this is what we would like to do but it seems that the
210         // viewer for PDF is often quicktime...
211         //LSRolesMask role = (mode == VIEW) ? kLSRolesViewer :  kLSRolesEditor;
212         (void)mode;
213         LSRolesMask role = kLSRolesAll;
214         FSRef outAppRef;
215         OSStatus status =
216                 LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator,
217                                         cfs_ext, role, &outAppRef, NULL);
218         CFRelease(cfs_ext);
219
220         return status != kLSApplicationNotFoundErr;
221 #else
222         // silence compiler warnings
223         (void)ext;
224         (void)mode;
225
226         // currently, no default viewer is tried for non-windows system
227         // support for KDE/Gnome/Macintosh may be added later
228         return false;
229 #endif
230 }
231
232
233 bool autoOpenFile(string const & filename, auto_open_mode const mode)
234 {
235 #ifdef __APPLE__
236 // Reference: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/
237         FSRef fileref;
238         OSStatus status =
239                 FSPathMakeRef((UInt8 *) filename.c_str(), &fileref, NULL);
240         if (status != 0)
241                 return false;
242
243         // this is what we would like to do but it seems that the
244         // viewer for PDF is often quicktime...
245         //LSRolesMask role = (mode == VIEW) ? kLSRolesViewer :  kLSRolesEditor;
246         (void)mode;
247         LSRolesMask role = kLSRolesAll;
248         FSRef outAppRef;
249
250         status = LSGetApplicationForItem(&fileref, role, &outAppRef, NULL);
251         if (status == kLSApplicationNotFoundErr)
252                 return false;
253
254         LSLaunchFSRefSpec inLaunchSpec;
255         inLaunchSpec.appRef = &outAppRef;
256         inLaunchSpec.numDocs = 1;
257         inLaunchSpec.itemRefs = &fileref;
258         inLaunchSpec.passThruParams = NULL;
259         inLaunchSpec.launchFlags = kLSLaunchDefaults;
260         inLaunchSpec.asyncRefCon = NULL;
261         status = LSOpenFromRefSpec(&inLaunchSpec, NULL);
262
263         return status != kLSApplicationNotFoundErr;
264 #else
265         // silence compiler warnings
266         (void)filename;
267         (void)mode;
268
269         // currently, no default viewer is tried for non-windows system
270         // support for KDE/Gnome/Macintosh may be added later
271         return false;
272 #endif
273 }
274
275
276 string real_path(string const & path)
277 {
278         char rpath[PATH_MAX + 1];
279         char * result = realpath(path.c_str(), rpath);
280         return FileName::fromFilesystemEncoding(result ? rpath : path).absFilename();
281 }
282
283 } // namespace os
284 } // namespace support
285 } // namespace lyx