1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
14 #pragma implementation
22 #include "converter.h"
24 #include "support/syscall.h"
25 #include "support/path.h"
29 #include "bufferview_funcs.h"
32 #include "minibuffer.h"
33 #include "lyx_gui_misc.h"
40 extern void ShowMessage(Buffer * buf,
42 string const & msg2 = string(),
43 string const & msg3 = string(), int delay = 6);
45 //////////////////////////////////////////////////////////////////////////////
47 map<string, Format> Formats::formats;
48 vector<Command> Converter::commands;
50 //////////////////////////////////////////////////////////////////////////////
52 Format::Format(string const & n) : name(n), in_degree(0)
56 char const * prettyname;
61 { "ps", "PostScript" },
69 for (int i = 0; items[i].name != 0; ++i)
70 if (items[i].name == n) {
71 prettyname = items[i].prettyname;
76 void Formats::Add(string const & name)
78 if (formats.find(name) == formats.end())
79 formats[name] = Format(name);
82 void Formats::SetViewer(string const & name, string const & command)
85 Format * f = GetFormat(name);
86 if (!f->viewer.empty())
87 lyxerr << "Error: a viewer for " << name
88 << " is already defined!" << endl;
94 bool Formats::View(string const & filename)
96 string extension = GetExtension(filename);
97 Format * format = GetFormat(extension);
98 if (!format || format->viewer.empty()) {
99 WriteAlert(_("Can not view file"),
100 _("No information for viewing ")
101 + Formats::PrettyName(extension));
105 string command = format->viewer;
106 command = subst(command, "$$FName", filename);
110 // OS/2 cmd.exe has another use for '&'
111 // This is not NLS safe, but it's OK, I think.
112 string sh = OnlyFilename(GetEnvPath("EMXSHELL"));
114 // COMSPEC is set, unless user unsets
115 sh = OnlyFilename(GetEnvPath("COMSPEC"));
120 if (contains(sh, "cmd.exe")
121 || contains(sh, "4os2.exe"))
122 command = "start /min/n " + command;
126 lyxerr << "Executing command: " << command << endl;
127 //ShowMessage(buffer, _("Executing command:"), command);
129 int res = one.startscript(Systemcalls::System, command);
132 WriteAlert(_("Can not view file"),
133 _("Error while executing"),
134 command.substr(0, 50));
141 Format * Formats::GetFormat(string const & name)
143 map<string, Format>::iterator it = formats.find(name);
144 if (it != formats.end())
145 return &(*it).second;
150 string Formats::PrettyName(string const & name)
154 Converter::SplitFormat(name, format);
155 Format * f = GetFormat(format);
157 return f->prettyname;
162 //////////////////////////////////////////////////////////////////////////////
163 void Converter::Add(string const & from, string const & to,
164 string const & command, string const & flags)
166 for (vector<Command>::const_iterator cit = commands.begin();
167 cit != commands.end(); ++cit)
168 if ((*cit).from == from && (*cit).to == to) {
169 lyxerr << "Error: Convertor from " << from
171 << " already exists!" << endl;
174 bool original_dir = flags == "origdir";
175 commands.push_back(Command(from, to, command, original_dir));
179 ++Formats::GetFormat(to)->in_degree;
182 vector< pair<string,string> >
183 Converter::GetReachable(string const & from, bool only_viewable)
185 vector< pair<string,string> > result;
186 Format * format = Formats::GetFormat(from);
191 if (!only_viewable || !format->viewer.empty()) {
192 result.push_back(pair<string,string>(from, format->prettyname));
196 queue< vector<Command>::iterator > Q;
197 for (vector<Command>::iterator it = commands.begin();
198 it != commands.end(); ++it)
199 if ((*it).from == from) {
201 (*it).visited = true;
203 (*it).visited = false;
206 vector<Command>::iterator it = Q.front();
207 format = Formats::GetFormat((*it).to);
208 string name = format->name;
209 string prettyname = format->prettyname;
210 if (format->in_degree > 1) {
211 name += ":" + (*it).from;
213 split((*it).command, tmp, ' ');
214 prettyname += _("(using ") + tmp + ")";
216 if (!only_viewable || !format->viewer.empty())
217 result.push_back(pair<string,string>(name, prettyname));
219 for (vector<Command>::iterator it2 = commands.begin();
220 it2 != commands.end(); ++it2)
221 if (!(*it2).visited && (*it).to == (*it2).from) {
223 (*it2).visited = true;
227 sort(result.begin() + sort_start, result.end());
232 bool Converter::convert(Buffer * buffer, string const & from_file,
233 string const & to_format)
236 string using_format, format;
237 using_format = SplitFormat(to_format, format);
238 string from_format = GetExtension(from_file);
239 if (from_format == format)
242 queue< vector<Command>::iterator > Q;
243 for (vector<Command>::iterator it = commands.begin();
244 it != commands.end(); ++it)
245 if ((*it).from == from_format) {
247 (*it).visited = true;
248 (*it).previous = commands.end();
250 (*it).visited = false;
253 WriteAlert(_("Can not convert file"),
254 ("Unknown format ") + from_format);
259 vector<Command>::iterator it;
262 if ((*it).to == format &&
263 (using_format.empty() || using_format == (*it).from)) {
268 for (vector<Command>::iterator it2 = commands.begin();
269 it2 != commands.end(); ++it2)
270 if (!(*it2).visited && (*it).to == (*it2).from) {
272 (*it2).visited = true;
273 (*it2).previous = it;
278 WriteAlert(_("Can not convert file"),
279 _("No information for converting from ")
280 + Formats::PrettyName(from_format) + _(" to ")
281 + Formats::PrettyName(to_format));
285 stack< vector<Command>::iterator > S;
286 while (it != commands.end()) {
291 //Path p(OnlyPath(buffer->fileName()));
292 Path p(OnlyPath(from_file));
294 string basename = ChangeExtension(from_file, "");
298 lyxerr << "Converting from "
299 << (*it).from << " to " << (*it).to << endl;
301 if ((*it).from == "tex" &&
302 ( (*it).to == "dvi" || (*it).to == "pdf") ) {
303 lyxrc.pdf_mode = (*it).to == "pdf";
304 if (!runLaTeX(buffer, (*it).command))
307 string infile = ChangeExtension(from_file, (*it).from);
308 if (!(*it).original_dir)
309 infile = OnlyFilename(infile);
310 string outfile = ChangeExtension(infile, (*it).to);
312 string command = (*it).command;
313 command = subst(command, "$$FName", infile);
314 command = subst(command, "$$BaseName", basename);
315 command = subst(command, "$$OutName", outfile);
316 lyxerr << "Calling " << command << endl;
317 ShowMessage(buffer, _("Executing command:"), command);
321 if ((*it).original_dir) {
322 Path p(buffer->filepath);
323 res = one.startscript(Systemcalls::System, command);
325 res = one.startscript(Systemcalls::System, command);
327 WriteAlert(_("Can not convert file"),
328 "Error while executing",
329 command.substr(0, 50));
339 string Converter::SplitFormat(string const & str, string & format)
341 string using_format = split(str, format, ':');
347 bool Converter::runLaTeX(Buffer * buffer, string const & command)
350 BufferView * bv = buffer->getUser();
352 if (!bv->text) return 0;
356 string name = buffer->getLatexName();
358 bv->owner()->getMiniBuffer()->Set(_("Running LaTeX..."));
360 // Remove all error insets
361 bool a = bv->removeAutoInsets();
363 // do the LaTex run(s)
365 LaTeX latex(command, name, buffer->filepath);
366 int result = latex.run(terr,
367 bv->owner()->getMiniBuffer()); // running latex
369 if ((result & LaTeX::ERRORS)) {
370 // Insert all errors as errors boxes
371 bv->insertErrors(terr);
374 // if we removed error insets before we ran LaTeX or if we inserted
375 // error insets after we ran LaTeX this must be run:
376 if (a || (result & LaTeX::ERRORS)){
379 //bv->updateScrollbar();
382 // check return value from latex.run().
383 if ((result & LaTeX::NO_LOGFILE)) {
384 WriteAlert(_("LaTeX did not work!"),
385 _("Missing log file:"), name);
386 } else if ((result & LaTeX::ERRORS)) {
387 int num_errors = latex.getNumErrors();
390 if (num_errors == 1) {
391 s = _("One error detected");
392 t = _("You should try to fix it.");
394 s = tostr(num_errors);
395 s += _(" errors detected.");
396 t = _("You should try to fix them.");
398 WriteAlert(_("There were errors during the LaTeX run."),
403 return (result & (LaTeX::NO_LOGFILE | LaTeX::ERRORS)) == 0;