]> git.lyx.org Git - lyx.git/blobdiff - src/support/os_unix.cpp
Fix some warnings
[lyx.git] / src / support / os_unix.cpp
index c3494798098d5c4f5e64bbf28e0024b08227d576..3f16dd86563588e5e4ed6da5e6f952c9cf05f1db 100644 (file)
 
 #include <config.h>
 
+#include "LyXRC.h"
+
 #include "support/os.h"
-#include "debug.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 <limits.h>
+#include <locale.h>
+#include <stdlib.h>
 
 #ifdef __APPLE__
-#include <Carbon/Carbon.h>
-#include <ApplicationServices/ApplicationServices.h>
-#elif defined(HAVE_FONTCONFIG_FONTCONFIG_H)
-#include "support/filetools.h"
-#include "support/Package.h"
-#include <fontconfig/fontconfig.h>
-using lyx::support::addPath;
+#include <CoreServices/CoreServices.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFArray.h>
 #endif
 
-using std::endl;
-using std::string;
-
+using namespace std;
 
 namespace lyx {
 namespace support {
 namespace os {
 
-void init(int, char *[])
+namespace {
+
+int argc_ = 0;
+char ** argv_ = 0;
+
+} // namespace
+
+void init(int argc, char ** argv[])
+{
+       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)
 {}
 
 
@@ -43,13 +73,28 @@ string current_root()
 }
 
 
+bool isFilesystemCaseSensitive()
+{
+#ifdef __APPLE__
+       return false;
+#else
+       return true;
+#endif
+}
+
+
 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))
@@ -63,6 +108,49 @@ docstring::size_type common_path(docstring const & p1, docstring const & p2)
 }
 
 
+bool path_prefix_is(string const & path, string const & pre)
+{
+#ifdef __APPLE__
+       return path_prefix_is(const_cast<string &>(path), pre, CASE_UNCHANGED);
+#else
+       return prefixIs(path, pre);
+#endif
+}
+
+
+bool path_prefix_is(string & path, string const & pre, path_case how)
+{
+#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(string const & p)
 {
        return p;
@@ -75,6 +163,12 @@ string internal_path(string const & p)
 }
 
 
+string safe_internal_path(string const & p, file_access)
+{
+       return p;
+}
+
+
 string external_path_list(string const & p)
 {
        return p;
@@ -93,9 +187,9 @@ string latex_path(string const & p)
 }
 
 
-bool is_absolute_path(string const & p)
+string latex_path_list(string const & p)
 {
-       return !p.empty() && p[0] == '/';
+       return p;
 }
 
 
@@ -118,7 +212,7 @@ shell_type shell()
 }
 
 
-char path_separator()
+char path_separator(path_type)
 {
        return ':';
 }
@@ -127,122 +221,125 @@ 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;
 
-       return status != kLSApplicationNotFoundErr;
+       LSRolesMask role = (mode == VIEW) ? kLSRolesViewer :  kLSRolesEditor;
+       bool result = canAutoOpenFile(cfs_uti, role);
+       if (!result && mode == VIEW)
+               result = canAutoOpenFile(cfs_uti, kLSRolesEditor);
+
+       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
 }
 
 
-void addFontResources()
+string real_path(string const & path)
 {
-#ifdef __APPLE__
-       CFBundleRef  myAppBundle = CFBundleGetMainBundle();
-       CFURLRef  myAppResourcesURL, FontsURL;
-       FSRef  fontDirRef;
-       FSSpec  fontDirSpec;
-       CFStringRef  filePath = CFStringCreateWithBytes(kCFAllocatorDefault,
-                                       (UInt8 *) "fonts", strlen("fonts"),
-                                       kCFStringEncodingISOLatin1, false);
-
-       myAppResourcesURL = CFBundleCopyResourcesDirectoryURL(myAppBundle);
-       FontsURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
-                       myAppResourcesURL, filePath, true);
-       if (lyxerr.debugging(Debug::FONT)) {
-               UInt8  buf[255];
-               if (CFURLGetFileSystemRepresentation(FontsURL, true, buf, 255))
-                       lyxerr << "Adding Fonts directory: " << buf << endl;
-       }
-       CFURLGetFSRef (FontsURL, &fontDirRef);
-       OSStatus err = FSGetCatalogInfo (&fontDirRef, kFSCatInfoNone,
-                                        NULL, NULL, &fontDirSpec, NULL);
-       if (err)
-               lyxerr << "FSGetCatalogInfo err = " << err << endl;
-       err = FMActivateFonts (&fontDirSpec, NULL, NULL,
-                              kFMLocalActivationContext);
-       if (err)
-               lyxerr << "FMActivateFonts err = " << err << endl;
-#elif defined(HAVE_FONTCONFIG_FONTCONFIG_H)
-       // Register BaKoMa truetype fonts with fontconfig
-       string const fonts_dir =
-               addPath(package().system_support().absFilename(), "fonts");
-       if (!FcConfigAppFontAddDir(0, (FcChar8 const *)fonts_dir.c_str()))
-               lyxerr << "Unable to register fonts with fontconfig." << endl;
-#endif
-}
-
-
-void restoreFontResources()
-{
-#if defined(HAVE_FONTCONFIG_FONTCONFIG_H) && !defined(__APPLE__)
-       FcConfigAppFontClear(0);
+#ifdef HAVE_DEF_PATH_MAX
+       char rpath[PATH_MAX + 1];
+       char * result = realpath(path.c_str(), rpath);
+       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
 }