X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2Ffiletools.cpp;h=5891e79fec62c6b89346ed3e611a265e8a7bc1ca;hb=d7320ad89b26bb89f8f133801c6a452005e5bff3;hp=519f779a5ef283e1c8271bfaa3390f9088688f7d;hpb=bbea06a0c6ed444a51e749f9f47593251095e982;p=lyx.git diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp index 519f779a5e..5891e79fec 100644 --- a/src/support/filetools.cpp +++ b/src/support/filetools.cpp @@ -21,6 +21,8 @@ #include +#include "LyXRC.h" + #include "support/filetools.h" #include "support/debug.h" @@ -47,6 +49,7 @@ #include #include #include +#include #if defined (_WIN32) #include @@ -97,13 +100,13 @@ string const latex_path(string const & original_path, // 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 { @@ -111,7 +114,18 @@ string const latex_path(string const & original_path, } } - 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 "); } @@ -307,6 +321,21 @@ FileName const i18nLibFileSearch(string const & dir, string const & name, } +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/"; @@ -427,7 +456,7 @@ FileName const makeAbsPath(string const & relPath, string const & basePath) // Split by first / rTemp = split(rTemp, temp, '/'); if (temp == "~") { - tempBase = package().home_dir().absFileName(); + tempBase = Package::get_home_dir().absFileName(); tempRel = rTemp; } @@ -523,7 +552,7 @@ string const expandPath(string const & path) 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(); @@ -546,29 +575,76 @@ string const replaceEnvironmentPath(string const & path) static regex envvar_br_re("(.*)" + envvar_br + "(.*)"); static regex envvar_re("(.*)" + envvar + "(.*)"); - smatch what; - string result; - string remaining = path; + string result = path; while (1) { - regex_match(remaining, what, envvar_br_re); - if (!what[0].matched) { - regex_match(remaining, what, envvar_re); - if (!what[0].matched) { - result += remaining; + smatch what; + if (!regex_match(result, what, envvar_br_re)) { + if (!regex_match(result, what, envvar_re)) break; - } } string env_var = getEnv(what.str(2)); - if (!env_var.empty()) - result += what.str(1) + env_var; - else - result += what.str(1) + "$" + what.str(2); - remaining = what.str(3); + result = what.str(1) + env_var + what.str(3); } return result; } +// 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, @@ -718,7 +794,7 @@ docstring const makeDisplayPath(string const & path, unsigned int threshold) 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, "~"); @@ -726,38 +802,57 @@ docstring const makeDisplayPath(string const & path, unsigned int threshold) 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 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; } @@ -788,6 +883,16 @@ cmd_ret const runCommand(string const & cmd) 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; @@ -800,12 +905,18 @@ cmd_ret const runCommand(string const & cmd) 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); @@ -821,7 +932,7 @@ cmd_ret const runCommand(string const & cmd) #error No popen() function. #endif - // (Claus Hentschel) Check if popen was succesful ;-) + // (Claus Hentschel) Check if popen was successful ;-) if (!inf) { lyxerr << "RunCommand:: could not start child process" << endl; return make_pair(-1, string()); @@ -836,6 +947,8 @@ cmd_ret const runCommand(string const & cmd) #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) @@ -977,5 +1090,32 @@ int compare_timestamps(FileName const & file1, FileName const & file2) } +bool prefs2prefs(FileName const & filename, FileName const & tempfile, bool lfuns) +{ + FileName const script = libFileSearch("scripts", "prefs2prefs.py"); + if (script.empty()) { + LYXERR0("Could not find bind file conversion " + "script prefs2prefs.py."); + return false; + } + + ostringstream command; + command << os::python() << ' ' << quoteName(script.toFilesystemEncoding()) + << ' ' << (lfuns ? "-l" : "-p") << ' ' + << quoteName(filename.toFilesystemEncoding()) + << ' ' << quoteName(tempfile.toFilesystemEncoding()); + string const command_str = command.str(); + + LYXERR(Debug::FILES, "Running `" << command_str << '\''); + + cmd_ret const ret = runCommand(command_str); + if (ret.first != 0) { + LYXERR0("Could not run file conversion script prefs2prefs.py."); + return false; + } + return true; +} + + } //namespace support } // namespace lyx