X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Fos_unix.cpp;h=3f16dd86563588e5e4ed6da5e6f952c9cf05f1db;hb=cf14e814124ccbc8155fa1dde98d03be319c0e87;hp=a9ae59850cb37ecd4cc735d754572f49000fe706;hpb=0ed38ed1f4d30d8eaaba6aa8b6236c55f33d8719;p=lyx.git diff --git a/src/support/os_unix.cpp b/src/support/os_unix.cpp index a9ae59850c..3f16dd8656 100644 --- a/src/support/os_unix.cpp +++ b/src/support/os_unix.cpp @@ -12,16 +12,24 @@ #include +#include "LyXRC.h" + #include "support/os.h" #include "support/docstring.h" +#include "support/environment.h" #include "support/FileName.h" +#include "support/filetools.h" #include "support/lstrings.h" +#include "support/lassert.h" #include +#include #include #ifdef __APPLE__ -#include +#include +#include +#include #endif using namespace std; @@ -32,23 +40,33 @@ namespace os { namespace { -string stdoutdev_ = "/dev/stdout"; -string stderrdev_ = "/dev/stderr"; +int argc_ = 0; +char ** argv_ = 0; -} // namespace anon +} // namespace -void init(int, char *[]) +void init(int argc, char ** argv[]) { - // Check whether /dev/stdout and /dev/stderr are available, - // otherwise default to /dev/tty. - if (access(stdoutdev_.c_str(), W_OK) != 0 - || access(stderrdev_.c_str(), W_OK) != 0) { - stdoutdev_ = "/dev/tty"; - stderrdev_ = "/dev/tty"; - } + argc_ = argc; + argv_ = *argv; + + // Set environment's default locale + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); } +string utf8_argv(int i) +{ + LASSERT(i < argc_, return ""); + return to_utf8(from_local8bit(argv_[i])); +} + + +void remove_internal_args(int, int) +{} + + string current_root() { return "/"; @@ -70,8 +88,13 @@ docstring::size_type common_path(docstring const & p1, docstring const & p2) docstring::size_type i = 0; docstring::size_type const p1_len = p1.length(); docstring::size_type const p2_len = p2.length(); +#ifdef __APPLE__ + while (i < p1_len && i < p2_len && uppercase(p1[i]) == uppercase(p2[i])) + ++i; +#else while (i < p1_len && i < p2_len && p1[i] == p2[i]) ++i; +#endif if ((i < p1_len && i < p2_len) || (i < p1_len && p1[i] != '/' && i == p2_len) || (i < p2_len && p2[i] != '/' && i == p1_len)) @@ -85,81 +108,101 @@ docstring::size_type common_path(docstring const & p1, docstring const & p2) } -string external_path(string const & p) +bool path_prefix_is(string const & path, string const & pre) { - return p; +#ifdef __APPLE__ + return path_prefix_is(const_cast(path), pre, CASE_UNCHANGED); +#else + return prefixIs(path, pre); +#endif } -string internal_path(string const & p) +bool path_prefix_is(string & path, string const & pre, path_case how) { - return p; +#ifdef __APPLE__ + docstring const p1 = from_utf8(path); + docstring const p2 = from_utf8(pre); + docstring::size_type const p1_len = p1.length(); + docstring::size_type const p2_len = p2.length(); + docstring::size_type common_len = common_path(p1, p2); + + if (p2[p2_len - 1] == '/' && p1_len != p2_len) + ++common_len; + + if (common_len != p2_len) + return false; + + if (how == CASE_ADJUSTED && !prefixIs(path, pre)) { + if (p1_len < common_len) + path = to_utf8(p2.substr(0, p1_len)); + else + path = to_utf8(p2 + p1.substr(common_len, + p1_len - common_len)); + } + + return true; +#else + // silence compiler warnings + (void)how; + + return prefixIs(path, pre); +#endif } -string external_path_list(string const & p) +string external_path(string const & p) { return p; } -string internal_path_list(string const & p) +string internal_path(string const & p) { return p; } -string latex_path(string const & p) +string safe_internal_path(string const & p, file_access) { return p; } -bool is_valid_strftime(string const & p) +string external_path_list(string const & p) { - string::size_type pos = p.find_first_of('%'); - while (pos != string::npos) { - if (pos + 1 == string::npos) - break; - if (!containsOnly(p.substr(pos + 1, 1), - "aAbBcCdDeEFgGhHIjklmMnOpPrRsStTuUVwWxXyYzZ%+")) - return false; - if (pos + 2 == string::npos) - break; - pos = p.find_first_of('%', pos + 2); - } - return true; + return p; } -char const * popen_read_mode() +string internal_path_list(string const & p) { - return "r"; + return p; } -string const & nulldev() +string latex_path(string const & p) { - static string const nulldev_ = "/dev/null"; - return nulldev_; + return p; } -string const & stdoutdev() +string latex_path_list(string const & p) { - return stdoutdev_; + return p; } -string const & stderrdev() +char const * popen_read_mode() { - return stderrdev_; + return "r"; } -bool is_terminal(io_channel channel) +string const & nulldev() { - return isatty(channel); + static string const nulldev_ = "/dev/null"; + return nulldev_; } @@ -169,7 +212,7 @@ shell_type shell() } -char path_separator() +char path_separator(path_type) { return ':'; } @@ -178,75 +221,109 @@ char path_separator() void windows_style_tex_paths(bool) {} + +#ifdef __APPLE__ +bool canAutoOpenFile(CFStringRef cfs_uti, LSRolesMask role) +{ + // Reference: + // https://developer.apple.com/reference/coreservices/1447734-lscopydefaultapplicationurlforco + CFURLRef outAppRef = LSCopyDefaultApplicationURLForContentType(cfs_uti, role, NULL); + + if (outAppRef == NULL) return false; + CFRelease(outAppRef); + return true; +} +#endif + bool canAutoOpenFile(string const & ext, auto_open_mode const mode) { #ifdef __APPLE__ -// Reference: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/ + // References: + // https://developer.apple.com/reference/coreservices/1447734-lscopydefaultapplicationurlforco CFStringRef cfs_ext = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *) ext.c_str(), ext.length(), kCFStringEncodingISOLatin1, false); - // this is what we would like to do but it seems that the - // viewer for PDF is often quicktime... - //LSRolesMask role = (mode == VIEW) ? kLSRolesViewer : kLSRolesEditor; - (void)mode; - LSRolesMask role = kLSRolesAll; - FSRef outAppRef; - OSStatus status = - LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, - cfs_ext, role, &outAppRef, NULL); + CFStringRef cfs_uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, cfs_ext, NULL); CFRelease(cfs_ext); + if (cfs_uti == NULL) return false; + + LSRolesMask role = (mode == VIEW) ? kLSRolesViewer : kLSRolesEditor; + bool result = canAutoOpenFile(cfs_uti, role); + if (!result && mode == VIEW) + result = canAutoOpenFile(cfs_uti, kLSRolesEditor); - return status != kLSApplicationNotFoundErr; + CFRelease(cfs_uti); + return result; #else // silence compiler warnings (void)ext; (void)mode; - // currently, no default viewer is tried for non-windows system - // support for KDE/Gnome/Macintosh may be added later + // currently, no default viewer is tried for non-apple system + // support for KDE/Gnome may be added later return false; #endif } -bool autoOpenFile(string const & filename, auto_open_mode const mode) +bool autoOpenFile(string const & filename, auto_open_mode const mode, + string const & path) { #ifdef __APPLE__ // Reference: http://developer.apple.com/documentation/Carbon/Reference/LaunchServicesReference/ - FSRef fileref; - OSStatus status = - FSPathMakeRef((UInt8 *) filename.c_str(), &fileref, NULL); - if (status != 0) - return false; - // this is what we would like to do but it seems that the // viewer for PDF is often quicktime... //LSRolesMask role = (mode == VIEW) ? kLSRolesViewer : kLSRolesEditor; (void)mode; - LSRolesMask role = kLSRolesAll; - FSRef outAppRef; - - status = LSGetApplicationForItem(&fileref, role, &outAppRef, NULL); - if (status == kLSApplicationNotFoundErr) - return false; - - LSLaunchFSRefSpec inLaunchSpec; - inLaunchSpec.appRef = &outAppRef; - inLaunchSpec.numDocs = 1; - inLaunchSpec.itemRefs = &fileref; - inLaunchSpec.passThruParams = NULL; - inLaunchSpec.launchFlags = kLSLaunchDefaults; - inLaunchSpec.asyncRefCon = NULL; - status = LSOpenFromRefSpec(&inLaunchSpec, NULL); - - return status != kLSApplicationNotFoundErr; + LSRolesMask role = (mode == VIEW) ? kLSRolesAll : kLSRolesEditor; + + CFURLRef docURL = CFURLCreateFromFileSystemRepresentation( + NULL, (UInt8 *) filename.c_str(), filename.size(), false); + CFURLRef appURL = LSCopyDefaultApplicationURLForURL(docURL, role, NULL); + + CFURLRef docURLs[] = { docURL }; + CFArrayRef launchItems = CFArrayCreate( + NULL, + (const void**)docURLs, sizeof(docURLs) / sizeof(CFURLRef), + NULL); + LSLaunchURLSpec launchUrlSpec = { + appURL, launchItems, NULL, kLSLaunchDefaults, NULL + }; + + string const texinputs = os::latex_path_list( + replaceCurdirPath(path, lyxrc.texinputs_prefix)); + string const otherinputs = os::latex_path_list(path); + string const oldtexinputs = getEnv("TEXINPUTS"); + string const newtexinputs = ".:" + texinputs + ":" + oldtexinputs; + string const oldbibinputs = getEnv("BIBINPUTS"); + string const newbibinputs = ".:" + otherinputs + ":" + oldbibinputs; + string const oldbstinputs = getEnv("BSTINPUTS"); + string const newbstinputs = ".:" + otherinputs + ":" + oldbstinputs; + string const oldtexfonts = getEnv("TEXFONTS"); + string const newtexfonts = ".:" + otherinputs + ":" + oldtexfonts; + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) { + setEnv("TEXINPUTS", newtexinputs); + setEnv("BIBINPUTS", newbibinputs); + setEnv("BSTINPUTS", newbstinputs); + setEnv("TEXFONTS", newtexfonts); + } + OSStatus const status = LSOpenFromURLSpec (&launchUrlSpec, NULL); + CFRelease(launchItems); + if (!path.empty() && !lyxrc.texinputs_prefix.empty()) { + setEnv("TEXINPUTS", oldtexinputs); + setEnv("BIBINPUTS", oldbibinputs); + setEnv("BSTINPUTS", oldbstinputs); + setEnv("TEXFONTS", oldtexfonts); + } + return status == 0; #else // silence compiler warnings (void)filename; (void)mode; + (void)path; - // currently, no default viewer is tried for non-windows system - // support for KDE/Gnome/Macintosh may be added later + // currently, no default viewer is tried for non-apple system + // support for KDE/Gnome may be added later return false; #endif } @@ -254,9 +331,16 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode) string real_path(string const & path) { +#ifdef HAVE_DEF_PATH_MAX char rpath[PATH_MAX + 1]; char * result = realpath(path.c_str(), rpath); - return FileName::fromFilesystemEncoding(result ? rpath : path).absFilename(); + return FileName::fromFilesystemEncoding(result ? rpath : path).absFileName(); +#else + char * result = realpath(path.c_str(), NULL); + string ret = FileName::fromFilesystemEncoding(result ? result : path).absFileName(); + free(result); + return ret; +#endif } } // namespace os