#include <config.h>
+#include "LyXRC.h"
+
#include "support/filetools.h"
#include "support/debug.h"
#include <utility>
#include <fstream>
#include <sstream>
+#include <vector>
#if defined (_WIN32)
#include <io.h>
// We can't use '"' because " is sometimes active (e.g. if
// babel is loaded with the "german" option)
if (extension == EXCLUDE_EXTENSION) {
- // ChangeExtension calls os::internal_path internally
+ // changeExtension calls os::internal_path internally
// so don't use it to remove the extension.
string const ext = getExtension(path);
string const base = ext.empty() ?
path :
path.substr(0, path.length() - ext.length() - 1);
- // ChangeExtension calls os::internal_path internally
+ // changeExtension calls os::internal_path internally
// so don't use it to re-add the extension.
path = "\\string\"" + base + "\\string\"." + ext;
} else {
}
}
- return dots == ESCAPE_DOTS ? subst(path, ".", "\\lyxdot ") : path;
+ if (dots != ESCAPE_DOTS)
+ return path;
+
+ // Replace dots with the lyxdot macro, but only in the file name,
+ // not the directory part.
+ // addName etc call os::internal_path internally
+ // so don't use them for path manipulation
+ // The directory separator is always '/' for LaTeX.
+ string::size_type pos = path.rfind('/');
+ if (pos == string::npos)
+ return subst(path, ".", "\\lyxdot ");
+ return path.substr(0, pos) + subst(path.substr(pos), ".", "\\lyxdot ");
}
}
+FileName const imageLibFileSearch(string & dir, string const & name,
+ string const & ext)
+{
+ if (!lyx::lyxrc.icon_set.empty()) {
+ string const imagedir = addPath(dir, lyx::lyxrc.icon_set);
+ FileName const fn = libFileSearch(imagedir, name, ext);
+ if (fn.exists()) {
+ dir = imagedir;
+ return fn;
+ }
+ }
+ return libFileSearch(dir, name, ext);
+}
+
+
string const libScriptSearch(string const & command_in, quote_style style)
{
static string const token_scriptpath = "$$s/";
// Split by first /
rTemp = split(rTemp, temp, '/');
if (temp == "~") {
- tempBase = package().home_dir().absFileName();
+ tempBase = Package::get_home_dir().absFileName();
tempRel = rTemp;
}
return FileName::getcwd().absFileName() + '/' + rTemp;
if (temp == "~")
- return package().home_dir().absFileName() + '/' + rTemp;
+ return Package::get_home_dir().absFileName() + '/' + rTemp;
if (temp == "..")
return makeAbsPath(copy).absFileName();
}
+// Return a command prefix for setting the environment of the TeX engine.
+string latexEnvCmdPrefix(string const & path)
+{
+ if (path.empty() || lyxrc.texinputs_prefix.empty())
+ return string();
+
+ string const texinputs_prefix = os::latex_path_list(
+ replaceCurdirPath(path, lyxrc.texinputs_prefix));
+ string const sep = string(1, os::path_separator(os::TEXENGINE));
+ string const texinputs = getEnv("TEXINPUTS");
+
+ if (os::shell() == os::UNIX)
+ return "env TEXINPUTS=\"." + sep + texinputs_prefix
+ + sep + texinputs + "\" ";
+ else
+ return "cmd /d /c set TEXINPUTS=." + sep + texinputs_prefix
+ + sep + texinputs + "&";
+}
+
+
+// Replace current directory in all elements of a path list with a given path.
+string const replaceCurdirPath(string const & path, string const & pathlist)
+{
+ string const oldpathlist = replaceEnvironmentPath(pathlist);
+ char const sep = os::path_separator();
+ string newpathlist;
+
+ for (size_t i = 0, k = 0; i != string::npos; k = i) {
+ i = oldpathlist.find(sep, i);
+ string p = oldpathlist.substr(k, i - k);
+ if (FileName::isAbsolute(p)) {
+ newpathlist += p;
+ } else if (i > k) {
+ size_t offset = 0;
+ if (p == ".") {
+ offset = 1;
+ } else if (prefixIs(p, "./")) {
+ offset = 2;
+ while (p[offset] == '/')
+ ++offset;
+ }
+ newpathlist += addPath(path, p.substr(offset));
+ if (suffixIs(p, "//"))
+ newpathlist += '/';
+ }
+ if (i != string::npos) {
+ newpathlist += sep;
+ // Stop here if the last element is empty
+ if (++i == oldpathlist.length())
+ break;
+ }
+ }
+ return newpathlist;
+}
+
+
// Make relative path out of two absolute paths
docstring const makeRelPath(docstring const & abspath, docstring const & basepath)
// Makes relative path out of absolute path. If it is deeper than basepath,
return from_utf8("[" + str.erase(0, system.length()) + "]");
// replace /home/blah with ~/
- string const home = package().home_dir().absFileName();
+ string const home = Package::get_home_dir().absFileName();
if (!home.empty() && prefixIs(str, home))
str = subst(str, home, "~");
return from_utf8(os::external_path(str));
string const prefix = ".../";
- string temp;
+ docstring dstr = from_utf8(str);
+ docstring temp;
- while (str.length() > threshold)
- str = split(str, temp, '/');
+ while (dstr.length() > threshold)
+ dstr = split(dstr, temp, '/');
// Did we shorten everything away?
- if (str.empty()) {
+ if (dstr.empty()) {
// Yes, filename itself is too long.
// Pick the start and the end of the filename.
- str = onlyFileName(path);
- string const head = str.substr(0, threshold / 2 - 3);
+ dstr = from_utf8(onlyFileName(path));
+ docstring const head = dstr.substr(0, threshold / 2 - 3);
- string::size_type len = str.length();
- string const tail =
- str.substr(len - threshold / 2 - 2, len - 1);
- str = head + "..." + tail;
+ docstring::size_type len = dstr.length();
+ docstring const tail =
+ dstr.substr(len - threshold / 2 - 2, len - 1);
+ dstr = head + from_ascii("...") + tail;
}
- return from_utf8(os::external_path(prefix + str));
+ return from_utf8(os::external_path(prefix + to_utf8(dstr)));
}
#ifdef HAVE_READLINK
bool readLink(FileName const & file, FileName & link)
{
- char linkbuffer[PATH_MAX + 1];
string const encoded = file.toFilesystemEncoding();
+#ifdef HAVE_DEF_PATH_MAX
+ char linkbuffer[PATH_MAX + 1];
int const nRead = ::readlink(encoded.c_str(),
linkbuffer, sizeof(linkbuffer) - 1);
if (nRead <= 0)
return false;
linkbuffer[nRead] = '\0'; // terminator
+#else
+ vector<char> buf(1024);
+ int nRead = -1;
+
+ while (true) {
+ nRead = ::readlink(encoded.c_str(), &buf[0], buf.size() - 1);
+ if (nRead < 0) {
+ return false;
+ }
+ if (nRead < buf.size() - 1) {
+ break;
+ }
+ buf.resize(buf.size() * 2);
+ }
+ buf[nRead] = '\0'; // terminator
+ const char * linkbuffer = &buf[0];
+#endif
link = makeAbsPath(linkbuffer, onlyPath(file.absFileName()));
return true;
}
SECURITY_ATTRIBUTES security;
HANDLE in, out;
FILE * inf = 0;
+ bool err2out = false;
+ string command;
+ string const infile = trim(split(cmd, command, '<'), " \"");
+ command = rtrim(command);
+ if (suffixIs(command, "2>&1")) {
+ command = rtrim(command, "2>&1");
+ err2out = true;
+ }
+ string const cmdarg = "/d /c " + command;
+ string const comspec = getEnv("COMSPEC");
security.nLength = sizeof(SECURITY_ATTRIBUTES);
security.bInheritHandle = TRUE;
startup.cb = sizeof(STARTUPINFO);
startup.dwFlags = STARTF_USESTDHANDLES;
- startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ startup.hStdError = err2out ? out : GetStdHandle(STD_ERROR_HANDLE);
+ startup.hStdInput = infile.empty()
+ ? GetStdHandle(STD_INPUT_HANDLE)
+ : CreateFile(infile.c_str(), GENERIC_READ,
+ FILE_SHARE_READ, &security, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL);
startup.hStdOutput = out;
- if (CreateProcess(0, (LPTSTR)cmd.c_str(), &security, &security,
- TRUE, CREATE_NO_WINDOW, 0, 0, &startup, &process)) {
+ if (startup.hStdInput != INVALID_HANDLE_VALUE &&
+ CreateProcess(comspec.c_str(), (LPTSTR)cmdarg.c_str(),
+ &security, &security, TRUE, CREATE_NO_WINDOW,
+ 0, 0, &startup, &process)) {
CloseHandle(process.hThread);
fno = _open_osfhandle((long)in, _O_RDONLY);
#if defined (_WIN32)
WaitForSingleObject(process.hProcess, INFINITE);
+ if (!infile.empty())
+ CloseHandle(startup.hStdInput);
CloseHandle(process.hProcess);
int const pret = fclose(inf);
#elif defined (HAVE_PCLOSE)