]> git.lyx.org Git - lyx.git/blob - src/converter.C
90babcaa0d66945604b5ea664c2782c8e9e956f1
[lyx.git] / src / converter.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *        
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include <cctype>
18
19 #include "converter.h"
20 #include "lyxrc.h"
21 #include "support/syscall.h"
22 #include "support/path.h"
23 #include "support/filetools.h"
24 #include "buffer.h"
25 #include "bufferview_funcs.h"
26 #include "LaTeX.h"
27 #include "LyXView.h"
28 #include "minibuffer.h"
29 #include "lyx_gui_misc.h"
30 #include "lyx_cb.h" // ShowMessage()
31 #include "support/lyxfunctional.h"
32
33 using std::vector;
34 using std::queue;
35 using std::endl;
36 using std::fill;
37 using std::find_if;
38 using std::reverse;
39 using std::sort;
40
41 static string const token_from("$$i");
42 static string const token_base("$$b");
43 static string const token_to("$$o");
44
45 //////////////////////////////////////////////////////////////////////////////
46
47 static inline
48 string const add_options(string const & command, string const & options)
49 {
50         string head;
51         string const tail = split(command, head, ' ');
52         return head + ' ' + options + ' ' + tail;
53 }
54
55 //////////////////////////////////////////////////////////////////////////////
56
57 bool Format::dummy() const
58 {
59         return extension().empty();
60 }
61
62
63 bool Format::IsChildFormat() const
64 {
65         if (name_.empty())
66                 return false;
67         return isdigit(name_[name_.length() - 1]);
68 }
69
70
71 string const Format::ParentFormat() const
72 {
73         return name_.substr(0, name_.length() - 1);
74 }
75
76 //////////////////////////////////////////////////////////////////////////////
77
78 // This method should return a reference, and throw an exception
79 // if the format named name cannot be found (Lgb)
80 Format const * Formats::GetFormat(string const & name) const
81 {
82         FormatList::const_iterator cit =
83                 find_if(formatlist.begin(), formatlist.end(),
84                         compare_memfun(&Format::name, name));
85         if (cit != formatlist.end())
86                 return &(*cit);
87         else
88                 return 0;
89 }
90
91
92 int Formats::GetNumber(string const & name) const
93 {
94         FormatList::const_iterator cit =
95                 find_if(formatlist.begin(), formatlist.end(),
96                         compare_memfun(&Format::name, name));
97         if (cit != formatlist.end())
98                 return cit - formatlist.begin();
99         else
100                 return -1;
101 }
102
103
104 void Formats::Add(string const & name)
105 {
106         if (!GetFormat(name))
107                 Add(name, name, name, string());
108 }
109
110
111 void Formats::Add(string const & name, string const & extension, 
112                   string const & prettyname, string const & shortcut)
113 {
114         FormatList::iterator it = 
115                 find_if(formatlist.begin(), formatlist.end(),
116                         compare_memfun(&Format::name, name));
117         if (it == formatlist.end())
118                 formatlist.push_back(Format(name, extension, prettyname,
119                                             shortcut, ""));
120         else {
121                 string viewer = it->viewer();
122                 *it = Format(name, extension, prettyname, shortcut, viewer);
123         }
124 }
125
126
127 void Formats::Delete(string const & name)
128 {
129         FormatList::iterator it = 
130                 find_if(formatlist.begin(), formatlist.end(),
131                         compare_memfun(&Format::name, name));
132         if (it != formatlist.end())
133                 formatlist.erase(it);
134 }
135
136
137 void Formats::Sort()
138 {
139         sort(formatlist.begin(), formatlist.end());
140 }
141
142
143 void Formats::SetViewer(string const & name, string const & command)
144 {
145         Add(name);
146         FormatList::iterator it =
147                 find_if(formatlist.begin(), formatlist.end(),
148                         compare_memfun(&Format::name, name));
149         if (it != formatlist.end())
150                 it->setViewer(command);
151 }
152
153
154 bool Formats::View(Buffer const * buffer, string const & filename,
155                    string const & format_name) const
156 {
157         if (filename.empty())
158                 return false;
159
160         Format const * format = GetFormat(format_name);
161         if (format && format->viewer().empty() &&
162             format->IsChildFormat())
163                 format = GetFormat(format->ParentFormat());
164         if (!format || format->viewer().empty()) {
165                 WriteAlert(_("Can not view file"),
166                            _("No information for viewing ")
167                            + PrettyName(format_name));
168                            return false;
169         }
170
171         string command = format->viewer();
172
173         if (format_name == "dvi" &&
174             !lyxrc.view_dvi_paper_option.empty()) {
175                 command += " " + lyxrc.view_dvi_paper_option;
176                 command += " " + converters.dvi_papersize(buffer);
177                 if (buffer->params.orientation 
178                     == BufferParams::ORIENTATION_LANDSCAPE)
179                         command += 'r';
180         }
181
182         string command2 = command + " " + OnlyFilename(filename);
183         lyxerr << "Executing command: " << command2 << endl;
184         ShowMessage(buffer, _("Executing command:"), command2);
185
186         command += " " + QuoteName(filename);
187         Systemcalls one;
188         int res = one.startscript(Systemcalls::SystemDontWait, command);
189
190         if (res) {
191                 WriteAlert(_("Can not view file"),
192                            _("Error while executing"),
193                            command2.substr(0, 50));
194                 return false;
195         }
196         return true;
197 }
198
199
200 string const Formats::PrettyName(string const & name) const
201 {
202         Format const * format = GetFormat(name);
203         if (format)
204                 return format->prettyname();
205         else
206                 return name;
207 }
208
209
210 string const Formats::Extension(string const & name) const
211 {
212         Format const * format = GetFormat(name);
213         if (format)
214                 return format->extension();
215         else
216                 return name;
217 }
218
219 //////////////////////////////////////////////////////////////////////////////
220
221 void Converter::ReadFlags()
222 {
223         string flag_list(flags);
224         while (!flag_list.empty()) {
225                 string flag_name, flag_value;
226                 flag_list = split(flag_list, flag_value, ',');
227                 flag_value = split(flag_value, flag_name, '=');
228                 if (flag_name == "latex")
229                         latex = true;
230                 else if (flag_name == "originaldir")
231                         original_dir = true;
232                 else if (flag_name == "needaux")
233                         need_aux = true;
234                 else if (flag_name == "resultdir")
235                         result_dir = (flag_value.empty())
236                                 ? token_base : flag_value;
237                 else if (flag_name == "resultfile")
238                         result_file = flag_value;
239                 else if (flag_name == "parselog")
240                         parselog = flag_value;
241         }
242         if (!result_dir.empty() && result_file.empty())
243                 result_file = "index." + formats.Extension(to);
244         //if (!contains(command, token_from))
245         //      latex = true;
246 }
247
248
249 bool operator<(Converter const & a, Converter const & b)
250 {
251         int i = compare_no_case(a.From->prettyname(), b.From->prettyname());
252         if (i == 0)
253                 return compare_no_case(a.To->prettyname(), b.To->prettyname())
254                         < 0;
255         else
256                 return i < 0;
257 }
258
259 //////////////////////////////////////////////////////////////////////////////
260
261 class compare_Converter {
262 public:
263         compare_Converter(string const & f, string const & t)
264                 : from(f), to(t) {}
265         bool operator()(Converter const & c) {
266                 return c.from == from && c.to == to;
267         }
268 private:
269         string from;
270         string to;
271 };
272
273
274 Converter const * Converters::GetConverter(string const & from,
275                                             string const & to)
276 {
277         ConverterList::const_iterator cit =
278                 find_if(converterlist.begin(), converterlist.end(),
279                         compare_Converter(from, to));
280         if (cit != converterlist.end())
281                 return &(*cit);
282         else
283                 return 0;
284 }
285
286
287 int Converters::GetNumber(string const & from, string const & to)
288 {
289         ConverterList::const_iterator cit =
290                 find_if(converterlist.begin(), converterlist.end(),
291                         compare_Converter(from, to));
292         if (cit != converterlist.end())
293                 return cit - converterlist.begin();
294         else
295                 return -1;
296 }
297
298
299 void Converters::Add(string const & from, string const & to,
300                      string const & command, string const & flags)
301 {
302         formats.Add(from);
303         formats.Add(to);
304         ConverterList::iterator it = find_if(converterlist.begin(),
305                                              converterlist.end(),
306                                              compare_Converter(from, to));
307
308         Converter converter(from, to, command, flags);
309         if (it != converterlist.end() && !flags.empty() && flags[0] == '*') {
310                 converter = *it;
311                 converter.command = command;
312                 converter.flags = flags;
313         }
314         converter.ReadFlags();
315         
316         if (converter.latex && (latex_command.empty() || to == "dvi"))
317                 latex_command = command;
318         // If we have both latex & pdflatex, we set latex_command to latex.
319         // The latex_command is used to update the .aux file when running
320         // a converter that uses it.
321
322         if (it == converterlist.end())
323                 converterlist.push_back(converter);
324         else {
325                 converter.From = it->From;
326                 converter.To = it->To;
327                 *it = converter;
328         }
329 }
330
331
332 void Converters::Delete(string const & from, string const & to)
333 {
334         ConverterList::iterator it = find_if(converterlist.begin(),
335                                              converterlist.end(),
336                                              compare_Converter(from, to));
337         if (it != converterlist.end())
338                 converterlist.erase(it);
339 }
340
341
342 // This method updates the pointers From and To in all the converters.
343 // The code is not very efficient, but it doesn't matter as the number
344 // of formats and converters is small.
345 // Furthermore, this method is called only on startup, or after 
346 // adding/deleting a format in FormPreferences (the latter calls can be
347 // eliminated if the formats in the Formats class are stored using a map or
348 // a list (instead of a vector), but this will cause other problems). 
349 void Converters::Update(Formats const & formats)
350 {
351         for (ConverterList::iterator it = converterlist.begin();
352              it != converterlist.end(); ++it) {
353                 it->From = formats.GetFormat(it->from);
354                 it->To = formats.GetFormat(it->to);
355         }
356 }
357
358
359 // This method updates the pointers From and To in the last converter.
360 // It is called when adding a new converter in FormPreferences
361 void Converters::UpdateLast(Formats const & formats)
362 {
363         if (converterlist.begin() != converterlist.end()) {
364                 ConverterList::iterator it = converterlist.end()-1;
365                 it->From = formats.GetFormat(it->from);
366                 it->To = formats.GetFormat(it->to);
367         }
368 }
369
370
371 void Converters::Sort()
372 {
373         sort(converterlist.begin(), converterlist.end());
374 }
375
376
377 int Converters::BFS_init(string const & start, bool clear_visited)
378 {
379         int s = formats.GetNumber(start);
380         if (s < 0)
381                 return s;
382
383         Q = queue<int>();
384         if (clear_visited)
385                 fill(visited.begin(), visited.end(), false);
386         if (visited[s] == false) {
387                 Q.push(s);
388                 visited[s] = true;
389         }
390         return s;
391 }
392
393
394 vector<Format const *> const
395 Converters::GetReachableTo(string const & target, bool clear_visited)
396 {
397         vector<Format const *> result;
398         int s = BFS_init(target, clear_visited);
399         if (s < 0)
400                 return result;
401
402         while (!Q.empty()) {
403                 int i = Q.front();
404                 Q.pop();
405                 if (i != s || target != "lyx")
406                         result.push_back(&formats.Get(i));
407                 for (vector<int>::iterator it = vertices[i].in_vertices.begin();
408                      it != vertices[i].in_vertices.end(); ++it)
409                         if (!visited[*it]) {
410                                 visited[*it] = true;
411                                 Q.push(*it);
412                         }
413         }
414
415         return result;
416 }
417
418
419 vector<Format const *> const
420 Converters::GetReachable(string const & from, bool only_viewable,
421                          bool clear_visited)
422 {
423         vector<Format const *> result;
424
425         if (BFS_init(from, clear_visited) < 0)
426                 return result;
427
428         while (!Q.empty()) {
429                 int i = Q.front();
430                 Q.pop();
431                 Format const & format = formats.Get(i);
432                 if (format.name() == "lyx")
433                         continue;
434                 if (!only_viewable || !format.viewer().empty() ||
435                     format.IsChildFormat())
436                         result.push_back(&format);
437                 for (vector<int>::iterator it = vertices[i].out_vertices.begin();
438                      it != vertices[i].out_vertices.end(); ++it)
439                         if (!visited[*it]) {
440                                 visited[*it] = true;
441                                 Q.push(*it);
442                         }
443         }
444
445         return result;
446 }
447
448
449 bool Converters::IsReachable(string const & from, string const & to)
450 {
451         if (from == to)
452                 return true;
453
454         int s = BFS_init(from);
455         int t = formats.GetNumber(to);
456         if (s < 0 || t < 0)
457                 return false;
458
459         while (!Q.empty()) {
460                 int i = Q.front();
461                 Q.pop();
462                 if (i == t)
463                         return true;
464                 for (vector<int>::iterator it = vertices[i].out_vertices.begin();
465                      it != vertices[i].out_vertices.end(); ++it)
466                         if (!visited[*it]) {
467                                 visited[*it] = true;
468                                 Q.push(*it);
469                         }
470         }
471
472         return false;
473 }
474
475
476 Converters::EdgePath const
477 Converters::GetPath(string const & from, string const & to)
478 {
479         EdgePath path;
480         if (from == to)
481                 return path;
482
483         int s = BFS_init(from);
484         int t = formats.GetNumber(to);
485         if (s < 0 || t < 0)
486                 return path;
487
488         vector<int> prev_edge(formats.size());
489         vector<int> prev_vertex(formats.size());
490
491         bool found = false;
492         while (!Q.empty()) {
493                 int i = Q.front();
494                 Q.pop();
495                 if (i == t) {
496                         found = true;
497                         break;
498                 }
499                 for (vector<int>::iterator it = vertices[i].out_vertices.begin();
500                      it != vertices[i].out_vertices.end(); ++it)
501                         if (!visited[*it]) {
502                                 int j = *it;
503                                 visited[j] = true;
504                                 Q.push(j);
505                                 int k = it - vertices[i].out_vertices.begin();
506                                 prev_edge[j] = vertices[i].out_edges[k];
507                                 prev_vertex[j] = i;
508                         }
509         }
510         if (!found)
511                 return path;
512
513         while (t != s) {
514                 path.push_back(prev_edge[t]);
515                 t = prev_vertex[t];
516         }
517         reverse(path.begin(), path.end());
518         return path;
519 }
520
521
522 bool Converters::UsePdflatex(EdgePath const & path)
523 {
524         for (EdgePath::const_iterator cit = path.begin();
525              cit != path.end(); ++cit) {
526                 Converter const & conv = converterlist[*cit];
527                 if (conv.latex)
528                         return contains(conv.to, "pdf");
529         }
530         return false;
531 }
532
533
534 bool Converters::Convert(Buffer const * buffer,
535                          string const & from_file, string const & to_file_base,
536                          string const & from_format, string const & to_format,
537                          string & to_file)
538 {
539         to_file = ChangeExtension(to_file_base,
540                                   formats.Extension(to_format));
541
542         if (from_format == to_format)
543                 if (from_file != to_file)
544                         return lyx::rename(from_file, to_file);
545                 else
546                         return true;
547
548         EdgePath edgepath = GetPath(from_format, to_format);
549         if (edgepath.empty()) {
550                 WriteAlert(_("Can not convert file"),
551                            _("No information for converting from ")
552                            + formats.PrettyName(from_format) + _(" to ")
553                            + formats.PrettyName(to_format));
554                 return false;
555         }
556
557         string path = OnlyPath(from_file);
558         Path p(path);
559
560         bool run_latex = false;
561         string from_base = ChangeExtension(from_file, "");
562         string to_base = ChangeExtension(to_file, "");
563         string infile;
564         string outfile = from_file;
565         for (EdgePath::const_iterator cit = edgepath.begin();
566              cit != edgepath.end(); ++cit) {
567                 Converter const & conv = converterlist[*cit];
568                 bool dummy = conv.To->dummy() && conv.to != "program";
569                 if (!dummy)
570                         lyxerr << "Converting from  "
571                                << conv.from << " to " << conv.to << endl;
572                 infile = outfile;
573                 outfile = conv.result_dir.empty()
574                         ? ChangeExtension(from_file, conv.To->extension())
575                         : AddName(subst(conv.result_dir,
576                                         token_base, from_base),
577                                   subst(conv.result_file,
578                                         token_base, OnlyFilename(from_base)));
579
580                 if (conv.latex) {
581                         run_latex = true;
582                         string command = subst(conv.command, token_from, "");
583                         lyxerr << "Running " << command << endl;
584                         if (!runLaTeX(buffer, command))
585                                 return false;
586                 } else {
587                         if (conv.need_aux && !run_latex
588                             && !latex_command.empty()) {
589                                 lyxerr << "Running " << latex_command 
590                                        << " to update aux file"<<  endl;
591                                 runLaTeX(buffer, latex_command);
592                         }
593
594                         string infile2 = (conv.original_dir)
595                                 ? infile : MakeRelPath(infile, path);
596                         string outfile2 = (conv.original_dir)
597                                 ? outfile : MakeRelPath(outfile, path);
598
599                         string command = conv.command;
600                         command = subst(command, token_from, QuoteName(infile2));
601                         command = subst(command, token_base, QuoteName(from_base));
602                         command = subst(command, token_to, QuoteName(outfile2));
603
604                         if (!conv.parselog.empty())
605                                 command += " 2> " + QuoteName(infile2 + ".out");
606
607                         if (conv.from == "dvi" && conv.to == "ps")
608                                 command = add_options(command,
609                                                       dvips_options(buffer));
610
611                         lyxerr << "Calling " << command << endl;
612                         if (buffer)
613                                 ShowMessage(buffer, _("Executing command:"), command);
614
615                         Systemcalls::Starttype type = (dummy)
616                                 ? Systemcalls::SystemDontWait : Systemcalls::System;
617                         Systemcalls one;
618                         int res;
619                         if (conv.original_dir && buffer) {
620                                 Path p(buffer->filepath);
621                                 res = one.startscript(type, command);
622                         } else
623                                 res = one.startscript(type, command);
624
625                         if (!conv.parselog.empty()) {
626                                 string const logfile =  infile2 + ".log";
627                                 string const command2 = conv.parselog +
628                                         " < " + QuoteName(infile2 + ".out") +
629                                         " > " + QuoteName(logfile);
630                                 one.startscript(Systemcalls::System, command2);
631                                 if (!scanLog(buffer, command, logfile))
632                                         return false;
633                         }
634
635                         if (res) {
636                                 if (conv.to == "program")
637                                         WriteAlert(_("There were errors during the Build process."),
638                                                    _("You should try to fix them."));
639                                 else
640                                         WriteAlert(_("Can not convert file"),
641                                                    "Error while executing",
642                                                    command.substr(0, 50));
643                                 return false;
644                         }
645                 }
646         }
647
648         Converter const & conv = converterlist[edgepath.back()];
649         if (conv.To->dummy())
650                 return true;
651
652
653         if (!conv.result_dir.empty()) {
654                 to_file = AddName(subst(conv.result_dir, token_base, to_base),
655                                   subst(conv.result_file,
656                                         token_base, OnlyFilename(to_base)));
657                 if (from_base != to_base) {
658                         string from = subst(conv.result_dir,
659                                             token_base, from_base);
660                         string to = subst(conv.result_dir,
661                                           token_base, to_base);
662                         if (!lyx::rename(from, to)) {
663                                 WriteAlert(_("Error while trying to move directory:"),
664                                            from, ("to ") + to);
665                                 return false;
666                         }
667                 }
668         } else if (outfile != to_file) {
669                 bool moved = (conv.latex)
670                         ? lyx::copy(outfile, to_file)
671                         : lyx::rename(outfile, to_file);
672                 if (!moved) {
673                         WriteAlert(_("Error while trying to move file:"),
674                                    outfile, _("to ") + to_file);
675                         return false;
676                 }
677         }
678
679         return true;
680 }
681
682
683 bool Converters::Convert(Buffer const * buffer,
684                         string const & from_file, string const & to_file_base,
685                         string const & from_format, string const & to_format)
686 {
687         string to_file;
688         return Convert(buffer, from_file, to_file_base, from_format, to_format,
689                        to_file);
690 }
691
692
693 void Converters::BuildGraph()
694 {
695         vertices = vector<Vertex>(formats.size());
696         visited.resize(formats.size());
697
698         for (ConverterList::iterator it = converterlist.begin();
699              it != converterlist.end(); ++it) {
700                 int s = formats.GetNumber(it->from);
701                 int t = formats.GetNumber(it->to);
702                 vertices[t].in_vertices.push_back(s);
703                 vertices[s].out_vertices.push_back(t);
704                 vertices[s].out_edges.push_back(it - converterlist.begin());
705         }
706 }
707
708
709 bool Converters::FormatIsUsed(string const & format)
710 {
711         for (ConverterList::const_iterator cit = converterlist.begin();
712             cit != converterlist.end(); ++cit)
713                 if (cit->from == format || cit->to == format)
714                         return true;
715         return false;
716 }
717
718
719 bool Converters::scanLog(Buffer const * buffer, string const & command,
720                         string const & filename)
721 {
722         if (!buffer)
723                 return false;
724
725         BufferView * bv = buffer->getUser();
726         bool need_redraw = false;
727         if (bv) {
728                 ProhibitInput(bv);
729                 // Remove all error insets
730                 need_redraw = bv->removeAutoInsets();
731         }
732
733         LaTeX latex("", filename, "");
734         TeXErrors terr;
735         int result = latex.scanLogFile(terr);
736         if (bv) {
737                 if ((result & LaTeX::ERRORS)) {
738                         // Insert all errors as errors boxes
739                         bv->insertErrors(terr);
740                         need_redraw = true;
741                 }
742                 if (need_redraw) {
743                         bv->redraw();
744                         bv->fitCursor(bv->text);
745                 }
746                 AllowInput(bv);
747         }
748
749         if ((result & LaTeX::ERRORS)) {
750                 int num_errors = latex.getNumErrors();
751                 string s;
752                 string t;
753                 if (num_errors == 1) {
754                         s = _("One error detected");
755                         t = _("You should try to fix it.");
756                 } else {
757                         s = tostr(num_errors);
758                         s += _(" errors detected.");
759                         t = _("You should try to fix them.");
760                 }
761                 string head;
762                 split(command, head, ' ');
763                 WriteAlert(_("There were errors during running of ") + head,
764                            s, t);
765                 return false;
766         } else if (result & LaTeX::NO_OUTPUT) {
767                 string const s = _("The operation resulted in");
768                 string const t = _("an empty file.");
769                 WriteAlert(_("Resulting file is empty"), s, t);
770                 return false;
771         }
772         return true;
773 }
774
775
776 bool Converters::runLaTeX(Buffer const * buffer, string const & command)
777 {
778         if (!buffer)
779                 return false;
780
781         BufferView * bv = buffer->getUser();
782         string name = buffer->getLatexName();
783         bool need_redraw = false;
784
785         if (bv) {
786                 ProhibitInput(bv);
787                 bv->owner()->getMiniBuffer()->Set(_("Running LaTeX..."));
788                 // Remove all error insets
789                 need_redraw = bv->removeAutoInsets();
790         }
791
792
793         // do the LaTex run(s)
794         TeXErrors terr;
795         LaTeX latex(command, name, buffer->filepath);
796         int result = latex.run(terr,
797                                bv ? bv->owner()->getMiniBuffer() : 0);
798         
799
800         if (bv) {
801                 if ((result & LaTeX::ERRORS)) {
802                         // Insert all errors as errors boxes
803                         bv->insertErrors(terr);
804                         need_redraw = true;
805                 }
806
807                 // if we removed error insets before we ran LaTeX or if we inserted
808                 // error insets after we ran LaTeX this must be run:
809                 if (need_redraw) {
810                         bv->redraw();
811                         bv->fitCursor(bv->text);
812                 }
813         }
814
815         // check return value from latex.run().
816         if ((result & LaTeX::NO_LOGFILE)) {
817                 WriteAlert(_("LaTeX did not work!"),
818                            _("Missing log file:"), name);
819         } else if ((result & LaTeX::ERRORS)) {
820                 int num_errors = latex.getNumErrors();
821                 string s;
822                 string t;
823                 if (num_errors == 1) {
824                         s = _("One error detected");
825                         t = _("You should try to fix it.");
826                 } else {
827                         s = tostr(num_errors);
828                         s += _(" errors detected.");
829                         t = _("You should try to fix them.");
830                 }
831                 WriteAlert(_("There were errors during the LaTeX run."),
832                            s, t);
833         }  else if (result & LaTeX::NO_OUTPUT) {
834                 string const s = _("The operation resulted in");
835                 string const t = _("an empty file.");
836                 WriteAlert(_("Resulting file is empty"), s, t);
837         }
838
839         if (bv)
840                 AllowInput(bv);
841  
842         int const ERROR_MASK = 
843                         LaTeX::NO_LOGFILE |
844                         LaTeX::ERRORS |
845                         LaTeX::NO_OUTPUT;
846         
847         return (result & ERROR_MASK) == 0;
848
849 }
850
851
852 string const Converters::dvi_papersize(Buffer const * buffer)
853 {
854         char real_papersize = buffer->params.papersize;
855         if (real_papersize == BufferParams::PAPER_DEFAULT)
856                 real_papersize = lyxrc.default_papersize;
857
858         switch (real_papersize) {
859         case BufferParams::PAPER_A3PAPER:
860                 return "a3";
861         case BufferParams::PAPER_A4PAPER:
862                 return "a4";
863         case BufferParams::PAPER_A5PAPER:
864                 return "a5";
865         case BufferParams::PAPER_B5PAPER:
866                 return "b5";
867         case BufferParams::PAPER_EXECUTIVEPAPER:
868                 return "foolscap";
869         case BufferParams::PAPER_LEGALPAPER:
870                 return "legal";
871         case BufferParams::PAPER_USLETTER:
872         default:
873                 return "us";
874         }
875 }
876
877
878 string const Converters::dvips_options(Buffer const * buffer)
879 {
880         string result;
881         if (!buffer)
882                 return result;
883
884         if (buffer->params.use_geometry
885             && buffer->params.papersize2 == BufferParams::VM_PAPER_CUSTOM
886             && !lyxrc.print_paper_dimension_flag.empty()
887             && !buffer->params.paperwidth.empty()
888             && !buffer->params.paperheight.empty()) {
889                 // using a custom papersize
890                 result = lyxrc.print_paper_dimension_flag;
891                 result += ' ' + buffer->params.paperwidth;
892                 result += ',' + buffer->params.paperheight;
893         } else {
894                 string paper_option = dvi_papersize(buffer);
895                 if (paper_option == "us")
896                         paper_option = "letter";
897                 if (paper_option != "letter" ||
898                     buffer->params.orientation != BufferParams::ORIENTATION_LANDSCAPE) {
899                         // dvips won't accept -t letter -t landscape.  In all other
900                         // cases, include the paper size explicitly.
901                         result = lyxrc.print_paper_flag;
902                         result += ' ' + paper_option;
903                 }
904         }
905         if (buffer->params.orientation == BufferParams::ORIENTATION_LANDSCAPE)
906                 result += ' ' + lyxrc.print_landscape_flag;
907         return result;
908 }
909
910 vector<Converters::Vertex> Converters::vertices;
911
912
913 /// The global instance
914 Formats formats;
915 Converters converters;
916
917 // The global copy after reading lyxrc.defaults
918 Formats system_formats;
919 Converters system_converters;