#include "support/regex.h"
#include <fcntl.h>
+#ifdef HAVE_MAGIC_H
+#include <magic.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#include <cerrno>
#include <cstdlib>
}
+bool isBinaryFile(FileName const & filename)
+{
+ bool isbinary = false;
+ if (filename.empty() || !filename.exists())
+ return isbinary;
+
+#ifdef HAVE_MAGIC_H
+ magic_t magic_cookie = magic_open(MAGIC_MIME_ENCODING);
+ if (magic_cookie) {
+ bool detected = true;
+ if (magic_load(magic_cookie, NULL) != 0) {
+ LYXERR(Debug::FILES, "isBinaryFile: "
+ "Could not load magic database - "
+ << magic_error(magic_cookie));
+ detected = false;
+ } else {
+ char const *charset = magic_file(magic_cookie,
+ filename.toFilesystemEncoding().c_str());
+ isbinary = contains(charset, "binary");
+ }
+ magic_close(magic_cookie);
+ if (detected)
+ return isbinary;
+ }
+#endif
+ // Try by looking for binary chars at the beginning of the file.
+ // Note that this is formally not correct, since count_bin_chars
+ // expects utf8, and the passed string can be anything: plain text
+ // in any encoding, or really binary data. In practice it works,
+ // since QString::fromUtf8() drops invalid utf8 sequences, and
+ // while the exact number may not be correct, we still get a high
+ // number for truly binary files.
+
+ ifstream ifs(filename.toFilesystemEncoding().c_str());
+ if (!ifs)
+ return isbinary;
+
+ // Maximum strings to read
+ int const max_count = 50;
+
+ // Maximum number of binary chars allowed
+ int const max_bin = 5;
+
+ int count = 0;
+ int binchars = 0;
+ string str;
+ while (count++ < max_count && !ifs.eof()) {
+ getline(ifs, str);
+ binchars += count_bin_chars(str);
+ }
+ return binchars > max_bin;
+}
+
+
string const latex_path(string const & original_path,
latex_path_extension extension,
latex_path_dots dots)
// simple parser in Systemcall.cpp do the substitution.
return '"' + subst(name, "\"", "\\\"") + '"';
#endif
+ case quote_shell_filename:
+ return quoteName(os::external_path(name), quote_shell);
case quote_python:
return "\"" + subst(subst(name, "\\", "\\\\"), "\"", "\\\"")
+ "\"";
// Returns the real name of file name in directory path, with optional
// extension ext.
FileName const fileSearch(string const & path, string const & name,
- string const & ext, search_mode mode)
+ string const & exts, search_mode mode)
{
// if `name' is an absolute path, we ignore the setting of `path'
// Expand Environmentvariables in 'name'
// search first without extension, then with it.
if (fullname.isReadableFile())
return fullname;
- if (ext.empty())
+ if (exts.empty())
// We are done.
return mode == may_not_exist ? fullname : FileName();
- // Only add the extension if it is not already the extension of
- // fullname.
- if (getExtension(fullname.absFileName()) != ext)
- fullname = FileName(addExtension(fullname.absFileName(), ext));
- if (fullname.isReadableFile() || mode == may_not_exist)
- return fullname;
+ int n = 0;
+ string ext = token(exts, ',', n);
+ while (!ext.empty()) {
+ // Only add the extension if it is not already the extension of
+ // fullname.
+ bool addext = getExtension(fullname.absFileName()) != ext;
+ if (addext) {
+ if (mode == check_hidpi) {
+ FileName fullname2x = FileName(addExtension(fullname.absFileName() + "@2x", ext));
+ if (fullname2x.isReadableFile())
+ return fullname2x;
+ }
+ fullname = FileName(addExtension(fullname.absFileName(), ext));
+ }
+ if (fullname.isReadableFile() || mode == may_not_exist)
+ return fullname;
+ if (addext)
+ fullname.changeExtension("");
+ ext = token(exts, ',', ++n);
+ }
return FileName();
}
// 2) build_lyxdir (if not empty)
// 3) system_lyxdir
FileName const libFileSearch(string const & dir, string const & name,
- string const & ext)
+ string const & ext, search_mode mode)
{
FileName fullname = fileSearch(addPath(package().user_support().absFileName(), dir),
- name, ext);
+ name, ext, mode);
if (!fullname.empty())
return fullname;
if (!package().build_support().empty())
fullname = fileSearch(addPath(package().build_support().absFileName(), dir),
- name, ext);
+ name, ext, mode);
if (!fullname.empty())
return fullname;
- return fileSearch(addPath(package().system_support().absFileName(), dir), name, ext);
+ return fileSearch(addPath(package().system_support().absFileName(), dir),
+ name, ext, mode);
}
FileName const imageLibFileSearch(string & dir, string const & name,
- string const & ext)
+ string const & ext, search_mode mode)
{
if (!lyx::lyxrc.icon_set.empty()) {
string const imagedir = addPath(dir, lyx::lyxrc.icon_set);
- FileName const fn = libFileSearch(imagedir, name, ext);
+ FileName const fn = libFileSearch(imagedir, name, ext, mode);
if (fn.exists()) {
dir = imagedir;
return fn;
}
}
- return libFileSearch(dir, name, ext);
+ return libFileSearch(dir, name, ext, mode);
}
// dir inside deflt.
return createTmpDir(deflt, "lyx_tmpdir");
} else {
- // some other error occured.
+ // some other error occurred.
return createTmpDir(package().system_temp_dir(), "lyx_tmpdir");
}
}
// Return a command prefix for setting the environment of the TeX engine.
-string latexEnvCmdPrefix(string const & path)
+string latexEnvCmdPrefix(string const & path, string const & lpath)
{
- if (path.empty() || lyxrc.texinputs_prefix.empty())
+ bool use_lpath = !(lpath.empty() || lpath == "." || lpath == "./");
+
+ if (path.empty() || (lyxrc.texinputs_prefix.empty() && !use_lpath))
return string();
- string const texinputs_prefix = os::latex_path_list(
+ string texinputs_prefix = lyxrc.texinputs_prefix.empty() ? string()
+ : os::latex_path_list(
replaceCurdirPath(path, lyxrc.texinputs_prefix));
+ string const allother_prefix = os::latex_path_list(path);
string const sep = string(1, os::path_separator(os::TEXENGINE));
string const texinputs = getEnv("TEXINPUTS");
+ string const bibinputs = getEnv("BIBINPUTS");
+ string const bstinputs = getEnv("BSTINPUTS");
+ string const texfonts = getEnv("TEXFONTS");
+
+ if (use_lpath) {
+ string const abslpath = FileName::isAbsolute(lpath)
+ ? os::latex_path(lpath)
+ : os::latex_path(FileName(path + "/" + lpath).realPath());
+ if (texinputs_prefix.empty())
+ texinputs_prefix = abslpath;
+ else if (suffixIs(texinputs_prefix, sep))
+ texinputs_prefix.append(abslpath + sep);
+ else
+ texinputs_prefix.append(sep + abslpath);
+ }
if (os::shell() == os::UNIX)
return "env TEXINPUTS=\"." + sep + texinputs_prefix
- + sep + texinputs + "\" ";
+ + sep + texinputs + "\" "
+ + "BIBINPUTS=\"." + sep + allother_prefix
+ + sep + bibinputs + "\" "
+ + "BSTINPUTS=\"." + sep + allother_prefix
+ + sep + bstinputs + "\" "
+ + "TEXFONTS=\"." + sep + allother_prefix
+ + sep + texfonts + "\" ";
else
- return "cmd /d /c set TEXINPUTS=." + sep + texinputs_prefix
- + sep + texinputs + "&";
+ // NOTE: the dummy blank dirs are necessary to force the
+ // QProcess parser to quote the argument (see bug 9453)
+ return "cmd /d /c set \"TEXINPUTS=." + sep + " "
+ + sep + texinputs_prefix
+ + sep + texinputs + "\" & "
+ + "set \"BIBINPUTS=." + sep + " "
+ + sep + allother_prefix
+ + sep + bibinputs + "\" & "
+ + "set \"BSTINPUTS=." + sep + " "
+ + sep + allother_prefix
+ + sep + bstinputs + "\" & "
+ + "set \"TEXFONTS=." + sep + " "
+ + sep + allother_prefix
+ + sep + texfonts + "\" & ";
}
}
if (i != string::npos) {
newpathlist += sep;
- // Stop here if the last element is empty
+ // Stop here if the last element is empty
if (++i == oldpathlist.length())
break;
}
string const ext = getExtension(zipped_file);
if (ext == "gz" || ext == "z" || ext == "Z")
return changeExtension(zipped_file, string());
+ else if (ext == "svgz")
+ return changeExtension(zipped_file, "svg");
return onlyPath(zipped_file) + "unzipped_" + onlyFileName(zipped_file);
}
if (dstr.empty()) {
// Yes, filename itself is too long.
// Pick the start and the end of the filename.
- dstr = from_utf8(onlyFileName(path));
- docstring const head = dstr.substr(0, threshold / 2 - 3);
-
- docstring::size_type len = dstr.length();
- docstring const tail =
- dstr.substr(len - threshold / 2 - 2, len - 1);
- dstr = head + from_ascii("...") + tail;
+ docstring fstr = from_utf8(onlyFileName(path));
+ dstr = fstr;
+ if (support::truncateWithEllipsis(dstr, threshold / 2))
+ dstr += fstr.substr(fstr.length() - threshold / 2 - 2,
+ docstring::npos);
}
return from_utf8(os::external_path(prefix + to_utf8(dstr)));
// variants ipstream, opstream
#if defined (_WIN32)
- int fno;
STARTUPINFO startup;
PROCESS_INFORMATION process;
SECURITY_ATTRIBUTES security;
0, 0, &startup, &process)) {
CloseHandle(process.hThread);
- fno = _open_osfhandle((long)in, _O_RDONLY);
+ int fno = _open_osfhandle((long)in, _O_RDONLY);
CloseHandle(out);
inf = _fdopen(fno, "r");
}
return true;
}
+
+bool configFileNeedsUpdate(string const & file)
+{
+ // We cannot initialize configure_script directly because the package
+ // is not initialized yet when static objects are constructed.
+ static FileName configure_script;
+ static bool firstrun = true;
+ if (firstrun) {
+ configure_script =
+ FileName(addName(package().system_support().absFileName(),
+ "configure.py"));
+ firstrun = false;
+ }
+
+ FileName absfile =
+ FileName(addName(package().user_support().absFileName(), file));
+ return !absfile.exists()
+ || configure_script.lastModified() > absfile.lastModified();
+}
+
+
int fileLock(const char * lock_file)
{
int fd = -1;
#if defined(HAVE_LOCKF)
fd = open(lock_file, O_CREAT|O_APPEND|O_SYNC|O_RDWR, 0666);
+ if (fd == -1)
+ return -1;
if (lockf(fd, F_LOCK, 0) != 0) {
close(fd);
- return(-1);
+ return -1;
}
#endif
- return(fd);
+ return fd;
}
+
void fileUnlock(int fd, const char * /* lock_file*/)
{
#if defined(HAVE_LOCKF)