#include "support/gettext.h"
#include "support/lstrings.h"
#include "support/os.h"
+#include "support/Messages.h"
#include "support/Package.h"
#include "support/Path.h"
#include "support/Systemcall.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 ");
}
each po file is able to tell us its name. (JMarc)
*/
- string lang = to_ascii(_(languageTestString()));
+ string lang = getGuiMessages().language();
string const language = getEnv("LANGUAGE");
if (!lang.empty() && !language.empty())
lang = language;
}
+// 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)
{
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)
}
-void readBB_lyxerrMessage(FileName const & file, bool & zipped,
- string const & message)
-{
- LYXERR(Debug::GRAPHICS, "[readBB_from_PSFile] " << message);
- // FIXME: Why is this func deleting a file? (Lgb)
- if (zipped)
- file.removeFile();
-}
-
-
-string const readBB_from_PSFile(FileName const & file)
-{
- // in a (e)ps-file it's an entry like %%BoundingBox:23 45 321 345
- // It seems that every command in the header has an own line,
- // getline() should work for all files.
- // On the other hand some plot programs write the bb at the
- // end of the file. Than we have in the header:
- // %%BoundingBox: (atend)
- // In this case we must check the end.
- bool zipped = file.isZippedFile();
- FileName const file_ = zipped ? unzipFile(file) : file;
- string const format = file_.guessFormatFromContents();
-
- if (format != "eps" && format != "ps") {
- readBB_lyxerrMessage(file_, zipped,"no(e)ps-format");
- return string();
- }
-
- static lyx::regex bbox_re(
- "^%%BoundingBox:\\s*([[:digit:]]+)\\s+([[:digit:]]+)\\s+([[:digit:]]+)\\s+([[:digit:]]+)");
- ifstream is(file_.toFilesystemEncoding().c_str());
- while (is) {
- string s;
- getline(is,s);
- lyx::smatch what;
- if (regex_match(s, what, bbox_re)) {
- // Our callers expect the tokens in the string
- // separated by single spaces.
- // FIXME: change return type from string to something
- // sensible
- ostringstream os;
- os << what.str(1) << ' ' << what.str(2) << ' '
- << what.str(3) << ' ' << what.str(4);
- string const bb = os.str();
- readBB_lyxerrMessage(file_, zipped, bb);
- return bb;
- }
- }
- readBB_lyxerrMessage(file_, zipped, "no bb found");
- return string();
-}
-
-
int compare_timestamps(FileName const & file1, FileName const & file2)
{
// If the original is newer than the copy, then copy the original