X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fsupport%2FSystemcall.cpp;h=ca804096603eb81b7f35732fe6bac5e6ac8820ab;hb=bd2e7480b17a8fa8bc8ed5ec60eb4f02d75a0f1e;hp=100023e29d14ee8cdda29cb1564b242344f61692;hpb=c58f009c9b9ff3b6f9f17d27f893e8f4ea2174d6;p=lyx.git diff --git a/src/support/Systemcall.cpp b/src/support/Systemcall.cpp index 100023e29d..ca80409660 100644 --- a/src/support/Systemcall.cpp +++ b/src/support/Systemcall.cpp @@ -15,6 +15,7 @@ #include "support/debug.h" #include "support/filetools.h" +#include "support/gettext.h" #include "support/lstrings.h" #include "support/qstring_helpers.h" #include "support/Systemcall.h" @@ -72,6 +73,8 @@ public: void toggleWarning(QString const &, QString const &, QString const &) {} void error(QString const &, QString const &) {} void information(QString const &, QString const &) {} + int prompt(docstring const &, docstring const &, int default_but, int, + docstring const &, docstring const &) { return default_but; } }; @@ -130,8 +133,7 @@ namespace { /* * This is a parser that (mostly) mimics the behavior of a posix shell as * regards quoting, but its output is tailored for being processed by QProcess. - * Note that shell metacharacters are not parsed and only output redirection - * is taken into account. + * Note that shell metacharacters are not parsed. * * The escape character is the backslash. * A backslash that is not quoted preserves the literal value of the following @@ -164,13 +166,14 @@ namespace { * "\a" -> "\a" * "a\"b" -> "a"""b" */ -string const parsecmd(string const & incmd, string & outfile, string & errfile) +string const parsecmd(string const & incmd, string & infile, string & outfile, + string & errfile) { bool in_single_quote = false; bool in_double_quote = false; bool escaped = false; string const python_call = "python -tt"; - vector outcmd(3); + vector outcmd(4); size_t start = 0; if (prefixIs(incmd, python_call)) { @@ -215,6 +218,8 @@ string const parsecmd(string const & incmd, string & outfile, string & errfile) outcmd[o] = rtrim(outcmd[o], "1"); o = 1; } + } else if (c == '<' && !(in_double_quote || escaped)) { + o = 3; } else { if (escaped && in_double_quote) outcmd[o] += '\\'; @@ -222,6 +227,7 @@ string const parsecmd(string const & incmd, string & outfile, string & errfile) escaped = false; } } + infile = trim(outcmd[3], " \""); outfile = trim(outcmd[1], " \""); errfile = trim(outcmd[2], " \""); return trim(outcmd[0]); @@ -234,14 +240,15 @@ string const parsecmd(string const & incmd, string & outfile, string & errfile) int Systemcall::startscript(Starttype how, string const & what, string const & path, bool process_events) { - lyxerr << "\nRunning: " << what << endl; + LYXERR(Debug::INFO,"Running: " << what); + string infile; string outfile; string errfile; - QString cmd = QString::fromLocal8Bit( - parsecmd(what, outfile, errfile).c_str()); + QString const cmd = QString::fromLocal8Bit( + parsecmd(what, infile, outfile, errfile).c_str()); - SystemcallPrivate d(outfile, errfile); + SystemcallPrivate d(infile, outfile, errfile); d.startProcess(cmd, path); @@ -274,15 +281,19 @@ int Systemcall::startscript(Starttype how, string const & what, } -SystemcallPrivate::SystemcallPrivate(std::string const & of, +SystemcallPrivate::SystemcallPrivate(std::string const & sf, + std::string const & of, std::string const & ef) : process_(new QProcess), out_index_(0), err_index_(0), + in_file_(sf), out_file_(of), err_file_(ef), process_events_(false) { + if (!in_file_.empty()) + process_->setStandardInputFile(QString::fromLocal8Bit(in_file_.c_str())); if (!out_file_.empty()) { if (out_file_[0] == '&') { if (subst(out_file_, " ", "") == "&2" @@ -350,7 +361,7 @@ void SystemcallPrivate::startProcess(QString const & cmd, string const & path) void SystemcallPrivate::processEvents() { - if(process_events_) { + if (process_events_) { QCoreApplication::processEvents(/*QEventLoop::ExcludeUserInputEvents*/); } } @@ -363,11 +374,26 @@ void SystemcallPrivate::waitAndProcessEvents() } +namespace { + +bool queryStopCommand(QString const & cmd) +{ + docstring text = bformat(_( + "The command\n%1$s\nhas not yet completed.\n\n" + "Do you want to stop it?"), qstring_to_ucs4(cmd)); + return ProgressInterface::instance()->prompt(_("Stop command?"), text, + 1, 1, _("&Stop it"), _("Let it &run")) == 0; +} + +} + + bool SystemcallPrivate::waitWhile(State waitwhile, bool process_events, int timeout) { if (!process_) return false; + bool timedout = false; process_events_ = process_events; // Block GUI while waiting, @@ -375,8 +401,24 @@ bool SystemcallPrivate::waitWhile(State waitwhile, bool process_events, int time if (!process_events_) { if (waitwhile == Starting) return process_->waitForStarted(timeout); - if (waitwhile == Running) - return process_->waitForFinished(timeout); + if (waitwhile == Running) { + int bump = 2; + while (!timedout) { + if (process_->waitForFinished(timeout)) + return true; + bool stop = queryStopCommand(cmd_); + // The command may have finished in the meantime + if (process_->state() == QProcess::NotRunning) + return true; + if (stop) { + timedout = true; + process_->kill(); + } else { + timeout *= bump; + bump = 3; + } + } + } return false; } @@ -388,13 +430,24 @@ bool SystemcallPrivate::waitWhile(State waitwhile, bool process_events, int time return state != Error; } - // process events while waiting whith timeout + // process events while waiting with timeout QTime timer; timer.start(); - while (state == waitwhile && state != Error && timer.elapsed() < timeout) { + while (state == waitwhile && state != Error && !timedout) { waitAndProcessEvents(); + if (timer.elapsed() > timeout) { + bool stop = queryStopCommand(cmd_); + // The command may have finished in the meantime + if (process_->state() == QProcess::NotRunning) + break; + if (stop) { + timedout = true; + process_->kill(); + } else + timeout *= 3; + } } - return (state != Error) && (timer.elapsed() < timeout); + return (state != Error) && !timedout; }