X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fconverter.C;h=370843056bf2a18ce44abe252813bc62dd0746c0;hb=78046794ccfce3a20751e00b35295c290853afd6;hp=ac91f7cf7f3039ad8e0469ad8c557481d4af00c3;hpb=29f7055e9527314060b4a74c31a46155ff264a63;p=lyx.git diff --git a/src/converter.C b/src/converter.C index ac91f7cf7f..370843056b 100644 --- a/src/converter.C +++ b/src/converter.C @@ -1,440 +1,291 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2000 The LyX Team. +/** + * \file converter.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * - * ====================================================== */ + * \author Dekel Tsur + * + * Full author contact details are available in file CREDITS. + */ #include -#ifdef __GNUG__ -#pragma implementation -#endif - -#include - #include "converter.h" -#include "lyxrc.h" -#include "support/syscall.h" -#include "support/path.h" + #include "buffer.h" -#include "bufferview_funcs.h" +#include "buffer_funcs.h" +#include "bufferparams.h" +#include "debug.h" +#include "format.h" +#include "gettext.h" #include "LaTeX.h" -#include "LyXView.h" -#include "minibuffer.h" -#include "lyx_gui_misc.h" -#include "lyx_cb.h" // ShowMessage() -using std::map; -using std::vector; -using std::queue; -using std::pair; +#include "frontends/Alert.h" + +#include "support/filetools.h" +#include "support/lyxlib.h" +#include "support/path.h" +#include "support/systemcall.h" + +using lyx::support::AddName; +using lyx::support::bformat; +using lyx::support::ChangeExtension; +using lyx::support::compare_ascii_no_case; +using lyx::support::contains; +using lyx::support::DirList; +using lyx::support::GetExtension; +using lyx::support::LibScriptSearch; +using lyx::support::MakeRelPath; +using lyx::support::OnlyFilename; +using lyx::support::OnlyPath; +using lyx::support::Path; +using lyx::support::prefixIs; +using lyx::support::QuoteName; +using lyx::support::rename; +using lyx::support::split; +using lyx::support::subst; +using lyx::support::Systemcall; + using std::endl; -using std::find; using std::find_if; +using std::string; +using std::vector; -////////////////////////////////////////////////////////////////////////////// -vector Converter::commands; -string Converter::latex_command; +namespace { -inline -string const add_options(string const & command, string const & options) -{ - string head; - string tail = split(command, head, ' '); - return head + ' ' + options + ' ' + tail; -} +string const token_from("$$i"); +string const token_base("$$b"); +string const token_to("$$o"); +string const token_path("$$p"); -////////////////////////////////////////////////////////////////////////////// -bool Format::dummy() const +string const add_options(string const & command, string const & options) { - return extension.empty(); + string head; + string const tail = split(command, head, ' '); + return head + ' ' + options + ' ' + tail; } -void Formats::Add(string const & name) +string const dvipdfm_options(BufferParams const & bp) { - if (formats.find(name) == formats.end()) - formats[name] = Format(name, name, name, "", ""); -} - + string result; -void Formats::Add(string const & name, string const & extension, - string const & prettyname, string const & shortcut) -{ + if (bp.papersize2 != VM_PAPER_CUSTOM) { + string const paper_size = bp.paperSizeName(); + if (paper_size != "b5" && paper_size != "foolscap") + result = "-p "+ paper_size; - if (prettyname.empty()) { - FormatList::iterator it = formats.find(name); - if (it != formats.end()) - formats.erase(it); - return; + if (bp.orientation == ORIENTATION_LANDSCAPE) + result += " -l"; } - string old_viewer = formats[name].viewer; - formats[name] = Format(name, extension, prettyname, shortcut, - old_viewer); + return result; } +} // namespace anon -void Formats::SetViewer(string const & name, string const & command) -{ - string command2 = command; - if (!command2.empty() && !contains(command2,"$$FName")) - command2 += " $$FName"; - Add(name); - GetFormat(name)->viewer = command2; -} +Converter::Converter(string const & f, string const & t, string const & c, + string const & l): from(f), to(t), command(c), flags(l), + From(0), To(0), latex(false), + original_dir(false), need_aux(false) +{} -bool Formats::View(Buffer const * buffer, string const & filename, - string const & format_name) +void Converter::readFlags() { - if (filename.empty()) - return false; - - Format const * format = GetFormat(format_name); - if (!format || format->viewer.empty()) { - WriteAlert(_("Can not view file"), - _("No information for viewing ") - + PrettyName(format_name)); - return false; - } - - string command = format->viewer; - - if (format_name == "dvi" && - !lyxrc.view_dvi_paper_option.empty()) { - string options = lyxrc.view_dvi_paper_option; - options += " " + Converter::dvi_papersize(buffer); - if (buffer->params.orientation - == BufferParams::ORIENTATION_LANDSCAPE) - options += 'r'; - command = add_options(command, options); - } - - string command2 = subst(command, "$$FName", OnlyFilename(filename)); - lyxerr << "Executing command: " << command2 << endl; - ShowMessage(buffer, _("Executing command:"), command2); - - command = subst(command, "$$FName", QuoteName(filename)); - Systemcalls one; - int res = one.startscript(Systemcalls::SystemDontWait, command); - - if (res) { - WriteAlert(_("Can not view file"), - _("Error while executing"), - command.substr(0, 50)); - return false; + string flag_list(flags); + while (!flag_list.empty()) { + string flag_name, flag_value; + flag_list = split(flag_list, flag_value, ','); + flag_value = split(flag_value, flag_name, '='); + if (flag_name == "latex") + latex = true; + else if (flag_name == "originaldir") + original_dir = true; + else if (flag_name == "needaux") + need_aux = true; + else if (flag_name == "resultdir") + result_dir = (flag_value.empty()) + ? token_base : flag_value; + else if (flag_name == "resultfile") + result_file = flag_value; + else if (flag_name == "parselog") + parselog = flag_value; } - return true; + if (!result_dir.empty() && result_file.empty()) + result_file = "index." + formats.extension(to); + //if (!contains(command, token_from)) + // latex = true; } -Format * Formats::GetFormat(string const & name) +bool operator<(Converter const & a, Converter const & b) { - FormatList::iterator it = formats.find(name); - if (it != formats.end()) - return &it->second; + // use the compare_ascii_no_case instead of compare_no_case, + // because in turkish, 'i' is not the lowercase version of 'I', + // and thus turkish locale breaks parsing of tags. + int const i = compare_ascii_no_case(a.From->prettyname(), + b.From->prettyname()); + if (i == 0) + return compare_ascii_no_case(a.To->prettyname(), + b.To->prettyname()) < 0; else - return 0; + return i < 0; } -string const Formats::PrettyName(string const & name) -{ - Format const * format = GetFormat(name); - if (format) - return format->prettyname; - else - return name; -} +class compare_Converter { +public: + compare_Converter(string const & f, string const & t) + : from(f), to(t) {} + bool operator()(Converter const & c) { + return c.from == from && c.to == to; + } +private: + string const & from; + string const & to; +}; -string const Formats::Extension(string const & name) + +Converter const * Converters::getConverter(string const & from, + string const & to) { - Format const * format = GetFormat(name); - if (format) - return format->extension; + ConverterList::const_iterator cit = + find_if(converterlist_.begin(), converterlist_.end(), + compare_Converter(from, to)); + if (cit != converterlist_.end()) + return &(*cit); else - return name; + return 0; } -vector -const Formats::GetAllFormats() +int Converters::getNumber(string const & from, string const & to) { - vector result; - for (FormatList::iterator it = formats.begin(); - it != formats.end(); ++it) - result.push_back(it->second); - return result; + ConverterList::const_iterator cit = + find_if(converterlist_.begin(), converterlist_.end(), + compare_Converter(from, to)); + if (cit != converterlist_.end()) + return cit - converterlist_.begin(); + else + return -1; } -////////////////////////////////////////////////////////////////////////////// - -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) +void Converters::add(string const & from, string const & to, + string const & command, string const & flags) { - 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; + formats.add(from); + formats.add(to); + ConverterList::iterator it = find_if(converterlist_.begin(), + converterlist_.end(), + compare_Converter(from, to)); + + Converter converter(from, to, command, flags); + if (it != converterlist_.end() && !flags.empty() && flags[0] == '*') { + converter = *it; + converter.command = command; + converter.flags = flags; } + converter.readFlags(); - - // Read the flags - string flag_list(flags); - while (!flag_list.empty()) { - string flag_name, flag_value; - flag_list = split(flag_list, flag_value, ','); - flag_value = split(flag_value, flag_name, '='); - if (flag_name == "*") { - if (it != commands.end()) { - Com = *it; - Com.command = command; - } - } - else if (flag_name == "importer") - Com.importer = true; - 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; - else if (flag_name == "resultdir") - Com.result_dir = (flag_value.empty()) - ? "$$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; - - if (Com.latex && (latex_command.empty() || to == "dvi")) - latex_command = command; + if (converter.latex && (latex_command_.empty() || to == "dvi")) + latex_command_ = subst(command, token_from, ""); // 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; + if (it == converterlist_.end()) { + converterlist_.push_back(converter); + } else { + converter.From = it->From; + converter.To = it->To; + *it = converter; } - commands.push_back(Com); } -inline -bool enable(vector::iterator it, string const & from) +void Converters::erase(string const & from, string const & to) { - return find(it->disable.begin(), it->disable.end(), from) - == it->disable.end(); + ConverterList::iterator it = find_if(converterlist_.begin(), + converterlist_.end(), + compare_Converter(from, to)); + if (it != converterlist_.end()) + converterlist_.erase(it); } -vector const -Converter::GetReachableTo(string const & target) +// This method updates the pointers From and To in all the converters. +// The code is not very efficient, but it doesn't matter as the number +// of formats and converters is small. +// Furthermore, this method is called only on startup, or after +// adding/deleting a format in FormPreferences (the latter calls can be +// eliminated if the formats in the Formats class are stored using a map or +// a list (instead of a vector), but this will cause other problems). +void Converters::update(Formats const & formats) { - vector result; - - queue< vector::iterator > Q; - for (vector::iterator it = commands.begin(); - it != commands.end(); ++it) - if (it->to->name == target && it->importer) { - Q.push(it); - it->visited = true; - } else - it->visited = false; - - while (!Q.empty()) { - vector::iterator it = Q.front(); - Q.pop(); - result.push_back(FormatPair(it->from, 0, "")); - for (vector::iterator it2 = commands.begin(); - it2 != commands.end(); ++it2) - if (!it2->visited && it->from == it2->to && - it2->importer) { - Q.push(it2); - it2->visited = true; - } + ConverterList::iterator it = converterlist_.begin(); + ConverterList::iterator end = converterlist_.end(); + for (; it != end; ++it) { + it->From = formats.getFormat(it->from); + it->To = formats.getFormat(it->to); } - - return result; } -vector const -Converter::GetReachable(string const & from, bool only_viewable) +// This method updates the pointers From and To in the last converter. +// It is called when adding a new converter in FormPreferences +void Converters::updateLast(Formats const & formats) { - vector result; - Format const * format = formats.GetFormat(from); - if (!format) - return result; - - 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->name == from && enable(it, from) - && !it->importer) { - Q.push(it); - it->visited = true; - } else - it->visited = false; - - while (!Q.empty()) { - vector::iterator it = Q.front(); - 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 && - enable(it2, from) && !it2->importer) { - Q.push(it2); - it2->visited = true; - } + if (converterlist_.begin() != converterlist_.end()) { + ConverterList::iterator it = converterlist_.end() - 1; + it->From = formats.getFormat(it->from); + it->To = formats.getFormat(it->to); } - - return result; } -bool Converter::IsReachable(string const & from, string const & to) +void Converters::sort() { - if (from == to) - return true; + std::sort(converterlist_.begin(), converterlist_.end()); +} - 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; - } + +bool Converters::usePdflatex(Graph::EdgePath const & path) +{ + for (Graph::EdgePath::const_iterator cit = path.begin(); + cit != path.end(); ++cit) { + Converter const & conv = converterlist_[*cit]; + if (conv.latex) + return contains(conv.to, "pdf"); } 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) +bool Converters::convert(Buffer const * buffer, + string const & from_file, string const & to_file_base, + string const & from_format, string const & to_format, + string & to_file) { to_file = ChangeExtension(to_file_base, - formats.Extension(to_format)); + formats.extension(to_format)); if (from_format == to_format) - if (from_file != to_file) - 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->name == from_format && enable(it, from_format)) { - Q.push(it); - it->visited = true; - it->previous = commands.end(); - } else - it->visited = false; - - if (Q.empty()) { - WriteAlert(_("Can not convert file"), - ("Unknown format ") + from_format); - return false; - } - - bool found = false; - vector::iterator it; - while (!Q.empty()) { - it = Q.front(); - 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 && - enable(it2, from_format)) { - Q.push(it2); - it2->visited = true; - it2->previous = it; - } - } + return move(from_file, to_file, false); - if (!found) { - WriteAlert(_("Can not convert file"), - _("No information for converting from ") - + formats.PrettyName(from_format) + _(" to ") - + formats.PrettyName(to_format)); + Graph::EdgePath edgepath = getPath(from_format, to_format); + if (edgepath.empty()) { return false; } - - vector< vector::iterator > S; - while (it != commands.end()) { - S.push_back(it); - it = it->previous; - } + LatexRunParams runparams; + runparams.flavor = usePdflatex(edgepath) ? + LatexRunParams::PDFLATEX : LatexRunParams::LATEX; string path = OnlyPath(from_file); Path p(path); @@ -444,342 +295,340 @@ bool Converter::Convert(Buffer const * buffer, string to_base = ChangeExtension(to_file, ""); string infile; string outfile = from_file; - for (vector< vector::iterator >::reverse_iterator rit = - S.rbegin(); rit != S.rend(); ++rit) { - it = *rit; - bool dummy = it->to->dummy() && it->to->name != "program"; + for (Graph::EdgePath::const_iterator cit = edgepath.begin(); + cit != edgepath.end(); ++cit) { + Converter const & conv = converterlist_[*cit]; + bool dummy = conv.To->dummy() && conv.to != "program"; if (!dummy) - lyxerr << "Converting from " - << it->from->name << " to " << it->to->name << endl; + lyxerr[Debug::FILES] << "Converting from " + << conv.from << " to " << conv.to << endl; infile = outfile; - outfile = it->result_dir.empty() - ? ChangeExtension(from_file, it->to->extension) - : AddName(subst(it->result_dir, - "$$BaseName", from_base), - subst(it->result_file, - "$$BaseName", OnlyFilename(from_base))); - - if (it->latex) { - lyxrc.pdf_mode = it->to->name == "pdf"; - lyxerr << "Running " << it->command << endl; + outfile = conv.result_dir.empty() + ? ChangeExtension(from_file, conv.To->extension()) + : AddName(subst(conv.result_dir, + token_base, from_base), + subst(conv.result_file, + token_base, OnlyFilename(from_base))); + + // if input and output files are equal, we use a + // temporary file as intermediary (JMarc) + string real_outfile; + if (outfile == infile) { + real_outfile = infile; + outfile = AddName(buffer->temppath(), "tmpfile.out"); + } + + if (conv.latex) { run_latex = true; - if (!runLaTeX(buffer, it->command)) + string command = subst(conv.command, token_from, ""); + lyxerr[Debug::FILES] << "Running " << command << endl; + if (!runLaTeX(*buffer, command, runparams)) return false; } else { - if (it->need_aux && !run_latex - && !latex_command.empty()) { - lyxerr << "Running " << latex_command - << " to update aux file"<< endl; - runLaTeX(buffer, latex_command); + if (conv.need_aux && !run_latex + && !latex_command_.empty()) { + lyxerr[Debug::FILES] + << "Running " << latex_command_ + << " to update aux file"<< endl; + runLaTeX(*buffer, latex_command_, runparams); } - string infile2 = (it->original_dir) + string infile2 = (conv.original_dir) ? infile : MakeRelPath(infile, path); - string outfile2 = (it->original_dir) + string outfile2 = (conv.original_dir) ? outfile : MakeRelPath(outfile, path); - string command = it->command; - command = subst(command, "$$FName", QuoteName(infile2)); - command = subst(command, "$$BaseName", QuoteName(from_base)); - command = subst(command, "$$OutName", QuoteName(outfile2)); + string command = conv.command; + command = subst(command, token_from, QuoteName(infile2)); + command = subst(command, token_base, QuoteName(from_base)); + command = subst(command, token_to, QuoteName(outfile2)); + command = LibScriptSearch(command); - if (!it->parselog.empty()) + if (!conv.parselog.empty()) command += " 2> " + QuoteName(infile2 + ".out"); - if (it->from->name == "dvi" && it->to->name == "ps") + if (conv.from == "dvi" && conv.to == "ps") + command = add_options(command, + buffer->params().dvips_options()); + else if (conv.from == "dvi" && prefixIs(conv.to, "pdf")) command = add_options(command, - dvips_options(buffer)); + dvipdfm_options(buffer->params())); - lyxerr << "Calling " << command << endl; - if (buffer) - ShowMessage(buffer, _("Executing command:"), command); + lyxerr[Debug::FILES] << "Calling " << command << endl; + buffer->message(_("Executing command: ") + command); - Systemcalls::Starttype type = (dummy) - ? Systemcalls::SystemDontWait : Systemcalls::System; - Systemcalls one; + Systemcall::Starttype type = (dummy) + ? Systemcall::DontWait : Systemcall::Wait; + Systemcall one; int res; - if (it->original_dir && buffer) { - Path p(buffer->filepath); + if (conv.original_dir) { + Path p(buffer->filePath()); res = one.startscript(type, command); } else res = one.startscript(type, command); - if (!it->parselog.empty()) { + if (!real_outfile.empty()) { + if (!rename(outfile, real_outfile)) + res = -1; + else + lyxerr[Debug::FILES] + << "renaming file " << outfile + << " to " << real_outfile + << endl; + } + + if (!conv.parselog.empty()) { string const logfile = infile2 + ".log"; - string const command2 = it->parselog + + string const script = LibScriptSearch(conv.parselog); + string const command2 = script + " < " + QuoteName(infile2 + ".out") + " > " + QuoteName(logfile); - one.startscript(Systemcalls::System, command2); - if (!scanLog(buffer, command, logfile)) + one.startscript(Systemcall::Wait, command2); + if (!scanLog(*buffer, command, logfile)) return false; } if (res) { - 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)); + if (conv.to == "program") { + Alert::error(_("Build errors"), + _("There were errors during the build process.")); + } else { +// FIXME: this should go out of here. For example, here we cannot say if +// it is a document (.lyx) or something else. Same goes for elsewhere. + Alert::error(_("Cannot convert file"), + bformat(_("An error occurred whilst running %1$s"), + command.substr(0, 50))); + } return false; } } } - if (it->to->dummy()) + Converter const & conv = converterlist_[edgepath.back()]; + if (conv.To->dummy()) return true; - if (!it->result_dir.empty()) { - to_file = AddName(subst(it->result_dir, - "$$BaseName", to_base), - subst(it->result_file, - "$$BaseName", OnlyFilename(to_base))); + if (!conv.result_dir.empty()) { + to_file = AddName(subst(conv.result_dir, token_base, to_base), + subst(conv.result_file, + token_base, 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); - if (!lyx::rename(from, to)) { - WriteAlert(_("Error while trying to move directory:"), - from, ("to ") + to); + string from = subst(conv.result_dir, + token_base, from_base); + string to = subst(conv.result_dir, + token_base, to_base); + if (!rename(from, to)) { + Alert::error(_("Cannot convert file"), + bformat(_("Could not move a temporary file from %1$s to %2$s."), + from, to)); return false; } } - } else if (outfile != to_file) { - bool moved = (it->latex) - ? lyx::copy(outfile, to_file) - : lyx::rename(outfile, to_file); - if (!moved) { - WriteAlert(_("Error while trying to move file:"), - outfile, _("to ") + to_file); - return false; - } - } - - return true; + return true; + } else + return move(outfile, to_file, conv.latex); } -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) +// If from = /path/file.ext and to = /path2/file2.ext2 then this method +// moves each /path/file*.ext file to /path2/file2*.ext2' +bool Converters::move(string const & from, string const & to, bool copy) { - string to_file; - return Convert(buffer, from_file, to_file_base, from_format, to_format, - using_format, to_file); + if (from == to) + return true; + + bool no_errors = true; + string const path = OnlyPath(from); + string const base = OnlyFilename(ChangeExtension(from, "")); + string const to_base = ChangeExtension(to, ""); + string const to_extension = GetExtension(to); + + vector files = DirList(OnlyPath(from), GetExtension(from)); + for (vector::const_iterator it = files.begin(); + it != files.end(); ++it) + if (prefixIs(*it, base)) { + string const from2 = path + *it; + string to2 = to_base + it->substr(base.length()); + to2 = ChangeExtension(to2, to_extension); + lyxerr[Debug::FILES] << "moving " << from2 + << " to " << to2 << endl; + bool const moved = (copy) + ? lyx::support::copy(from2, to2) + : rename(from2, to2); + if (!moved && no_errors) { + Alert::error(_("Cannot convert file"), + bformat(_("Could not move a temporary file from %1$s to %2$s."), + from2, to2)); + no_errors = false; + } + } + return no_errors; } -string const Converter::SplitFormat(string const & str, string & format) +bool Converters::convert(Buffer const * buffer, + string const & from_file, string const & to_file_base, + string const & from_format, string const & to_format) { - string using_format = split(str, format, ':'); - if (format.empty()) - format = "dvi"; - return using_format; + string to_file; + return convert(buffer, from_file, to_file_base, from_format, to_format, + to_file); } -bool Converter::scanLog(Buffer const * buffer, string const & command, - string const & filename) +bool Converters::formatIsUsed(string const & format) { - if (!buffer) - return false; - - BufferView * bv = buffer->getUser(); - bool need_redraw = false; - if (bv) { - ProhibitInput(bv); - // Remove all error insets - need_redraw = bv->removeAutoInsets(); + ConverterList::const_iterator cit = converterlist_.begin(); + ConverterList::const_iterator end = converterlist_.end(); + for (; cit != end; ++cit) { + if (cit->from == format || cit->to == format) + return true; } + return false; +} + - LaTeX latex("", filename, ""); +bool Converters::scanLog(Buffer const & buffer, string const & /*command*/, + string const & filename) +{ + LatexRunParams runparams; + runparams.flavor = LatexRunParams::LATEX; + LaTeX latex("", runparams, 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); - } - 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; - } + if (result & LaTeX::ERRORS) + bufferErrors(buffer, terr); + return true; } +namespace { -bool Converter::runLaTeX(Buffer const * buffer, string const & command) -{ - if (!buffer) - return false; +class showMessage : public boost::signals::trackable { +public: + showMessage(Buffer const & b) : buffer_(b) {}; + void operator()(string const & m) + { + buffer_.message(m); + } +private: + Buffer const & buffer_; +}; - BufferView * bv = buffer->getUser(); - string name = buffer->getLatexName(); - bool need_redraw = false; +} - if (bv) { - ProhibitInput(bv); - bv->owner()->getMiniBuffer()->Set(_("Running LaTeX...")); - // Remove all error insets - need_redraw = bv->removeAutoInsets(); - } +bool Converters::runLaTeX(Buffer const & buffer, string const & command, + LatexRunParams const & runparams) +{ + buffer.busy(true); + buffer.message(_("Running LaTeX...")); - // do the LaTex run(s) + // do the LaTeX run(s) + string name = buffer.getLatexName(); + LaTeX latex(command, runparams, name, buffer.filePath()); TeXErrors terr; - LaTeX latex(command, name, buffer->filepath); - int result = latex.run(terr, - bv ? bv->owner()->getMiniBuffer() : 0); - - - if (bv) { - if ((result & LaTeX::ERRORS)) { - // Insert all errors as errors boxes - bv->insertErrors(terr); - need_redraw = true; - } + showMessage show(buffer); + latex.message.connect(show); + int result = latex.run(terr); - // 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); - } - } + if (result & LaTeX::ERRORS) + bufferErrors(buffer, terr); // check return value from latex.run(). if ((result & LaTeX::NO_LOGFILE)) { - WriteAlert(_("LaTeX did not work!"), - _("Missing log file:"), name); - } else 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."); - } - 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); + string str = bformat(_("LaTeX did not run successfully. " + "Additionally, LyX could not locate " + "the LaTeX log %1$s."), name); + Alert::error(_("LaTeX failed"), str); + } else if (result & LaTeX::NO_OUTPUT) { + Alert::warning(_("Output is empty"), + _("An empty output file was generated.")); } - if (bv) - AllowInput(bv); - - int const ERROR_MASK = + + buffer.busy(false); + + int const ERROR_MASK = LaTeX::NO_LOGFILE | LaTeX::ERRORS | LaTeX::NO_OUTPUT; - + return (result & ERROR_MASK) == 0; } -string const Converter::dvi_papersize(Buffer const * buffer) + +void Converters::buildGraph() { - char real_papersize = buffer->params.papersize; - if (real_papersize == BufferParams::PAPER_DEFAULT) - real_papersize = lyxrc.default_papersize; - - switch (real_papersize) { - case BufferParams::PAPER_A3PAPER: - return "a3"; - case BufferParams::PAPER_A4PAPER: - return "a4"; - case BufferParams::PAPER_A5PAPER: - return "a5"; - case BufferParams::PAPER_B5PAPER: - return "b5"; - case BufferParams::PAPER_EXECUTIVEPAPER: - return "foolscap"; - case BufferParams::PAPER_LEGALPAPER: - return "legal"; - case BufferParams::PAPER_USLETTER: - default: - return "us"; + G_.init(formats.size()); + ConverterList::iterator beg = converterlist_.begin(); + ConverterList::iterator end = converterlist_.end(); + for (ConverterList::iterator it = beg; it != end ; ++it) { + int const s = formats.getNumber(it->from); + int const t = formats.getNumber(it->to); + G_.addEdge(s,t); } } -string const Converter::dvips_options(Buffer const * buffer) +std::vector const +Converters::intToFormat(std::vector const & input) { - string result; - if (!buffer) - return result; - - if (buffer->params.use_geometry - && buffer->params.papersize2 == BufferParams::VM_PAPER_CUSTOM - && !lyxrc.print_paper_dimension_flag.empty() - && !buffer->params.paperwidth.empty() - && !buffer->params.paperheight.empty()) { - // using a custom papersize - result = lyxrc.print_paper_dimension_flag; - result += ' ' + buffer->params.paperwidth; - result += ',' + buffer->params.paperheight; - } else { - string paper_option = dvi_papersize(buffer); - if (paper_option == "us") - paper_option = "letter"; - if (paper_option != "letter" || - buffer->params.orientation != BufferParams::ORIENTATION_LANDSCAPE) { - // dvips won't accept -t letter -t landscape. In all other - // cases, include the paper size explicitly. - result = lyxrc.print_paper_flag; - result += ' ' + paper_option; - } + vector result(input.size()); + + vector::const_iterator it = input.begin(); + vector::const_iterator end = input.end(); + vector::iterator rit = result.begin(); + for ( ; it != end; ++it, ++rit) { + *rit = &formats.get(*it); } - if (buffer->params.orientation == BufferParams::ORIENTATION_LANDSCAPE) - result += ' ' + lyxrc.print_landscape_flag; return result; } +vector const +Converters::getReachableTo(string const & target, bool clear_visited) +{ + vector const & reachablesto = + G_.getReachableTo(formats.getNumber(target), clear_visited); + + return intToFormat(reachablesto); +} + -void Converter::init() +vector const +Converters::getReachable(string const & from, bool only_viewable, + bool clear_visited) { + vector const & reachables = + G_.getReachable(formats.getNumber(from), + only_viewable, + clear_visited); + + return intToFormat(reachables); +} + + +bool Converters::isReachable(string const & from, string const & to) +{ + return G_.isReachable(formats.getNumber(from), + formats.getNumber(to)); } + +Graph::EdgePath const +Converters::getPath(string const & from, string const & to) +{ + return G_.getPath(formats.getNumber(from), + formats.getNumber(to)); +} + + /// The global instance -Formats formats; +Converters converters; -// The global copy of the system lyxrc entries (everything except preferences) -Formats system_formats; +// The global copy after reading lyxrc.defaults +Converters system_converters;