X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fconverter.C;h=fab51433f8b268b2c5909c2495dc38e65b688af7;hb=a235c8b10f71c3d77930ba0fb3270991b1134203;hp=c964d685c92ae88ef8f8f31b1c683bfe25070d8f;hpb=567e0d583fe716c2b3889f868e4902a6dfdab13a;p=lyx.git diff --git a/src/converter.C b/src/converter.C index c964d685c9..fab51433f8 100644 --- a/src/converter.C +++ b/src/converter.C @@ -15,7 +15,6 @@ #endif #include -#include // sort() #include "converter.h" #include "lyxrc.h" @@ -33,8 +32,9 @@ using std::map; using std::vector; using std::queue; using std::pair; -using std::sort; using std::endl; +using std::find; +using std::find_if; ////////////////////////////////////////////////////////////////////////////// @@ -52,68 +52,49 @@ string const add_options(string const & command, string const & options) ////////////////////////////////////////////////////////////////////////////// -Format::Format(string const & n) - : name(n), in_degree(0) +void Formats::Add(string const & name) { - struct Item { - char const * name; - char const * prettyname; - }; - Item items[] = { - { "tex", "LaTeX" }, - { "dvi", "DVI" }, - { "ps", "PostScript" }, - { "txt", "Ascii" }, - { "html", "HTML" }, - { "pdf", "PDF" }, - { 0, 0} - }; - - prettyname = n; - for (int i = 0; items[i].name != 0; ++i) - if (items[i].name == n) { - prettyname = items[i].prettyname; - break; - } + if (formats.find(name) == formats.end()) + formats[name] = Format(name, name, name, string()); } -void Formats::Add(string const & name) +void Formats::Add(string const & name, string const & extension, + string const & prettyname, string const & shortcut) { - if (formats.find(name) == formats.end()) - formats[name] = Format(name); + formats[name] = Format(name, extension, prettyname, shortcut); } void Formats::SetViewer(string const & name, string const & command) { - string command2 = subst(command, "$$FName", "'$$FName'"); - if (!contains(command,"$$FName")) - command2 += " '$$FName'"; + string command2 = command; + if (!contains(command2,"$$FName")) + command2 += " $$FName"; Add(name); GetFormat(name)->viewer = command2; } -bool Formats::View(Buffer * buffer, string const & filename) +bool Formats::View(Buffer const * buffer, string const & filename, + string const & format_name) { if (filename.empty()) return false; - string extension = GetExtension(filename); - Format * format = GetFormat(extension); + Format const * format = GetFormat(format_name); if (!format || format->viewer.empty()) { WriteAlert(_("Can not view file"), _("No information for viewing ") - + Formats::PrettyName(extension)); + + Formats::PrettyName(format_name)); return false; } string command = format->viewer; - if (extension == "dvi" && + if (format_name == "dvi" && !lyxrc.view_dvi_paper_option.empty()) { string options = lyxrc.view_dvi_paper_option; options += " " + Converter::dvi_papersize(buffer); @@ -127,7 +108,7 @@ bool Formats::View(Buffer * buffer, string const & filename) lyxerr << "Executing command: " << command2 << endl; ShowMessage(buffer, _("Executing command:"), command2); - command = subst(command, "$$FName", filename); + command = subst(command, "$$FName", QuoteName(filename)); Systemcalls one; int res = one.startscript(Systemcalls::SystemDontWait, command); @@ -153,42 +134,68 @@ Format * Formats::GetFormat(string const & name) string const Formats::PrettyName(string const & name) { - string format; - Converter::SplitFormat(name, format); - Format * f = GetFormat(format); - if (f) - return f->prettyname; + Format const * format = GetFormat(name); + if (format) + return format->prettyname; else - return format; + return name; } +string const Formats::Extension(string const & name) +{ + Format const * format = GetFormat(name); + if (format) + return format->extension; + else + return name; +} + ////////////////////////////////////////////////////////////////////////////// +class compare_Command { +public: + compare_Command(Command const & c) : com(c) {} + bool operator()(Command const & c) { + return c.from == com.from && c.to == com.to; + } +private: + Command com; +}; + + void Converter::Add(string const & from, string const & to, string const & command, string const & flags) { - if (command == "none") + Formats::Add(from); + Formats::Add(to); + Command Com(Formats::GetFormat(from), Formats::GetFormat(to), command); + vector::iterator it = find_if(commands.begin(), + commands.end(), + compare_Command(Com)); + + if (command.empty() || command == "none") { + if (it != commands.end()) + commands.erase(it); return; + } - string command2 = - subst(command, "$$FName", "'$$FName'"); - command2 = subst(command2, "$$BaseName", "'$$BaseName'"); - command2 = subst(command2, "$$OutName", "'$$OutName'"); - Command Com(from, to, command2); - - if (from == "tex" && - (to == "dvi" || - (to == "pdf" && latex_command.empty()))) - latex_command = command2; // Read the flags - string flag_name,flag_value; string flag_list(flags); while (!flag_list.empty()) { - flag_list = split(flag_list, flag_value,','); + string flag_name, flag_value; + flag_list = split(flag_list, flag_value, ','); flag_value = split(flag_value, flag_name, '='); - if (flag_name == "originaldir") + if (flag_name == "*") { + if (it != commands.end()) { + Com = *it; + Com.command = command; + } + } + else if (flag_name == "latex") + Com.latex = true; + else if (flag_name == "originaldir") Com.original_dir = true; else if (flag_name == "needaux") Com.need_aux = true; @@ -197,41 +204,60 @@ void Converter::Add(string const & from, string const & to, ? "$$BaseName" : flag_value; else if (flag_name == "resultfile") Com.result_file = flag_value; + else if (flag_name == "parselog") + Com.parselog = flag_value; + else if (flag_name == "disable") { + while (!flag_value.empty()) { + string tmp; + flag_value = split(flag_value, tmp, '&'); + Com.disable.push_back(tmp); + } + } } if (!Com.result_dir.empty() && Com.result_file.empty()) Com.result_file = "index." + to; + //if (!contains(command, "$$FName")) + // Com.latex = true; - for (vector::iterator it = commands.begin(); - it != commands.end(); ++it) - if ((*it).from == from && (*it).to == to) { - *it = Com; - return; - } + if (Com.latex && (latex_command.empty() || to == "dvi")) + latex_command = command; + // If we have both latex & pdflatex, we set latex_command to latex. + // The latex_command is used to update the .aux file when running + // a converter that uses it. + + if (it != commands.end()) { + *it = Com; + return; + } commands.push_back(Com); - Formats::Add(from); - Formats::Add(to); - ++Formats::GetFormat(to)->in_degree; } -vector< pair > const -Converter::GetReachable(string const & from, bool only_viewable) +inline +bool enable(vector::iterator it, string const & from) +{ + return find((*it).disable.begin(), (*it).disable.end(), from) + == (*it).disable.end(); +} + + +vector const +Converter::GetReachable(string const & from, string const & stop_format, + bool only_viewable) { - vector< pair > result; - Format * format = Formats::GetFormat(from); + vector result; + Format const * format = Formats::GetFormat(from); if (!format) return result; - int sort_start = 0; - if (!only_viewable || !format->viewer.empty()) { - result.push_back(pair(from, format->prettyname)); - sort_start = 1; - } + if (!only_viewable || !format->viewer.empty()) + result.push_back(FormatPair(format, 0, "")); queue< vector::iterator > Q; for (vector::iterator it = commands.begin(); it != commands.end(); ++it) - if ((*it).from == from) { + if ((*it).from->name == from && enable(it, from) + && (*it).to->name != stop_format) { Q.push(it); (*it).visited = true; } else @@ -239,50 +265,73 @@ Converter::GetReachable(string const & from, bool only_viewable) while (!Q.empty()) { vector::iterator it = Q.front(); - format = Formats::GetFormat((*it).to); - string name = format->name; - string prettyname = format->prettyname; - if (format->in_degree > 1) { - name += ":" + (*it).from; - string tmp; - split((*it).command, tmp, ' '); - prettyname += _(" (using ") + tmp + ")"; - } - if (!only_viewable || !format->viewer.empty()) - result.push_back(pair(name, prettyname)); Q.pop(); + if (!only_viewable || !(*it).to->viewer.empty()) + result.push_back(FormatPair((*it).to, (*it).from, + (*it).command)); for (vector::iterator it2 = commands.begin(); it2 != commands.end(); ++it2) - if (!(*it2).visited && (*it).to == (*it2).from) { + if (!(*it2).visited && (*it).to == (*it2).from && + enable(it2, from) && + (*it2).to->name != stop_format) { Q.push(it2); (*it2).visited = true; } } - sort(result.begin() + sort_start, result.end()); return result; } -bool Converter::Convert(Buffer * buffer, string const & from_file, - string const & to_file, string const & using_format, - string * view_file) +bool Converter::IsReachable(string const & from, string const & to) +{ + if (from == to) + return true; + + queue< vector::iterator > Q; + for (vector::iterator it = commands.begin(); + it != commands.end(); ++it) + if ((*it).from->name == from && enable(it, from)) { + Q.push(it); + (*it).visited = true; + } else + (*it).visited = false; + + while (!Q.empty()) { + vector::iterator it = Q.front(); + Q.pop(); + if ((*it).to->name == to) + return true; + for (vector::iterator it2 = commands.begin(); + it2 != commands.end(); ++it2) + if (!(*it2).visited && (*it).to == (*it2).from && + enable(it2, from)) { + Q.push(it2); + (*it2).visited = true; + } + } + return false; +} + + +bool Converter::Convert(Buffer const * buffer, + string const & from_file, string const & to_file_base, + string const & from_format, string const & to_format, + string const & using_format, string & to_file) { - if (view_file) - *view_file = to_file; + to_file = ChangeExtension(to_file_base, + Formats::Extension(to_format)); - string from_format = GetExtension(from_file); - string to_format = GetExtension(to_file); if (from_format == to_format) if (from_file != to_file) - return lyx::rename(from_file.c_str(), to_file.c_str()); + return lyx::rename(from_file, to_file); else return true; queue< vector::iterator > Q; for (vector::iterator it = commands.begin(); it != commands.end(); ++it) - if ((*it).from == from_format) { + if ((*it).from->name == from_format && enable(it, from_format)) { Q.push(it); (*it).visited = true; (*it).previous = commands.end(); @@ -299,15 +348,16 @@ bool Converter::Convert(Buffer * buffer, string const & from_file, vector::iterator it; while (!Q.empty()) { it = Q.front(); - if ((*it).to == to_format && - (using_format.empty() || using_format == (*it).from)) { + if ((*it).to->name == to_format && + (using_format.empty() || using_format == (*it).from->name)) { found = true; break; } Q.pop(); for (vector::iterator it2 = commands.begin(); it2 != commands.end(); ++it2) - if (!(*it2).visited && (*it).to == (*it2).from) { + if (!(*it2).visited && (*it).to == (*it2).from && + enable(it2, from_format)) { Q.push(it2); (*it2).visited = true; (*it2).previous = it; @@ -340,18 +390,17 @@ bool Converter::Convert(Buffer * buffer, string const & from_file, S.rbegin(); rit != S.rend(); ++rit) { it = *rit; lyxerr << "Converting from " - << (*it).from << " to " << (*it).to << endl; + << (*it).from->name << " to " << (*it).to->name << endl; infile = outfile; outfile = (*it).result_dir.empty() - ? ChangeExtension(from_file, (*it).to) + ? ChangeExtension(from_file, (*it).to->extension) : AddName(subst((*it).result_dir, "$$BaseName", from_base), subst((*it).result_file, "$$BaseName", OnlyFilename(from_base))); - if ((*it).from == "tex" && - ( (*it).to == "dvi" || (*it).to == "pdf") ) { - lyxrc.pdf_mode = (*it).to == "pdf"; + if ((*it).latex) { + lyxrc.pdf_mode = (*it).to->name == "pdf"; lyxerr << "Running " << (*it).command << endl; run_latex = true; if (!runLaTeX(buffer, (*it).command)) @@ -370,58 +419,85 @@ bool Converter::Convert(Buffer * buffer, string const & from_file, ? outfile : MakeRelPath(outfile, path); string command = (*it).command; - command = subst(command, "$$FName", infile2); - command = subst(command, "$$BaseName", from_base); - command = subst(command, "$$OutName", outfile2); + command = subst(command, "$$FName", QuoteName(infile2)); + command = subst(command, "$$BaseName", QuoteName(from_base)); + command = subst(command, "$$OutName", QuoteName(outfile2)); - if ((*it).from == "dvi" && (*it).to == "ps") + if (!(*it).parselog.empty()) + command += " 2> " + QuoteName(infile2 + ".out"); + + if ((*it).from->name == "dvi" && (*it).to->name == "ps") command = add_options(command, dvips_options(buffer)); lyxerr << "Calling " << command << endl; - ShowMessage(buffer, _("Executing command:"), command); + if (buffer) + ShowMessage(buffer, _("Executing command:"), command); Systemcalls one; int res; - if ((*it).original_dir) { + if ((*it).original_dir && buffer) { Path p(buffer->filepath); res = one.startscript(Systemcalls::System, command); } else res = one.startscript(Systemcalls::System, command); + + if (!(*it).parselog.empty()) { + string const logfile = infile2 + ".log"; + string const command2 = (*it).parselog + + " < " + QuoteName(infile2 + ".out") + + " > " + QuoteName(logfile); + one.startscript(Systemcalls::System, command2); + if (!scanLog(buffer, command, logfile)) + return false; + } + if (res) { - WriteAlert(_("Can not convert file"), - "Error while executing", - command.substr(0, 50)); + if ((*it).to->name == "program") + WriteAlert(_("There were errors during the Build process."), + _("You should try to fix them.")); + else + WriteAlert(_("Can not convert file"), + "Error while executing", + command.substr(0, 50)); return false; } } } if (!(*it).result_dir.empty()) { - if (view_file) - *view_file = AddName(subst((*it).result_dir, - "$$BaseName", to_base), - subst((*it).result_file, - "$$BaseName", OnlyFilename(to_base))); + to_file = AddName(subst((*it).result_dir, + "$$BaseName", to_base), + subst((*it).result_file, + "$$BaseName", OnlyFilename(to_base))); if (from_base != to_base) { string from = subst((*it).result_dir, "$$BaseName", from_base); string to = subst((*it).result_dir, "$$BaseName", to_base); - return lyx::rename(from.c_str(), to.c_str()); + return lyx::rename(from, to); } - } else if (outfile != to_file) - if ((*it).from == "tex" && - ( (*it).to == "dvi" || (*it).to == "pdf") ) - return lyx::copy(outfile.c_str(), to_file.c_str()); + if ((*it).latex) + return lyx::copy(outfile, to_file); else - return lyx::rename(outfile.c_str(), to_file.c_str()); + return lyx::rename(outfile, to_file); return true; } +bool Converter::Convert(Buffer const * buffer, + string const & from_file, string const & to_file_base, + string const & from_format, string const & to_format, + string const & using_format) +{ + string to_file; + return Convert(buffer, from_file, to_file_base, from_format, to_format, + using_format, to_file); +} + + string const Converter::SplitFormat(string const & str, string & format) { string using_format = split(str, format, ':'); @@ -431,40 +507,101 @@ string const Converter::SplitFormat(string const & str, string & format) } -bool Converter::runLaTeX(Buffer * buffer, string const & command) +bool Converter::scanLog(Buffer const * buffer, string const & command, + string const & filename) { - + if (!buffer) + return false; + BufferView * bv = buffer->getUser(); + bool need_redraw = false; + if (bv) { + ProhibitInput(bv); + // Remove all error insets + need_redraw = bv->removeAutoInsets(); + } - if (!bv->text) return 0; + LaTeX latex("", filename, ""); + TeXErrors terr; + int result = latex.scanLogFile(terr); + if (bv) { + if ((result & LaTeX::ERRORS)) { + // Insert all errors as errors boxes + bv->insertErrors(terr); + need_redraw = true; + } + if (need_redraw) { + bv->redraw(); + bv->fitCursor(bv->text); + } + AllowInput(bv); + } - ProhibitInput(bv); + if ((result & LaTeX::ERRORS)) { + int num_errors = latex.getNumErrors(); + string s; + string t; + if (num_errors == 1) { + s = _("One error detected"); + t = _("You should try to fix it."); + } else { + s = tostr(num_errors); + s += _(" errors detected."); + t = _("You should try to fix them."); + } + string head; + split(command, head, ' '); + WriteAlert(_("There were errors during running of ") + head, + s, t); + return false; + } else if (result & LaTeX::NO_OUTPUT) { + string const s = _("The operation resulted in"); + string const t = _("an empty file."); + WriteAlert(_("Resulting file is empty"), s, t); + return false; + } + return true; +} + +bool Converter::runLaTeX(Buffer const * buffer, string const & command) +{ + if (!buffer) + return false; + + BufferView * bv = buffer->getUser(); string name = buffer->getLatexName(); + bool need_redraw = false; - bv->owner()->getMiniBuffer()->Set(_("Running LaTeX...")); + if (bv) { + ProhibitInput(bv); + bv->owner()->getMiniBuffer()->Set(_("Running LaTeX...")); + // Remove all error insets + need_redraw = bv->removeAutoInsets(); + } - // Remove all error insets - bool a = bv->removeAutoInsets(); // do the LaTex run(s) TeXErrors terr; LaTeX latex(command, name, buffer->filepath); int result = latex.run(terr, - bv->owner()->getMiniBuffer()); // running latex + bv ? bv->owner()->getMiniBuffer() : 0); + - if ((result & LaTeX::ERRORS)) { - // Insert all errors as errors boxes - bv->insertErrors(terr); - } + if (bv) { + if ((result & LaTeX::ERRORS)) { + // Insert all errors as errors boxes + bv->insertErrors(terr); + need_redraw = true; + } - // if we removed error insets before we ran LaTeX or if we inserted - // error insets after we ran LaTeX this must be run: - if (a || (result & LaTeX::ERRORS)){ - bv->redraw(); - bv->fitCursor(); - //bv->updateScrollbar(); - } + // if we removed error insets before we ran LaTeX or if we inserted + // error insets after we ran LaTeX this must be run: + if (need_redraw) { + bv->redraw(); + bv->fitCursor(bv->text); + } + } // check return value from latex.run(). if ((result & LaTeX::NO_LOGFILE)) { @@ -484,10 +621,21 @@ bool Converter::runLaTeX(Buffer * buffer, string const & command) } WriteAlert(_("There were errors during the LaTeX run."), s, t); + } else if (result & LaTeX::NO_OUTPUT) { + string const s = _("The operation resulted in"); + string const t = _("an empty file."); + WriteAlert(_("Resulting file is empty"), s, t); } - AllowInput(bv); + + if (bv) + AllowInput(bv); - return (result & (LaTeX::NO_LOGFILE | LaTeX::ERRORS)) == 0; + int const ERROR_MASK = + LaTeX::NO_LOGFILE | + LaTeX::ERRORS | + LaTeX::NO_OUTPUT; + + return (result & ERROR_MASK) == 0; } @@ -521,6 +669,9 @@ string const Converter::dvi_papersize(Buffer const * buffer) string const Converter::dvips_options(Buffer const * buffer) { string result; + if (!buffer) + return result; + if (buffer->params.use_geometry && buffer->params.papersize2 == BufferParams::VM_PAPER_CUSTOM && !lyxrc.print_paper_dimension_flag.empty() @@ -546,3 +697,8 @@ string const Converter::dvips_options(Buffer const * buffer) result += ' ' + lyxrc.print_landscape_flag; return result; } + + +void Converter::init() +{ +}