3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Ruurd A. Reitsma
7 * \author Claus Hentschel
8 * \author Angus Leeming
9 * \author Enrico Forestieri
11 * Full author contact details are available in file CREDITS.
13 * Various OS specific functions
18 #include "support/os.h"
20 #include "support/FileName.h"
21 #include "support/lstrings.h"
22 #include "support/debug.h"
32 #include <sys/cygwin.h>
38 void emergencyCleanup();
45 bool windows_style_tex_paths_ = false;
47 // In both is_posix_path() and is_windows_path() it is assumed that
48 // a valid posix or pseudo-windows path is passed. They simply tell
49 // whether the path looks posix/pseudo-windows or not.
51 bool is_posix_path(string const & p)
54 (!contains(p, '\\') && (p.length() <= 1 || p[1] != ':'));
57 // This is a test for a win32 style path with forward slashes (pseudo-windows).
59 bool is_windows_path(string const & p)
61 return p.empty() || (!contains(p, '\\') && p[0] != '/');
71 /// Convert a path to or from posix style.
72 /// \p p is encoded in local 8bit encoding or utf8.
73 /// The result is returned in the same encoding as \p p.
74 string convert_path(string const & p, PathStyle const & target)
76 char path_buf[PATH_MAX];
78 if ((target == posix && is_posix_path(p)) ||
79 (target == windows && is_windows_path(p)))
84 // cygwin_conv_to_posix_path and cygwin_conv_to_win32_path do not
85 // care about the encoding.
87 cygwin_conv_to_posix_path(p.c_str(), path_buf);
89 cygwin_conv_to_win32_path(p.c_str(), path_buf);
91 return subst(path_buf[0] ? path_buf : p, '\\', '/');
95 /// Convert a path list to or from posix style.
96 /// \p p is encoded in local 8bit encoding or utf8.
97 /// The result is returned in the same encoding as \p p.
98 string convert_path_list(string const & p, PathStyle const & target)
103 char const * const pc = p.c_str();
104 PathStyle const actual = cygwin_posix_path_list_p(pc) ? posix : windows;
106 if (target != actual) {
107 int const target_size = (target == posix) ?
108 cygwin_win32_to_posix_path_list_buf_size(pc) :
109 cygwin_posix_to_win32_path_list_buf_size(pc);
111 char * ptr = new char[target_size];
114 // FIXME: See comment in convert_path() above
116 cygwin_win32_to_posix_path_list(pc, ptr);
118 cygwin_posix_to_win32_path_list(pc, ptr);
120 string path_list = subst(ptr, '\\', '/');
126 return subst(p, '\\', '/');
130 BOOL terminate_handler(DWORD event)
132 if (event == CTRL_CLOSE_EVENT
133 || event == CTRL_LOGOFF_EVENT
134 || event == CTRL_SHUTDOWN_EVENT) {
135 lyx::emergencyCleanup();
143 void init(int, char *[])
145 // Make sure that the TEMP variable is set
146 // and sync the Windows environment.
147 setenv("TEMP", "/tmp", false);
148 cygwin_internal(CW_SYNC_WINENV);
150 // Catch shutdown events.
151 SetConsoleCtrlHandler((PHANDLER_ROUTINE)terminate_handler, TRUE);
155 string current_root()
161 bool isFilesystemCaseSensitive()
167 docstring::size_type common_path(docstring const & p1, docstring const & p2)
169 docstring::size_type i = 0;
170 docstring::size_type const p1_len = p1.length();
171 docstring::size_type const p2_len = p2.length();
172 while (i < p1_len && i < p2_len && uppercase(p1[i]) == uppercase(p2[i]))
174 if ((i < p1_len && i < p2_len)
175 || (i < p1_len && p1[i] != '/' && i == p2_len)
176 || (i < p2_len && p2[i] != '/' && i == p1_len))
179 --i; // here was the last match
180 while (i && p1[i] != '/')
187 bool path_prefix_is(string const & path, string const & pre)
189 return path_prefix_is(const_cast<string &>(path), pre, CASE_UNCHANGED);
193 bool path_prefix_is(string & path, string const & pre, path_case how)
195 docstring const p1 = from_utf8(path);
196 docstring const p2 = from_utf8(pre);
197 docstring::size_type const p1_len = p1.length();
198 docstring::size_type const p2_len = p2.length();
199 docstring::size_type common_len = common_path(p1, p2);
201 if (p2[p2_len - 1] == '/' && p1_len != p2_len)
204 if (common_len != p2_len)
207 if (how == CASE_ADJUSTED && !prefixIs(path, pre)) {
208 if (p1_len < common_len)
209 path = to_utf8(p2.substr(0, p1_len));
211 path = to_utf8(p2 + p1.substr(common_len,
212 p1_len - common_len));
219 string external_path(string const & p)
221 return convert_path(p, PathStyle(posix));
225 string internal_path(string const & p)
227 return convert_path(p, PathStyle(posix));
231 string external_path_list(string const & p)
233 return convert_path_list(p, PathStyle(posix));
237 string internal_path_list(string const & p)
239 return convert_path_list(p, PathStyle(posix));
243 string latex_path(string const & p)
245 // We may need a posix style path or a windows style path (depending
246 // on windows_style_tex_paths_), but we use always forward slashes,
247 // since it gets written into a .tex file.
249 if (windows_style_tex_paths_ && FileName::isAbsolute(p)) {
250 string dos_path = convert_path(p, PathStyle(windows));
251 LYXERR(Debug::LATEX, "<Path correction for LaTeX> ["
252 << p << "]->>[" << dos_path << ']');
256 return convert_path(p, PathStyle(posix));
260 bool is_valid_strftime(string const & p)
262 string::size_type pos = p.find_first_of('%');
263 while (pos != string::npos) {
264 if (pos + 1 == string::npos)
266 if (!containsOnly(p.substr(pos + 1, 1),
267 "aAbBcCdDeEFgGhHIjklmMnOpPrRsStTuUVwWxXyYzZ%+"))
269 if (pos + 2 == string::npos)
271 pos = p.find_first_of('%', pos + 2);
277 // returns a string suitable to be passed to popen when
279 char const * popen_read_mode()
285 string const & nulldev()
287 static string const nulldev_ = "/dev/null";
292 bool is_terminal(io_channel channel)
294 return isatty(channel);
304 char path_separator()
310 void windows_style_tex_paths(bool use_windows_paths)
312 windows_style_tex_paths_ = use_windows_paths;
316 bool canAutoOpenFile(string const & ext, auto_open_mode const mode)
321 string const full_ext = "." + ext;
323 DWORD bufSize = MAX_PATH + 100;
324 TCHAR buf[MAX_PATH + 100];
325 // reference: http://msdn.microsoft.com/en-us/library/bb773471.aspx
326 char const * action = (mode == VIEW) ? "open" : "edit";
327 return S_OK == AssocQueryString(ASSOCF_INIT_IGNOREUNKNOWN,
328 ASSOCSTR_EXECUTABLE, full_ext.c_str(), action, buf, &bufSize);
332 bool autoOpenFile(string const & filename, auto_open_mode const mode)
334 // reference: http://msdn.microsoft.com/en-us/library/bb762153.aspx
335 string const win_path = to_local8bit(from_utf8(convert_path(filename, PathStyle(windows))));
336 char const * action = (mode == VIEW) ? "open" : "edit";
337 return reinterpret_cast<int>(ShellExecute(NULL, action,
338 win_path.c_str(), NULL, NULL, 1)) > 32;
342 string real_path(string const & path)
344 char rpath[PATH_MAX + 1];
345 char * result = realpath(path.c_str(), rpath);
346 return FileName::fromFilesystemEncoding(result ? rpath : path).absFilename();
350 } // namespace support