X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fconverter.C;h=8ab0ff809ba948e222a7ed4b68804d84e3ee9e35;hb=b2f4586c984226bcc945d93891f3d0736d6ffb43;hp=c964d685c92ae88ef8f8f31b1c683bfe25070d8f;hpb=567e0d583fe716c2b3889f868e4902a6dfdab13a;p=lyx.git diff --git a/src/converter.C b/src/converter.C index c964d685c9..8ab0ff809b 100644 --- a/src/converter.C +++ b/src/converter.C @@ -4,7 +4,7 @@ * LyX, The Document Processor * * Copyright 1995 Matthias Ettrich - * Copyright 1995-2000 The LyX Team. + * Copyright 1995-2001 The LyX Team. * * ====================================================== */ @@ -14,125 +14,193 @@ #pragma implementation #endif -#include -#include // sort() +#include #include "converter.h" #include "lyxrc.h" -#include "support/syscall.h" -#include "support/path.h" #include "buffer.h" #include "bufferview_funcs.h" #include "LaTeX.h" #include "LyXView.h" -#include "minibuffer.h" -#include "lyx_gui_misc.h" #include "lyx_cb.h" // ShowMessage() +#include "gettext.h" +#include "BufferView.h" +#include "debug.h" + +#include "frontends/Alert.h" + +#include "support/filetools.h" +#include "support/lyxfunctional.h" +#include "support/path.h" +#include "support/systemcall.h" -using std::map; using std::vector; using std::queue; -using std::pair; -using std::sort; using std::endl; +using std::fill; +using std::find_if; +using std::reverse; +using std::sort; -////////////////////////////////////////////////////////////////////////////// +namespace { -map Formats::formats; -vector Converter::commands; -string Converter::latex_command; +string const token_from("$$i"); +string const token_base("$$b"); +string const token_to("$$o"); + +////////////////////////////////////////////////////////////////////////////// inline string const add_options(string const & command, string const & options) { string head; - string tail = split(command, head, ' '); + string const tail = split(command, head, ' '); return head + ' ' + options + ' ' + tail; } +} // namespace anon + ////////////////////////////////////////////////////////////////////////////// -Format::Format(string const & n) - : name(n), in_degree(0) -{ - 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; - } +bool Format::dummy() const +{ + return extension().empty(); } -void Formats::Add(string const & name) +bool Format::isChildFormat() const { - if (formats.find(name) == formats.end()) - formats[name] = Format(name); + if (name_.empty()) + return false; + return isdigit(name_[name_.length() - 1]); } -void Formats::SetViewer(string const & name, string const & command) +string const Format::parentFormat() const { + return name_.substr(0, name_.length() - 1); +} + +////////////////////////////////////////////////////////////////////////////// + +// This method should return a reference, and throw an exception +// if the format named name cannot be found (Lgb) +Format const * Formats::getFormat(string const & name) const +{ + FormatList::const_iterator cit = + find_if(formatlist.begin(), formatlist.end(), + lyx::compare_memfun(&Format::name, name)); + if (cit != formatlist.end()) + return &(*cit); + else + return 0; +} - string command2 = subst(command, "$$FName", "'$$FName'"); - if (!contains(command,"$$FName")) - command2 += " '$$FName'"; - Add(name); - GetFormat(name)->viewer = command2; +int Formats::getNumber(string const & name) const +{ + FormatList::const_iterator cit = + find_if(formatlist.begin(), formatlist.end(), + lyx::compare_memfun(&Format::name, name)); + if (cit != formatlist.end()) + return cit - formatlist.begin(); + else + return -1; } -bool Formats::View(Buffer * buffer, string const & filename) +void Formats::add(string const & name) +{ + if (!getFormat(name)) + add(name, name, name, string()); +} + + +void Formats::add(string const & name, string const & extension, + string const & prettyname, string const & shortcut) +{ + FormatList::iterator it = + find_if(formatlist.begin(), formatlist.end(), + lyx::compare_memfun(&Format::name, name)); + if (it == formatlist.end()) + formatlist.push_back(Format(name, extension, prettyname, + shortcut, "")); + else { + string viewer = it->viewer(); + *it = Format(name, extension, prettyname, shortcut, viewer); + } +} + + +void Formats::erase(string const & name) +{ + FormatList::iterator it = + find_if(formatlist.begin(), formatlist.end(), + lyx::compare_memfun(&Format::name, name)); + if (it != formatlist.end()) + formatlist.erase(it); +} + + +void Formats::sort() +{ + std::sort(formatlist.begin(), formatlist.end()); +} + + +void Formats::setViewer(string const & name, string const & command) +{ + add(name); + FormatList::iterator it = + find_if(formatlist.begin(), formatlist.end(), + lyx::compare_memfun(&Format::name, name)); + if (it != formatlist.end()) + it->setViewer(command); +} + + +bool Formats::view(Buffer const * buffer, string const & filename, + string const & format_name) const { if (filename.empty()) return false; - string extension = GetExtension(filename); - Format * format = GetFormat(extension); - if (!format || format->viewer.empty()) { - WriteAlert(_("Can not view file"), + Format const * format = getFormat(format_name); + if (format && format->viewer().empty() && + format->isChildFormat()) + format = getFormat(format->parentFormat()); + if (!format || format->viewer().empty()) { + Alert::alert(_("Cannot view file"), _("No information for viewing ") - + Formats::PrettyName(extension)); + + prettyName(format_name)); return false; } - string command = format->viewer; + 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); + command += " " + lyxrc.view_dvi_paper_option; + string paper_size = converters.papersize(buffer); + if (paper_size == "letter") + paper_size = "us"; + command += " " + paper_size; if (buffer->params.orientation == BufferParams::ORIENTATION_LANDSCAPE) - options += 'r'; - command = add_options(command, options); + command += 'r'; } - string command2 = subst(command, "$$FName", OnlyFilename(filename)); - lyxerr << "Executing command: " << command2 << endl; - ShowMessage(buffer, _("Executing command:"), command2); + command += " " + QuoteName(OnlyFilename((filename))); - command = subst(command, "$$FName", filename); - Systemcalls one; - int res = one.startscript(Systemcalls::SystemDontWait, command); + lyxerr[Debug::FILES] << "Executing command: " << command << endl; + ShowMessage(buffer, _("Executing command:"), command); + + Path p(OnlyPath(filename)); + Systemcall one; + int const res = one.startscript(Systemcall::DontWait, command); if (res) { - WriteAlert(_("Can not view file"), + Alert::alert(_("Cannot view file"), _("Error while executing"), command.substr(0, 50)); return false; @@ -141,191 +209,378 @@ bool Formats::View(Buffer * buffer, string const & filename) } -Format * Formats::GetFormat(string const & name) +string const Formats::prettyName(string const & name) const { - map::iterator it = formats.find(name); - if (it != formats.end()) - return &(*it).second; + Format const * format = getFormat(name); + if (format) + return format->prettyname(); else - return 0; + return name; } -string const Formats::PrettyName(string const & name) +string const Formats::extension(string const & name) const { - string format; - Converter::SplitFormat(name, format); - Format * f = GetFormat(format); - if (f) - return f->prettyname; + Format const * format = getFormat(name); + if (format) + return format->extension(); else - return format; + return name; } - ////////////////////////////////////////////////////////////////////////////// -void Converter::Add(string const & from, string const & to, - string const & command, string const & flags) +void Converter::readFlags() { - if (command == "none") - 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") - Com.original_dir = true; + if (flag_name == "latex") + latex = true; + else if (flag_name == "originaldir") + original_dir = true; else if (flag_name == "needaux") - Com.need_aux = true; + need_aux = true; else if (flag_name == "resultdir") - Com.result_dir = (flag_value.empty()) - ? "$$BaseName" : flag_value; + result_dir = (flag_value.empty()) + ? token_base : flag_value; else if (flag_name == "resultfile") - Com.result_file = flag_value; + result_file = flag_value; + else if (flag_name == "parselog") + parselog = flag_value; } - if (!Com.result_dir.empty() && Com.result_file.empty()) - Com.result_file = "index." + to; - - for (vector::iterator it = commands.begin(); - it != commands.end(); ++it) - if ((*it).from == from && (*it).to == to) { - *it = Com; - return; - } - commands.push_back(Com); - Formats::Add(from); - Formats::Add(to); - ++Formats::GetFormat(to)->in_degree; + if (!result_dir.empty() && result_file.empty()) + result_file = "index." + formats.extension(to); + //if (!contains(command, token_from)) + // latex = true; } -vector< pair > const -Converter::GetReachable(string const & from, bool only_viewable) +bool operator<(Converter const & a, Converter const & b) { - vector< pair > result; - Format * format = Formats::GetFormat(from); - if (!format) - return result; + int const i = compare_no_case(a.From->prettyname(), + b.From->prettyname()); + if (i == 0) + return compare_no_case(a.To->prettyname(), b.To->prettyname()) + < 0; + else + return i < 0; +} + +////////////////////////////////////////////////////////////////////////////// - int sort_start = 0; - if (!only_viewable || !format->viewer.empty()) { - result.push_back(pair(from, format->prettyname)); - sort_start = 1; +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; +}; - queue< vector::iterator > Q; - for (vector::iterator it = commands.begin(); - it != commands.end(); ++it) - if ((*it).from == from) { - Q.push(it); - (*it).visited = true; - } else - (*it).visited = false; - - 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 + ")"; + +Converter const * Converters::getConverter(string const & from, + string const & to) +{ + ConverterList::const_iterator cit = + find_if(converterlist_.begin(), converterlist_.end(), + compare_Converter(from, to)); + if (cit != converterlist_.end()) + return &(*cit); + else + return 0; +} + + +int Converters::getNumber(string const & from, string const & to) +{ + 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; +} + + +void Converters::add(string const & from, string const & to, + string const & command, string const & flags) +{ + 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(); + + 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 == converterlist_.end()) { + converterlist_.push_back(converter); + } else { + converter.From = it->From; + converter.To = it->To; + *it = converter; + } +} + + +void Converters::erase(string const & from, string const & to) +{ + ConverterList::iterator it = find_if(converterlist_.begin(), + converterlist_.end(), + compare_Converter(from, to)); + if (it != converterlist_.end()) + converterlist_.erase(it); +} + + +// 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) +{ + 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); + } +} + + +// 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) +{ + if (converterlist_.begin() != converterlist_.end()) { + ConverterList::iterator it = converterlist_.end() - 1; + it->From = formats.getFormat(it->from); + it->To = formats.getFormat(it->to); + } +} + + +void Converters::sort() +{ + std::sort(converterlist_.begin(), converterlist_.end()); +} + + +int Converters::bfs_init(string const & start, bool clear_visited) +{ + int const s = formats.getNumber(start); + if (s < 0) + return s; + + Q_ = queue(); + if (clear_visited) + fill(visited_.begin(), visited_.end(), false); + if (visited_[s] == false) { + Q_.push(s); + visited_[s] = true; + } + return s; +} + + +vector const +Converters::getReachableTo(string const & target, bool clear_visited) +{ + vector result; + int const s = bfs_init(target, clear_visited); + if (s < 0) + return result; + + while (!Q_.empty()) { + int const i = Q_.front(); + Q_.pop(); + if (i != s || target != "lyx") { + result.push_back(&formats.get(i)); } - if (!only_viewable || !format->viewer.empty()) - result.push_back(pair(name, prettyname)); - Q.pop(); - for (vector::iterator it2 = commands.begin(); - it2 != commands.end(); ++it2) - if (!(*it2).visited && (*it).to == (*it2).from) { - Q.push(it2); - (*it2).visited = true; + + vector::iterator it = vertices_[i].in_vertices.begin(); + vector::iterator end = vertices_[i].in_vertices.end(); + for (; it != end; ++it) { + if (!visited_[*it]) { + visited_[*it] = true; + Q_.push(*it); } + } } - 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) +vector const +Converters::getReachable(string const & from, bool only_viewable, + bool clear_visited) { - if (view_file) - *view_file = to_file; + vector result; - 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()); - else - return true; + if (bfs_init(from, clear_visited) < 0) + return result; + + while (!Q_.empty()) { + int const i = Q_.front(); + Q_.pop(); + Format const & format = formats.get(i); + if (format.name() == "lyx") + continue; + if (!only_viewable || !format.viewer().empty() || + format.isChildFormat()) + result.push_back(&format); + + vector::const_iterator cit = + vertices_[i].out_vertices.begin(); + vector::const_iterator end = + vertices_[i].out_vertices.end(); + for (; cit != end; ++cit) + if (!visited_[*cit]) { + visited_[*cit] = true; + Q_.push(*cit); + } + } + + return result; +} - queue< vector::iterator > Q; - for (vector::iterator it = commands.begin(); - it != commands.end(); ++it) - if ((*it).from == 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); + +bool Converters::isReachable(string const & from, string const & to) +{ + if (from == to) + return true; + + int const s = bfs_init(from); + int const t = formats.getNumber(to); + if (s < 0 || t < 0) return false; + + while (!Q_.empty()) { + int const i = Q_.front(); + Q_.pop(); + if (i == t) + return true; + + vector::const_iterator cit = + vertices_[i].out_vertices.begin(); + vector::const_iterator end = + vertices_[i].out_vertices.end(); + for (; cit != end; ++cit) { + if (!visited_[*cit]) { + visited_[*cit] = true; + Q_.push(*cit); + } + } } + return false; +} + + +Converters::EdgePath const +Converters::getPath(string const & from, string const & to) +{ + EdgePath path; + if (from == to) + return path; + + int const s = bfs_init(from); + int t = formats.getNumber(to); + if (s < 0 || t < 0) + return path; + + vector prev_edge(formats.size()); + vector prev_vertex(formats.size()); + bool found = false; - vector::iterator it; - while (!Q.empty()) { - it = Q.front(); - if ((*it).to == to_format && - (using_format.empty() || using_format == (*it).from)) { + while (!Q_.empty()) { + int const i = Q_.front(); + Q_.pop(); + if (i == t) { found = true; break; } - Q.pop(); - for (vector::iterator it2 = commands.begin(); - it2 != commands.end(); ++it2) - if (!(*it2).visited && (*it).to == (*it2).from) { - Q.push(it2); - (*it2).visited = true; - (*it2).previous = it; + + vector::const_iterator beg = + vertices_[i].out_vertices.begin(); + vector::const_iterator cit = beg; + vector::const_iterator end = + vertices_[i].out_vertices.end(); + for (; cit != end; ++cit) + if (!visited_[*cit]) { + int const j = *cit; + visited_[j] = true; + Q_.push(j); + int const k = cit - beg; + prev_edge[j] = vertices_[i].out_edges[k]; + prev_vertex[j] = i; } } + if (!found) + return path; - if (!found) { - WriteAlert(_("Can not convert file"), - _("No information for converting from ") - + Formats::PrettyName(from_format) + _(" to ") - + Formats::PrettyName(to_format)); - return false; + while (t != s) { + path.push_back(prev_edge[t]); + t = prev_vertex[t]; + } + reverse(path.begin(), path.end()); + return path; +} + + +bool Converters::usePdflatex(EdgePath const & path) +{ + for (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 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)); + + if (from_format == to_format) + return move(from_file, to_file, false); - vector< vector::iterator > S; - while (it != commands.end()) { - S.push_back(it); - it = (*it).previous; + EdgePath edgepath = getPath(from_format, to_format); + if (edgepath.empty()) { + Alert::alert(_("Cannot convert file"), + _("No information for converting from ") + + formats.prettyName(from_format) + _(" to ") + + formats.prettyName(to_format)); + return false; } string path = OnlyPath(from_file); @@ -336,139 +591,290 @@ bool Converter::Convert(Buffer * buffer, string const & from_file, 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; - lyxerr << "Converting from " - << (*it).from << " to " << (*it).to << endl; + for (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[Debug::FILES] << "Converting from " + << conv.from << " to " << conv.to << endl; infile = outfile; - outfile = (*it).result_dir.empty() - ? ChangeExtension(from_file, (*it).to) - : 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"; - 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 (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)) 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_); } - 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", infile2); - command = subst(command, "$$BaseName", from_base); - command = subst(command, "$$OutName", 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)); - if ((*it).from == "dvi" && (*it).to == "ps") + if (!conv.parselog.empty()) + command += " 2> " + QuoteName(infile2 + ".out"); + + if (conv.from == "dvi" && conv.to == "ps") command = add_options(command, dvips_options(buffer)); + else if (conv.from == "dvi" && prefixIs(conv.to, "pdf")) + command = add_options(command, + dvipdfm_options(buffer)); - lyxerr << "Calling " << command << endl; - ShowMessage(buffer, _("Executing command:"), command); - - Systemcalls one; + lyxerr[Debug::FILES] << "Calling " << command << endl; + if (buffer) + ShowMessage(buffer, _("Executing command:"), command); + + Systemcall::Starttype type = (dummy) + ? Systemcall::DontWait : Systemcall::Wait; + Systemcall one; int res; - if ((*it).original_dir) { - Path p(buffer->filepath); - res = one.startscript(Systemcalls::System, command); + if (conv.original_dir && buffer) { + Path p(buffer->filePath()); + res = one.startscript(type, command); } else - res = one.startscript(Systemcalls::System, command); + res = one.startscript(type, command); + + if (!conv.parselog.empty()) { + string const logfile = infile2 + ".log"; + string const command2 = conv.parselog + + " < " + QuoteName(infile2 + ".out") + + " > " + QuoteName(logfile); + one.startscript(Systemcall::Wait, command2); + if (!scanLog(buffer, command, logfile)) + return false; + } + if (res) { - WriteAlert(_("Can not convert file"), - "Error while executing", - command.substr(0, 50)); + if (conv.to == "program") + Alert::alert(_("There were errors during the Build process."), + _("You should try to fix them.")); + else + Alert::alert(_("Cannot 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))); + Converter const & conv = converterlist_[edgepath.back()]; + if (conv.To->dummy()) + return true; + + + 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); - return lyx::rename(from.c_str(), to.c_str()); + string from = subst(conv.result_dir, + token_base, from_base); + string to = subst(conv.result_dir, + token_base, to_base); + if (!lyx::rename(from, to)) { + Alert::alert(_("Error while trying to move directory:"), + from, ("to ") + to); + return false; + } + } + return true; + } else + return move(outfile, to_file, conv.latex); +} + +// 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) +{ + 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 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 moved = (copy) + ? lyx::copy(from2, to2) + : lyx::rename(from2, to2); + if (!moved && no_errors) { + Alert::alert(_("Error while trying to move file:"), + from2, _("to ") + to2); + no_errors = false; + } } + return no_errors; +} - } 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()); - else - return lyx::rename(outfile.c_str(), to_file.c_str()); - return true; +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; + return convert(buffer, from_file, to_file_base, from_format, to_format, + to_file); } -string const Converter::SplitFormat(string const & str, string & format) +void Converters::buildGraph() { - string using_format = split(str, format, ':'); - if (format.empty()) - format = "dvi"; - return using_format; + vertices_ = vector(formats.size()); + visited_.resize(formats.size()); + + for (ConverterList::iterator it = converterlist_.begin(); + it != converterlist_.end(); ++it) { + int const s = formats.getNumber(it->from); + int const t = formats.getNumber(it->to); + vertices_[t].in_vertices.push_back(s); + vertices_[s].out_vertices.push_back(t); + vertices_[s].out_edges.push_back(it - converterlist_.begin()); + } } -bool Converter::runLaTeX(Buffer * buffer, string const & command) +bool Converters::formatIsUsed(string const & format) { - + 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; +} + + +bool Converters::scanLog(Buffer const * buffer, string const & command, + string const & filename) +{ + if (!buffer) + return false; + BufferView * bv = buffer->getUser(); + bool need_redraw = false; + if (bv) { + bv->owner()->prohibitInput(); + // Remove all error insets + need_redraw = bv->removeAutoInsets(); + } + + 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->owner()->allowInput(); + } + + 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, ' '); + Alert::alert(_("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."); + Alert::alert(_("Resulting file is empty"), s, t); + return false; + } + return true; +} - if (!bv->text) return 0; - ProhibitInput(bv); +bool Converters::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) { + bv->owner()->prohibitInput(); + bv->owner()->message(_("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); + LaTeX latex(command, name, buffer->filePath()); int result = latex.run(terr, - bv->owner()->getMiniBuffer()); // running latex + bv ? bv->owner()->getLyXFunc() : 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(); + } + } // check return value from latex.run(). if ((result & LaTeX::NO_LOGFILE)) { - WriteAlert(_("LaTeX did not work!"), + Alert::alert(_("LaTeX did not work!"), _("Missing log file:"), name); } else if ((result & LaTeX::ERRORS)) { int num_errors = latex.getNumErrors(); @@ -482,17 +888,28 @@ bool Converter::runLaTeX(Buffer * buffer, string const & command) s += _(" errors detected."); t = _("You should try to fix them."); } - WriteAlert(_("There were errors during the LaTeX run."), + Alert::alert(_("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."); + Alert::alert(_("Resulting file is empty"), s, t); } - AllowInput(bv); + + if (bv) + bv->owner()->allowInput(); - 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; } -string const Converter::dvi_papersize(Buffer const * buffer) +string const Converters::papersize(Buffer const * buffer) { char real_papersize = buffer->params.papersize; if (real_papersize == BufferParams::PAPER_DEFAULT) @@ -513,14 +930,17 @@ string const Converter::dvi_papersize(Buffer const * buffer) return "legal"; case BufferParams::PAPER_USLETTER: default: - return "us"; + return "letter"; } } -string const Converter::dvips_options(Buffer const * buffer) +string const Converters::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() @@ -531,9 +951,7 @@ string const Converter::dvips_options(Buffer const * buffer) result += ' ' + buffer->params.paperwidth; result += ',' + buffer->params.paperheight; } else { - string paper_option = dvi_papersize(buffer); - if (paper_option == "us") - paper_option = "letter"; + string const paper_option = papersize(buffer); if (paper_option != "letter" || buffer->params.orientation != BufferParams::ORIENTATION_LANDSCAPE) { // dvips won't accept -t letter -t landscape. In all other @@ -542,7 +960,39 @@ string const Converter::dvips_options(Buffer const * buffer) result += ' ' + paper_option; } } - if (buffer->params.orientation == BufferParams::ORIENTATION_LANDSCAPE) + if (buffer->params.orientation == BufferParams::ORIENTATION_LANDSCAPE && + buffer->params.papersize2 != BufferParams::VM_PAPER_CUSTOM) result += ' ' + lyxrc.print_landscape_flag; return result; } + + +string const Converters::dvipdfm_options(Buffer const * buffer) +{ + string result; + if (!buffer) + return result; + + if (buffer->params.papersize2 != BufferParams::VM_PAPER_CUSTOM) { + string const paper_size = papersize(buffer); + if (paper_size != "b5" && paper_size != "foolscap") + result = "-p "+ paper_size; + + if (buffer->params.orientation == BufferParams::ORIENTATION_LANDSCAPE) + result += " -l"; + } + + return result; +} + + +vector Converters::vertices_; + + +/// The global instance +Formats formats; +Converters converters; + +// The global copy after reading lyxrc.defaults +Formats system_formats; +Converters system_converters;