]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
Revert accidental commit.
[lyx.git] / src / BufferParams.cpp
1 /**
2  * \file BufferParams.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alfredo Braunstein
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author John Levon
10  * \author André Pönitz
11  * \author Martin Vermeer
12  *
13  * Full author contact details are available in file CREDITS.
14  */
15
16 #include <config.h>
17
18 #include "BufferParams.h"
19
20 #include "Author.h"
21 #include "BranchList.h"
22 #include "buffer_funcs.h"
23 #include "Bullet.h"
24 #include "debug.h"
25 #include "Encoding.h"
26 #include "gettext.h"
27 #include "Language.h"
28 #include "LaTeXFeatures.h"
29 #include "Messages.h"
30 #include "ModuleList.h"
31 #include "Color.h"
32 #include "Font.h"
33 #include "Lexer.h"
34 #include "LyXRC.h"
35 #include "TextClassList.h"
36 #include "OutputParams.h"
37 #include "Spacing.h"
38 #include "TexRow.h"
39 #include "VSpace.h"
40
41 #include "frontends/alert.h"
42 #include "insets/InsetListingsParams.h"
43
44 #include "support/convert.h"
45 #include "support/filetools.h"
46 #include "support/Translator.h"
47
48 #include <boost/array.hpp>
49
50 #include <algorithm>
51 #include <sstream>
52
53 using std::count;
54 using std::endl;
55 using std::string;
56 using std::istringstream;
57 using std::ostream;
58 using std::ostringstream;
59 using std::pair;
60 using std::string;
61 using lyx::support::FileName;
62 using lyx::support::libFileSearch;
63 using lyx::support::bformat;
64 using lyx::support::rtrim;
65 using lyx::support::tokenPos;
66
67
68 static char const * const string_paragraph_separation[] = {
69         "indent", "skip", ""
70 };
71
72
73 static char const * const string_quotes_language[] = {
74         "english", "swedish", "german", "polish", "french", "danish", ""
75 };
76
77
78 static char const * const string_papersize[] = {
79         "default", "custom", "letterpaper", "executivepaper", "legalpaper",
80         "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
81 };
82
83
84 static char const * const string_orientation[] = {
85         "portrait", "landscape", ""
86 };
87
88
89 static char const * const string_footnotekinds[] = {
90         "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
91 };
92
93
94 static char const * const tex_graphics[] = {
95         "default", "dvips", "dvitops", "emtex",
96         "ln", "oztex", "textures", "none", ""
97 };
98
99
100 namespace lyx {
101
102 // Local translators
103 namespace {
104
105 // Paragraph separation
106 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
107
108
109 ParSepTranslator const init_parseptranslator()
110 {
111         ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
112         translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
113         return translator;
114 }
115
116
117 ParSepTranslator const & parseptranslator()
118 {
119         static ParSepTranslator translator = init_parseptranslator();
120         return translator;
121 }
122
123
124 // Quotes language
125 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
126
127
128 QuotesLangTranslator const init_quoteslangtranslator()
129 {
130         QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
131         translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
132         translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
133         translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
134         translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
135         translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
136         return translator;
137 }
138
139
140 QuotesLangTranslator const & quoteslangtranslator()
141 {
142         static QuotesLangTranslator translator = init_quoteslangtranslator();
143         return translator;
144 }
145
146
147 // Paper size
148 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
149
150
151 PaperSizeTranslator const init_papersizetranslator()
152 {
153         PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
154         translator.addPair(string_papersize[1], PAPER_CUSTOM);
155         translator.addPair(string_papersize[2], PAPER_USLETTER);
156         translator.addPair(string_papersize[3], PAPER_USLEGAL);
157         translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
158         translator.addPair(string_papersize[5], PAPER_A3);
159         translator.addPair(string_papersize[6], PAPER_A4);
160         translator.addPair(string_papersize[7], PAPER_A5);
161         translator.addPair(string_papersize[8], PAPER_B3);
162         translator.addPair(string_papersize[9], PAPER_B4);
163         translator.addPair(string_papersize[10], PAPER_B5);
164         return translator;
165 }
166
167
168 PaperSizeTranslator const & papersizetranslator()
169 {
170         static PaperSizeTranslator translator = init_papersizetranslator();
171         return translator;
172 }
173
174
175 // Paper orientation
176 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
177
178
179 PaperOrientationTranslator const init_paperorientationtranslator()
180 {
181         PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
182         translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
183         return translator;
184 }
185
186
187 PaperOrientationTranslator const & paperorientationtranslator()
188 {
189         static PaperOrientationTranslator translator = init_paperorientationtranslator();
190         return translator;
191 }
192
193
194 // Page sides
195 typedef Translator<int, TextClass::PageSides> SidesTranslator;
196
197
198 SidesTranslator const init_sidestranslator()
199 {
200         SidesTranslator translator(1, TextClass::OneSide);
201         translator.addPair(2, TextClass::TwoSides);
202         return translator;
203 }
204
205
206 SidesTranslator const & sidestranslator()
207 {
208         static SidesTranslator translator = init_sidestranslator();
209         return translator;
210 }
211
212
213 // LaTeX packages
214 typedef Translator<int, BufferParams::Package> PackageTranslator;
215
216
217 PackageTranslator const init_packagetranslator()
218 {
219         PackageTranslator translator(0, BufferParams::package_off);
220         translator.addPair(1, BufferParams::package_auto);
221         translator.addPair(2, BufferParams::package_on);
222         return translator;
223 }
224
225
226 PackageTranslator const & packagetranslator()
227 {
228         static PackageTranslator translator = init_packagetranslator();
229         return translator;
230 }
231
232
233 // Cite engine
234 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
235
236
237 CiteEngineTranslator const init_citeenginetranslator()
238 {
239         CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
240         translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
241         translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
242         translator.addPair("jurabib", biblio::ENGINE_JURABIB);
243         return translator;
244 }
245
246
247 CiteEngineTranslator const & citeenginetranslator()
248 {
249         static CiteEngineTranslator translator = init_citeenginetranslator();
250         return translator;
251 }
252
253
254 // Spacing
255 typedef Translator<string, Spacing::Space> SpaceTranslator;
256
257
258 SpaceTranslator const init_spacetranslator()
259 {
260         SpaceTranslator translator("default", Spacing::Default);
261         translator.addPair("single", Spacing::Single);
262         translator.addPair("onehalf", Spacing::Onehalf);
263         translator.addPair("double", Spacing::Double);
264         translator.addPair("other", Spacing::Other);
265         return translator;
266 }
267
268
269 SpaceTranslator const & spacetranslator()
270 {
271         static SpaceTranslator translator = init_spacetranslator();
272         return translator;
273 }
274
275
276 } // anon namespace
277
278
279 class BufferParams::Impl
280 {
281 public:
282         Impl();
283
284         AuthorList authorlist;
285         BranchList branchlist;
286         boost::array<Bullet, 4> temp_bullets;
287         boost::array<Bullet, 4> user_defined_bullets;
288         Spacing spacing;
289         /** This is the amount of space used for paragraph_separation "skip",
290          * and for detached paragraphs in "indented" documents.
291          */
292         VSpace defskip;
293 };
294
295
296 BufferParams::Impl::Impl()
297         : defskip(VSpace::MEDSKIP)
298 {
299         // set initial author
300         // FIXME UNICODE
301         authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
302 }
303
304
305 BufferParams::Impl *
306 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
307 {
308         BOOST_ASSERT(ptr);
309
310         return new BufferParams::Impl(*ptr);
311 }
312
313
314 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
315 {
316         delete ptr;
317 }
318
319
320 BufferParams::BufferParams()
321         : pimpl_(new Impl)
322 {
323         setBaseClass(defaultTextclass());
324         paragraph_separation = PARSEP_INDENT;
325         quotes_language = InsetQuotes::EnglishQ;
326         fontsize = "default";
327
328         /*  PaperLayout */
329         papersize = PAPER_DEFAULT;
330         orientation = ORIENTATION_PORTRAIT;
331         use_geometry = false;
332         use_amsmath = package_auto;
333         use_esint = package_auto;
334         cite_engine_ = biblio::ENGINE_BASIC;
335         use_bibtopic = false;
336         trackChanges = false;
337         outputChanges = false;
338         secnumdepth = 3;
339         tocdepth = 3;
340         language = default_language;
341         fontsRoman = "default";
342         fontsSans = "default";
343         fontsTypewriter = "default";
344         fontsDefaultFamily = "default";
345         fontsSC = false;
346         fontsOSF = false;
347         fontsSansScale = 100;
348         fontsTypewriterScale = 100;
349         inputenc = "auto";
350         graphicsDriver = "default";
351         sides = TextClass::OneSide;
352         columns = 1;
353         listings_params = string();
354         pagestyle = "default";
355         compressed = false;
356         embedded = false;
357         for (int iter = 0; iter < 4; ++iter) {
358                 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
359                 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
360         }
361 }
362
363
364 BufferParams::~BufferParams()
365 {}
366
367
368 docstring const BufferParams::B_(string const & l10n) const
369 {
370         BOOST_ASSERT(language);
371         return getMessages(language->code()).get(l10n);
372 }
373
374
375 AuthorList & BufferParams::authors()
376 {
377         return pimpl_->authorlist;
378 }
379
380
381 AuthorList const & BufferParams::authors() const
382 {
383         return pimpl_->authorlist;
384 }
385
386
387 BranchList & BufferParams::branchlist()
388 {
389         return pimpl_->branchlist;
390 }
391
392
393 BranchList const & BufferParams::branchlist() const
394 {
395         return pimpl_->branchlist;
396 }
397
398
399 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
400 {
401         BOOST_ASSERT(index < 4);
402         return pimpl_->temp_bullets[index];
403 }
404
405
406 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
407 {
408         BOOST_ASSERT(index < 4);
409         return pimpl_->temp_bullets[index];
410 }
411
412
413 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
414 {
415         BOOST_ASSERT(index < 4);
416         return pimpl_->user_defined_bullets[index];
417 }
418
419
420 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
421 {
422         BOOST_ASSERT(index < 4);
423         return pimpl_->user_defined_bullets[index];
424 }
425
426
427 Spacing & BufferParams::spacing()
428 {
429         return pimpl_->spacing;
430 }
431
432
433 Spacing const & BufferParams::spacing() const
434 {
435         return pimpl_->spacing;
436 }
437
438
439 VSpace const & BufferParams::getDefSkip() const
440 {
441         return pimpl_->defskip;
442 }
443
444
445 void BufferParams::setDefSkip(VSpace const & vs)
446 {
447         pimpl_->defskip = vs;
448 }
449
450
451 string const BufferParams::readToken(Lexer & lex, string const & token)
452 {
453         if (token == "\\textclass") {
454                 lex.next();
455                 string const classname = lex.getString();
456                 pair<bool, lyx::textclass_type> pp =
457                         textclasslist.numberOfClass(classname);
458                 if (pp.first) {
459                         setBaseClass(pp.second);
460                 } else {
461                         // if text class does not exist, try to load it from filepath
462                         pp = textclasslist.addTextClass(classname, filepath);
463                         if (pp.first) {
464                                 setBaseClass(pp.second);
465                         } else {
466                                 setBaseClass(defaultTextclass());
467                                 return classname;
468                         }
469                 }
470                 if (!getTextClass().isTeXClassAvailable()) {
471                         docstring const msg =
472                                 bformat(_("The layout file requested by this document,\n"
473                                                  "%1$s.layout,\n"
474                                                  "is not usable. This is probably because a LaTeX\n"
475                                                  "class or style file required by it is not\n"
476                                                  "available. See the Customization documentation\n"
477                                                  "for more information.\n"), from_utf8(classname));
478                         frontend::Alert::warning(_("Document class not available"),
479                                        msg + _("LyX will not be able to produce output."));
480                 } 
481                 
482         } else if (token == "\\begin_preamble") {
483                 readPreamble(lex);
484         } else if (token == "\\begin_modules") {
485                 readModules(lex);
486                 makeTextClass();
487         } else if (token == "\\options") {
488                 lex.eatLine();
489                 options = lex.getString();
490         } else if (token == "\\language") {
491                 readLanguage(lex);
492         } else if (token == "\\inputencoding") {
493                 lex >> inputenc;
494         } else if (token == "\\graphics") {
495                 readGraphicsDriver(lex);
496         } else if (token == "\\font_roman") {
497                 lex >> fontsRoman;
498         } else if (token == "\\font_sans") {
499                 lex >> fontsSans;
500         } else if (token == "\\font_typewriter") {
501                 lex >> fontsTypewriter;
502         } else if (token == "\\font_default_family") {
503                 lex >> fontsDefaultFamily;
504         } else if (token == "\\font_sc") {
505                 lex >> fontsSC;
506         } else if (token == "\\font_osf") {
507                 lex >> fontsOSF;
508         } else if (token == "\\font_sf_scale") {
509                 lex >> fontsSansScale;
510         } else if (token == "\\font_tt_scale") {
511                 lex >> fontsTypewriterScale;
512         } else if (token == "\\paragraph_separation") {
513                 string parsep;
514                 lex >> parsep;
515                 paragraph_separation = parseptranslator().find(parsep);
516         } else if (token == "\\defskip") {
517                 lex.next();
518                 pimpl_->defskip = VSpace(lex.getString());
519         } else if (token == "\\quotes_language") {
520                 string quotes_lang;
521                 lex >> quotes_lang;
522                 quotes_language = quoteslangtranslator().find(quotes_lang);
523         } else if (token == "\\papersize") {
524                 string ppsize;
525                 lex >> ppsize;
526                 papersize = papersizetranslator().find(ppsize);
527         } else if (token == "\\use_geometry") {
528                 lex >> use_geometry;
529         } else if (token == "\\use_amsmath") {
530                 int use_ams;
531                 lex >> use_ams;
532                 use_amsmath = packagetranslator().find(use_ams);
533         } else if (token == "\\use_esint") {
534                 int useesint;
535                 lex >> useesint;
536                 use_esint = packagetranslator().find(useesint);
537         } else if (token == "\\cite_engine") {
538                 string engine;
539                 lex >> engine;
540                 cite_engine_ = citeenginetranslator().find(engine);
541         } else if (token == "\\use_bibtopic") {
542                 lex >> use_bibtopic;
543         } else if (token == "\\tracking_changes") {
544                 lex >> trackChanges;
545         } else if (token == "\\output_changes") {
546                 lex >> outputChanges;
547         } else if (token == "\\branch") {
548                 lex.next();
549                 docstring branch = lex.getDocString();
550                 branchlist().add(branch);
551                 while (true) {
552                         lex.next();
553                         string const tok = lex.getString();
554                         if (tok == "\\end_branch")
555                                 break;
556                         Branch * branch_ptr = branchlist().find(branch);
557                         if (tok == "\\selected") {
558                                 lex.next();
559                                 if (branch_ptr)
560                                         branch_ptr->setSelected(lex.getInteger());
561                         }
562                         // not yet operational
563                         if (tok == "\\color") {
564                                 lex.eatLine();
565                                 string color = lex.getString();
566                                 if (branch_ptr)
567                                         branch_ptr->setColor(color);
568                                 // Update also the Color table:
569                                 if (color == "none")
570                                         color = lcolor.getX11Name(Color::background);
571                                 // FIXME UNICODE
572                                 lcolor.setColor(to_utf8(branch), color);
573
574                         }
575                 }
576         } else if (token == "\\author") {
577                 lex.eatLine();
578                 istringstream ss(lex.getString());
579                 Author a;
580                 ss >> a;
581                 author_map.push_back(pimpl_->authorlist.record(a));
582         } else if (token == "\\paperorientation") {
583                 string orient;
584                 lex >> orient;
585                 orientation = paperorientationtranslator().find(orient);
586         } else if (token == "\\paperwidth") {
587                 lex >> paperwidth;
588         } else if (token == "\\paperheight") {
589                 lex >> paperheight;
590         } else if (token == "\\leftmargin") {
591                 lex >> leftmargin;
592         } else if (token == "\\topmargin") {
593                 lex >> topmargin;
594         } else if (token == "\\rightmargin") {
595                 lex >> rightmargin;
596         } else if (token == "\\bottommargin") {
597                 lex >> bottommargin;
598         } else if (token == "\\headheight") {
599                 lex >> headheight;
600         } else if (token == "\\headsep") {
601                 lex >> headsep;
602         } else if (token == "\\footskip") {
603                 lex >> footskip;
604         } else if (token == "\\paperfontsize") {
605                 lex >> fontsize;
606         } else if (token == "\\papercolumns") {
607                 lex >> columns;
608         } else if (token == "\\listings_params") {
609                 string par;
610                 lex >> par;
611                 listings_params = InsetListingsParams(par).params();
612         } else if (token == "\\papersides") {
613                 int psides;
614                 lex >> psides;
615                 sides = sidestranslator().find(psides);
616         } else if (token == "\\paperpagestyle") {
617                 lex >> pagestyle;
618         } else if (token == "\\bullet") {
619                 readBullets(lex);
620         } else if (token == "\\bulletLaTeX") {
621                 readBulletsLaTeX(lex);
622         } else if (token == "\\secnumdepth") {
623                 lex >> secnumdepth;
624         } else if (token == "\\tocdepth") {
625                 lex >> tocdepth;
626         } else if (token == "\\spacing") {
627                 string nspacing;
628                 lex >> nspacing;
629                 string tmp_val;
630                 if (nspacing == "other") {
631                         lex >> tmp_val;
632                 }
633                 spacing().set(spacetranslator().find(nspacing), tmp_val);
634         } else if (token == "\\float_placement") {
635                 lex >> float_placement;
636         } else {
637                 lyxerr << "BufferParams::readToken(): Unknown token: " << 
638                         token << endl;
639                 return token;
640         }
641
642         return string();
643 }
644
645
646 void BufferParams::writeFile(ostream & os) const
647 {
648         // The top of the file is written by the buffer.
649         // Prints out the buffer info into the .lyx file given by file
650
651         // the textclass
652         os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
653
654         // then the preamble
655         if (!preamble.empty()) {
656                 // remove '\n' from the end of preamble
657                 string const tmppreamble = rtrim(preamble, "\n");
658                 os << "\\begin_preamble\n"
659                    << tmppreamble
660                    << "\n\\end_preamble\n";
661         }
662
663         // the options
664         if (!options.empty()) {
665                 os << "\\options " << options << '\n';
666         }
667         
668         //the modules
669         if (!layoutModules_.empty()) {
670                 os << "\\begin_modules" << '\n';
671                 LayoutModuleList::const_iterator it = layoutModules_.begin();
672                 for (; it != layoutModules_.end(); it++)
673                         os << *it << '\n';
674                 os << "\\end_modules" << '\n';
675         }
676
677         // then the text parameters
678         if (language != ignore_language)
679                 os << "\\language " << language->lang() << '\n';
680         os << "\\inputencoding " << inputenc
681            << "\n\\font_roman " << fontsRoman
682            << "\n\\font_sans " << fontsSans
683            << "\n\\font_typewriter " << fontsTypewriter
684            << "\n\\font_default_family " << fontsDefaultFamily
685            << "\n\\font_sc " << convert<string>(fontsSC)
686            << "\n\\font_osf " << convert<string>(fontsOSF)
687            << "\n\\font_sf_scale " << fontsSansScale
688            << "\n\\font_tt_scale " << fontsTypewriterScale
689            << "\n\\graphics " << graphicsDriver << '\n';
690
691         if (!float_placement.empty()) {
692                 os << "\\float_placement " << float_placement << '\n';
693         }
694         os << "\\paperfontsize " << fontsize << '\n';
695
696         spacing().writeFile(os);
697
698         os << "\\papersize " << string_papersize[papersize]
699            << "\n\\use_geometry " << convert<string>(use_geometry)
700            << "\n\\use_amsmath " << use_amsmath
701            << "\n\\use_esint " << use_esint
702            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
703            << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
704            << "\n\\paperorientation " << string_orientation[orientation]
705            << '\n';
706
707         BranchList::const_iterator it = branchlist().begin();
708         BranchList::const_iterator end = branchlist().end();
709         for (; it != end; ++it) {
710                 os << "\\branch " << to_utf8(it->getBranch())
711                    << "\n\\selected " << it->getSelected()
712                    << "\n\\color " << lyx::X11hexname(it->getColor())
713                    << "\n\\end_branch"
714                    << "\n";
715         }
716
717         if (!paperwidth.empty())
718                 os << "\\paperwidth "
719                    << VSpace(paperwidth).asLyXCommand() << '\n';
720         if (!paperheight.empty())
721                 os << "\\paperheight "
722                    << VSpace(paperheight).asLyXCommand() << '\n';
723         if (!leftmargin.empty())
724                 os << "\\leftmargin "
725                    << VSpace(leftmargin).asLyXCommand() << '\n';
726         if (!topmargin.empty())
727                 os << "\\topmargin "
728                    << VSpace(topmargin).asLyXCommand() << '\n';
729         if (!rightmargin.empty())
730                 os << "\\rightmargin "
731                    << VSpace(rightmargin).asLyXCommand() << '\n';
732         if (!bottommargin.empty())
733                 os << "\\bottommargin "
734                    << VSpace(bottommargin).asLyXCommand() << '\n';
735         if (!headheight.empty())
736                 os << "\\headheight "
737                    << VSpace(headheight).asLyXCommand() << '\n';
738         if (!headsep.empty())
739                 os << "\\headsep "
740                    << VSpace(headsep).asLyXCommand() << '\n';
741         if (!footskip.empty())
742                 os << "\\footskip "
743                    << VSpace(footskip).asLyXCommand() << '\n';
744         os << "\\secnumdepth " << secnumdepth
745            << "\n\\tocdepth " << tocdepth
746            << "\n\\paragraph_separation "
747            << string_paragraph_separation[paragraph_separation]
748            << "\n\\defskip " << getDefSkip().asLyXCommand()
749            << "\n\\quotes_language "
750            << string_quotes_language[quotes_language]
751            << "\n\\papercolumns " << columns
752            << "\n\\papersides " << sides
753            << "\n\\paperpagestyle " << pagestyle << '\n';
754         if (!listings_params.empty())
755                 os << "\\listings_params \"" <<
756                         InsetListingsParams(listings_params).encodedString() << "\"\n";
757         for (int i = 0; i < 4; ++i) {
758                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
759                         if (user_defined_bullet(i).getFont() != -1) {
760                                 os << "\\bullet " << i << " "
761                                    << user_defined_bullet(i).getFont() << " "
762                                    << user_defined_bullet(i).getCharacter() << " "
763                                    << user_defined_bullet(i).getSize() << "\n";
764                         }
765                         else {
766                                 // FIXME UNICODE
767                                 os << "\\bulletLaTeX " << i << " \""
768                                    << lyx::to_ascii(user_defined_bullet(i).getText())
769                                    << "\"\n";
770                         }
771                 }
772         }
773
774         os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
775         os << "\\output_changes " << convert<string>(outputChanges) << "\n";
776
777         AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
778         AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
779         for (; a_it != a_end; ++a_it) {
780                 if (a_it->second.used())
781                         os << "\\author " << a_it->second << "\n";
782                 else
783                         os << "\\author " << Author() << "\n";
784         }
785 }
786
787
788 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
789                               TexRow & texrow) const
790 {
791         os << "\\documentclass";
792
793         TextClass const & tclass = getTextClass();
794
795         ostringstream clsoptions; // the document class options.
796
797         if (tokenPos(tclass.opt_fontsize(),
798                      '|', fontsize) >= 0) {
799                 // only write if existing in list (and not default)
800                 clsoptions << fontsize << "pt,";
801         }
802
803         // custom, A3, B3 and B4 paper sizes need geometry
804         bool nonstandard_papersize = papersize == PAPER_B3
805                 || papersize == PAPER_B4
806                 || papersize == PAPER_A3
807                 || papersize == PAPER_CUSTOM;
808
809         if (!use_geometry) {
810                 switch (papersize) {
811                 case PAPER_A4:
812                         clsoptions << "a4paper,";
813                         break;
814                 case PAPER_USLETTER:
815                         clsoptions << "letterpaper,";
816                         break;
817                 case PAPER_A5:
818                         clsoptions << "a5paper,";
819                         break;
820                 case PAPER_B5:
821                         clsoptions << "b5paper,";
822                         break;
823                 case PAPER_USEXECUTIVE:
824                         clsoptions << "executivepaper,";
825                         break;
826                 case PAPER_USLEGAL:
827                         clsoptions << "legalpaper,";
828                         break;
829                 case PAPER_DEFAULT:
830                 case PAPER_A3:
831                 case PAPER_B3:
832                 case PAPER_B4:
833                 case PAPER_CUSTOM:
834                         break;
835                 }
836         }
837
838         // if needed
839         if (sides != tclass.sides()) {
840                 switch (sides) {
841                 case TextClass::OneSide:
842                         clsoptions << "oneside,";
843                         break;
844                 case TextClass::TwoSides:
845                         clsoptions << "twoside,";
846                         break;
847                 }
848         }
849
850         // if needed
851         if (columns != tclass.columns()) {
852                 if (columns == 2)
853                         clsoptions << "twocolumn,";
854                 else
855                         clsoptions << "onecolumn,";
856         }
857
858         if (!use_geometry
859             && orientation == ORIENTATION_LANDSCAPE)
860                 clsoptions << "landscape,";
861
862         // language should be a parameter to \documentclass
863         if (language->babel() == "hebrew"
864             && default_language->babel() != "hebrew")
865                 // This seems necessary
866                 features.useLanguage(default_language);
867
868         ostringstream language_options;
869         bool const use_babel = features.useBabel();
870         if (use_babel) {
871                 language_options << features.getLanguages();
872                 if (!language->babel().empty()) {
873                         if (!language_options.str().empty())
874                                 language_options << ',';
875                         language_options << language->babel();
876                 }
877                 if (lyxrc.language_global_options && !language_options.str().empty())
878                         clsoptions << language_options.str() << ',';
879         }
880
881         // the user-defined options
882         if (!options.empty()) {
883                 clsoptions << options << ',';
884         }
885
886         string strOptions(clsoptions.str());
887         if (!strOptions.empty()) {
888                 strOptions = rtrim(strOptions, ",");
889                 // FIXME UNICODE
890                 os << '[' << from_utf8(strOptions) << ']';
891         }
892
893         os << '{' << from_ascii(tclass.latexname()) << "}\n";
894         texrow.newline();
895         // end of \documentclass defs
896
897         // font selection must be done before loading fontenc.sty
898         string const fonts =
899                 loadFonts(fontsRoman, fontsSans,
900                           fontsTypewriter, fontsSC, fontsOSF,
901                           fontsSansScale, fontsTypewriterScale);
902         if (!fonts.empty()) {
903                 os << from_ascii(fonts);
904                 texrow.newline();
905         }
906         if (fontsDefaultFamily != "default")
907                 os << "\\renewcommand{\\familydefault}{\\"
908                    << from_ascii(fontsDefaultFamily) << "}\n";
909
910         // set font encoding
911         // this one is not per buffer
912         // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
913         if (lyxrc.fontenc != "default") {
914                 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
915                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
916                            << ",LFE,LAE]{fontenc}\n";
917                         texrow.newline();
918                 } else {
919                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
920                            << "]{fontenc}\n";
921                         texrow.newline();
922                 }
923         }
924
925         // handle inputenc etc.
926         writeEncodingPreamble(os, features, texrow);
927
928         if (!listings_params.empty()) {
929                 os << "\\usepackage{listings}\n";
930                 texrow.newline();
931                 os << "\\lstset{";
932                 // do not test validity because listings_params is supposed to be valid
933                 string par = InsetListingsParams(listings_params).separatedParams(true);
934                 os << from_ascii(par);
935                 // count the number of newlines
936                 for (size_t i = 0; i < par.size(); ++i)
937                         if (par[i] == '\n')
938                                 texrow.newline();
939                 os << "}\n";
940                 texrow.newline();
941         }
942         if (use_geometry || nonstandard_papersize) {
943                 os << "\\usepackage{geometry}\n";
944                 texrow.newline();
945                 os << "\\geometry{verbose";
946                 if (orientation == ORIENTATION_LANDSCAPE)
947                         os << ",landscape";
948                 switch (papersize) {
949                 case PAPER_CUSTOM:
950                         if (!paperwidth.empty())
951                                 os << ",paperwidth="
952                                    << from_ascii(paperwidth);
953                         if (!paperheight.empty())
954                                 os << ",paperheight="
955                                    << from_ascii(paperheight);
956                         break;
957                 case PAPER_USLETTER:
958                         os << ",letterpaper";
959                         break;
960                 case PAPER_USLEGAL:
961                         os << ",legalpaper";
962                         break;
963                 case PAPER_USEXECUTIVE:
964                         os << ",executivepaper";
965                         break;
966                 case PAPER_A3:
967                         os << ",a3paper";
968                         break;
969                 case PAPER_A4:
970                         os << ",a4paper";
971                         break;
972                 case PAPER_A5:
973                         os << ",a5paper";
974                         break;
975                 case PAPER_B3:
976                         os << ",b3paper";
977                         break;
978                 case PAPER_B4:
979                         os << ",b4paper";
980                         break;
981                 case PAPER_B5:
982                         os << ",b5paper";
983                         break;
984                 default:
985                         // default papersize ie PAPER_DEFAULT
986                         switch (lyxrc.default_papersize) {
987                         case PAPER_DEFAULT: // keep compiler happy
988                         case PAPER_USLETTER:
989                                 os << ",letterpaper";
990                                 break;
991                         case PAPER_USLEGAL:
992                                 os << ",legalpaper";
993                                 break;
994                         case PAPER_USEXECUTIVE:
995                                 os << ",executivepaper";
996                                 break;
997                         case PAPER_A3:
998                                 os << ",a3paper";
999                                 break;
1000                         case PAPER_A4:
1001                                 os << ",a4paper";
1002                                 break;
1003                         case PAPER_A5:
1004                                 os << ",a5paper";
1005                                 break;
1006                         case PAPER_B5:
1007                                 os << ",b5paper";
1008                                 break;
1009                         case PAPER_B3:
1010                         case PAPER_B4:
1011                         case PAPER_CUSTOM:
1012                                 break;
1013                         }
1014                 }
1015                 if (!topmargin.empty())
1016                         os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1017                 if (!bottommargin.empty())
1018                         os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1019                 if (!leftmargin.empty())
1020                         os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1021                 if (!rightmargin.empty())
1022                         os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1023                 if (!headheight.empty())
1024                         os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1025                 if (!headsep.empty())
1026                         os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1027                 if (!footskip.empty())
1028                         os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1029                 os << "}\n";
1030                 texrow.newline();
1031         }
1032
1033         if (tokenPos(tclass.opt_pagestyle(),
1034                      '|', pagestyle) >= 0) {
1035                 if (pagestyle == "fancy") {
1036                         os << "\\usepackage{fancyhdr}\n";
1037                         texrow.newline();
1038                 }
1039                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1040                 texrow.newline();
1041         }
1042
1043         // Only if class has a ToC hierarchy
1044         if (tclass.hasTocLevels()) {
1045                 if (secnumdepth != tclass.secnumdepth()) {
1046                         os << "\\setcounter{secnumdepth}{"
1047                            << secnumdepth
1048                            << "}\n";
1049                         texrow.newline();
1050                 }
1051                 if (tocdepth != tclass.tocdepth()) {
1052                         os << "\\setcounter{tocdepth}{"
1053                            << tocdepth
1054                            << "}\n";
1055                         texrow.newline();
1056                 }
1057         }
1058
1059         if (paragraph_separation) {
1060                 switch (getDefSkip().kind()) {
1061                 case VSpace::SMALLSKIP:
1062                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1063                         break;
1064                 case VSpace::MEDSKIP:
1065                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1066                         break;
1067                 case VSpace::BIGSKIP:
1068                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1069                         break;
1070                 case VSpace::LENGTH:
1071                         os << "\\setlength{\\parskip}{"
1072                            << from_utf8(getDefSkip().length().asLatexString())
1073                            << "}\n";
1074                         break;
1075                 default: // should never happen // Then delete it.
1076                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1077                         break;
1078                 }
1079                 texrow.newline();
1080
1081                 os << "\\setlength{\\parindent}{0pt}\n";
1082                 texrow.newline();
1083         }
1084
1085         // If we use jurabib, we have to call babel here.
1086         if (use_babel && features.isRequired("jurabib")) {
1087                 os << from_ascii(babelCall(language_options.str()))
1088                    << '\n'
1089                    << from_ascii(features.getBabelOptions());
1090                 texrow.newline();
1091         }
1092
1093         // Now insert the LyX specific LaTeX commands...
1094
1095         // The optional packages;
1096         docstring lyxpreamble(from_ascii(features.getPackages()));
1097
1098         // this might be useful...
1099         lyxpreamble += "\n\\makeatletter\n";
1100
1101         // Some macros LyX will need
1102         docstring tmppreamble(from_ascii(features.getMacros()));
1103
1104         if (!tmppreamble.empty()) {
1105                 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1106                         "LyX specific LaTeX commands.\n"
1107                         + tmppreamble + '\n';
1108         }
1109
1110         // the text class specific preamble
1111         tmppreamble = features.getTClassPreamble();
1112         if (!tmppreamble.empty()) {
1113                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1114                         "Textclass specific LaTeX commands.\n"
1115                         + tmppreamble + '\n';
1116         }
1117
1118         /* the user-defined preamble */
1119         if (!preamble.empty()) {
1120                 // FIXME UNICODE
1121                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1122                         "User specified LaTeX commands.\n"
1123                         + from_utf8(preamble) + '\n';
1124         }
1125
1126         // Itemize bullet settings need to be last in case the user
1127         // defines their own bullets that use a package included
1128         // in the user-defined preamble -- ARRae
1129         // Actually it has to be done much later than that
1130         // since some packages like frenchb make modifications
1131         // at \begin{document} time -- JMarc
1132         docstring bullets_def;
1133         for (int i = 0; i < 4; ++i) {
1134                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1135                         if (bullets_def.empty())
1136                                 bullets_def += "\\AtBeginDocument{\n";
1137                         bullets_def += "  \\def\\labelitemi";
1138                         switch (i) {
1139                                 // `i' is one less than the item to modify
1140                         case 0:
1141                                 break;
1142                         case 1:
1143                                 bullets_def += 'i';
1144                                 break;
1145                         case 2:
1146                                 bullets_def += "ii";
1147                                 break;
1148                         case 3:
1149                                 bullets_def += 'v';
1150                                 break;
1151                         }
1152                         bullets_def += '{' +
1153                                 user_defined_bullet(i).getText()
1154                                 + "}\n";
1155                 }
1156         }
1157
1158         if (!bullets_def.empty())
1159                 lyxpreamble += bullets_def + "}\n\n";
1160
1161         // We try to load babel late, in case it interferes
1162         // with other packages.
1163         // Jurabib has to be called after babel, though.
1164         if (use_babel && !features.isRequired("jurabib")) {
1165                 // FIXME UNICODE
1166                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1167                 lyxpreamble += from_utf8(features.getBabelOptions());
1168         }
1169
1170         lyxpreamble += "\\makeatother\n\n";
1171
1172         int const nlines =
1173                 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1174         for (int j = 0; j != nlines; ++j) {
1175                 texrow.newline();
1176         }
1177
1178         os << lyxpreamble;
1179         return use_babel;
1180 }
1181
1182
1183 void BufferParams::useClassDefaults()
1184 {
1185         TextClass const & tclass = textclasslist[baseClass_];
1186
1187         sides = tclass.sides();
1188         columns = tclass.columns();
1189         pagestyle = tclass.pagestyle();
1190         options = tclass.options();
1191         // Only if class has a ToC hierarchy
1192         if (tclass.hasTocLevels()) {
1193                 secnumdepth = tclass.secnumdepth();
1194                 tocdepth = tclass.tocdepth();
1195         }
1196 }
1197
1198
1199 bool BufferParams::hasClassDefaults() const
1200 {
1201         TextClass const & tclass = textclasslist[baseClass_];
1202
1203         return (sides == tclass.sides()
1204                 && columns == tclass.columns()
1205                 && pagestyle == tclass.pagestyle()
1206                 && options == tclass.options()
1207                 && secnumdepth == tclass.secnumdepth()
1208                 && tocdepth == tclass.tocdepth());
1209 }
1210
1211
1212 TextClass const & BufferParams::getTextClass() const
1213 {
1214         return *textClass_;
1215 }
1216
1217
1218 TextClass_ptr BufferParams::getTextClass_ptr() const {
1219         return textClass_;
1220 }
1221
1222
1223 void BufferParams::setTextClass(TextClass_ptr tc) {
1224         textClass_ = tc;
1225 }
1226
1227
1228 bool BufferParams::setBaseClass(textclass_type tc)
1229 {
1230         if (!textclasslist[tc].load()) {
1231                 docstring s = bformat(_("The document class %1$s."
1232                                         "could not be loaded."),
1233                  from_utf8(textclasslist[tc].name()));
1234                 frontend::Alert::error(_("Could not load class"), s);
1235                 return false;
1236         }
1237         
1238         baseClass_ = tc;
1239         makeTextClass();
1240         return true;
1241 }
1242
1243
1244 void BufferParams::setJustBaseClass(textclass_type tc)
1245
1246         baseClass_ = tc; 
1247 }
1248
1249
1250 textclass_type BufferParams::getBaseClass() const
1251 {
1252         return baseClass_;
1253 }
1254
1255
1256 void BufferParams::makeTextClass()
1257 {
1258         textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1259         //FIXME It might be worth loading the children's modules here,
1260         //just as we load their bibliographies and such, instead of just 
1261         //doing a check in InsetInclude.
1262         LayoutModuleList::const_iterator it = layoutModules_.begin();
1263         for (; it != layoutModules_.end(); it++) {
1264                 string const modName = *it;
1265                 LyXModule * lm = moduleList[modName];
1266                 if (!lm) {
1267                         docstring const msg =
1268                                                 bformat(_("The module %1$s has been requested by\n"
1269                                                 "this document but has not been found in the list of\n"
1270                                                 "available modules. If you recently installed it, you\n"
1271                                                 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1272                         frontend::Alert::warning(_("Module not available"),
1273                                                                                                                          msg + _("Some layouts may not be available."));
1274                         lyxerr << "BufferParams::makeTextClass(): Module " <<
1275                                         modName << " requested but not found in module list." <<
1276                                         endl;
1277                         continue;
1278                 }
1279                 FileName layout_file = libFileSearch("layouts", lm->filename);
1280                 textClass_->read(layout_file, TextClass::MODULE);
1281         }
1282 }
1283
1284
1285 std::vector<string> const & BufferParams::getModules() const {
1286         return layoutModules_;
1287 }
1288
1289
1290
1291 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1292         LayoutModuleList::const_iterator it = layoutModules_.begin();
1293         LayoutModuleList::const_iterator end = layoutModules_.end();
1294         for (; it != end; it++) {
1295                 if (*it == modName) 
1296                         break;
1297         }
1298         if (it != layoutModules_.end())
1299                 return false;
1300         layoutModules_.push_back(modName);
1301         if (makeClass)
1302                 makeTextClass();
1303         return true;
1304 }
1305
1306
1307 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1308 {
1309         bool retval = true;
1310         std::vector<string>::const_iterator it = modNames.begin();
1311         std::vector<string>::const_iterator end = modNames.end();
1312         for (; it != end; ++it)
1313                 retval &= addLayoutModule(*it, false);
1314         makeTextClass();
1315         return retval;
1316 }
1317
1318
1319 void BufferParams::clearLayoutModules() {
1320         layoutModules_.clear();
1321         makeTextClass();
1322 }
1323
1324
1325 Font const BufferParams::getFont() const
1326 {
1327         Font f = getTextClass().defaultfont();
1328         f.setLanguage(language);
1329         if (fontsDefaultFamily == "rmdefault")
1330                 f.setFamily(Font::ROMAN_FAMILY);
1331         else if (fontsDefaultFamily == "sfdefault")
1332                 f.setFamily(Font::SANS_FAMILY);
1333         else if (fontsDefaultFamily == "ttdefault")
1334                 f.setFamily(Font::TYPEWRITER_FAMILY);
1335         return f;
1336 }
1337
1338
1339 void BufferParams::readPreamble(Lexer & lex)
1340 {
1341         if (lex.getString() != "\\begin_preamble")
1342                 lyxerr << "Error (BufferParams::readPreamble):"
1343                         "consistency check failed." << endl;
1344
1345         preamble = lex.getLongString("\\end_preamble");
1346 }
1347
1348
1349 void BufferParams::readLanguage(Lexer & lex)
1350 {
1351         if (!lex.next()) return;
1352
1353         string const tmptok = lex.getString();
1354
1355         // check if tmptok is part of tex_babel in tex-defs.h
1356         language = languages.getLanguage(tmptok);
1357         if (!language) {
1358                 // Language tmptok was not found
1359                 language = default_language;
1360                 lyxerr << "Warning: Setting language `"
1361                        << tmptok << "' to `" << language->lang()
1362                        << "'." << endl;
1363         }
1364 }
1365
1366
1367 void BufferParams::readGraphicsDriver(Lexer & lex)
1368 {
1369         if (!lex.next()) return;
1370
1371         string const tmptok = lex.getString();
1372         // check if tmptok is part of tex_graphics in tex_defs.h
1373         int n = 0;
1374         while (true) {
1375                 string const test = tex_graphics[n++];
1376
1377                 if (test == tmptok) {
1378                         graphicsDriver = tmptok;
1379                         break;
1380                 } else if (test == "") {
1381                         lex.printError(
1382                                 "Warning: graphics driver `$$Token' not recognized!\n"
1383                                 "         Setting graphics driver to `default'.\n");
1384                         graphicsDriver = "default";
1385                         break;
1386                 }
1387         }
1388 }
1389
1390
1391 void BufferParams::readBullets(Lexer & lex)
1392 {
1393         if (!lex.next()) return;
1394
1395         int const index = lex.getInteger();
1396         lex.next();
1397         int temp_int = lex.getInteger();
1398         user_defined_bullet(index).setFont(temp_int);
1399         temp_bullet(index).setFont(temp_int);
1400         lex >> temp_int;
1401         user_defined_bullet(index).setCharacter(temp_int);
1402         temp_bullet(index).setCharacter(temp_int);
1403         lex >> temp_int;
1404         user_defined_bullet(index).setSize(temp_int);
1405         temp_bullet(index).setSize(temp_int);
1406 }
1407
1408
1409 void BufferParams::readBulletsLaTeX(Lexer & lex)
1410 {
1411         // The bullet class should be able to read this.
1412         if (!lex.next()) return;
1413         int const index = lex.getInteger();
1414         lex.next(true);
1415         docstring const temp_str = lex.getDocString();
1416
1417         user_defined_bullet(index).setText(temp_str);
1418         temp_bullet(index).setText(temp_str);
1419 }
1420
1421
1422 void BufferParams::readModules(Lexer & lex)
1423 {
1424         if (!lex.eatLine()) {
1425                 lyxerr << "Error (BufferParams::readModules):"
1426                                 "Unexpected end of input." << endl;
1427                 return;
1428         }
1429         while (true) {
1430                 string mod = lex.getString();
1431                 if (mod == "\\end_modules")
1432                         break;
1433                 addLayoutModule(mod);
1434                 lex.eatLine();
1435         }
1436 }
1437
1438
1439 string const BufferParams::paperSizeName() const
1440 {
1441         char real_papersize = papersize;
1442         if (real_papersize == PAPER_DEFAULT)
1443                 real_papersize = lyxrc.default_papersize;
1444
1445         switch (real_papersize) {
1446         case PAPER_A3:
1447                 return "a3";
1448         case PAPER_A4:
1449                 return "a4";
1450         case PAPER_A5:
1451                 return "a5";
1452         case PAPER_B5:
1453                 return "b5";
1454         case PAPER_USEXECUTIVE:
1455                 return "foolscap";
1456         case PAPER_USLEGAL:
1457                 return "legal";
1458         case PAPER_USLETTER:
1459         default:
1460                 return "letter";
1461         }
1462 }
1463
1464
1465 string const BufferParams::dvips_options() const
1466 {
1467         string result;
1468
1469         if (use_geometry
1470             && papersize == PAPER_CUSTOM
1471             && !lyxrc.print_paper_dimension_flag.empty()
1472             && !paperwidth.empty()
1473             && !paperheight.empty()) {
1474                 // using a custom papersize
1475                 result = lyxrc.print_paper_dimension_flag;
1476                 result += ' ' + paperwidth;
1477                 result += ',' + paperheight;
1478         } else {
1479                 string const paper_option = paperSizeName();
1480                 if (paper_option != "letter" ||
1481                     orientation != ORIENTATION_LANDSCAPE) {
1482                         // dvips won't accept -t letter -t landscape.
1483                         // In all other cases, include the paper size
1484                         // explicitly.
1485                         result = lyxrc.print_paper_flag;
1486                         result += ' ' + paper_option;
1487                 }
1488         }
1489         if (orientation == ORIENTATION_LANDSCAPE &&
1490             papersize != PAPER_CUSTOM)
1491                 result += ' ' + lyxrc.print_landscape_flag;
1492         return result;
1493 }
1494
1495
1496 string const BufferParams::babelCall(string const & lang_opts) const
1497 {
1498         string lang_pack = lyxrc.language_package;
1499         if (lang_pack != "\\usepackage{babel}")
1500                 return lang_pack;
1501         // suppress the babel call when there is no babel language defined
1502         // for the document language in the lib/languages file and if no
1503         // other languages are used (lang_opts is then empty)
1504         if (lang_opts.empty())
1505                 return string();
1506         if (!lyxrc.language_global_options)
1507                 return "\\usepackage[" + lang_opts + "]{babel}";
1508         return lang_pack;
1509 }
1510
1511
1512 void BufferParams::writeEncodingPreamble(odocstream & os,
1513                 LaTeXFeatures & features, TexRow & texrow) const
1514 {
1515         if (inputenc == "auto") {
1516                 string const doc_encoding =
1517                         language->encoding()->latexName();
1518                 Encoding::Package const package =
1519                         language->encoding()->package();
1520
1521                 // Create a list with all the input encodings used
1522                 // in the document
1523                 std::set<string> encodings =
1524                         features.getEncodingSet(doc_encoding);
1525
1526                 if (!encodings.empty() || package == Encoding::inputenc) {
1527                         os << "\\usepackage[";
1528                         std::set<string>::const_iterator it = encodings.begin();
1529                         std::set<string>::const_iterator const end = encodings.end();
1530                         if (it != end) {
1531                                 os << from_ascii(*it);
1532                                 ++it;
1533                         }
1534                         for (; it != end; ++it)
1535                                 os << ',' << from_ascii(*it);
1536                         if (package == Encoding::inputenc) {
1537                                 if (!encodings.empty())
1538                                         os << ',';
1539                                 os << from_ascii(doc_encoding);
1540                         }
1541                         os << "]{inputenc}\n";
1542                         texrow.newline();
1543                 }
1544                 if (package == Encoding::CJK) {
1545                         os << "\\usepackage{CJK}\n";
1546                         texrow.newline();
1547                 }
1548         } else if (inputenc != "default") {
1549                 switch (encoding().package()) {
1550                 case Encoding::none:
1551                         break;
1552                 case Encoding::inputenc:
1553                         os << "\\usepackage[" << from_ascii(inputenc)
1554                            << "]{inputenc}\n";
1555                         texrow.newline();
1556                         break;
1557                 case Encoding::CJK:
1558                         os << "\\usepackage{CJK}\n";
1559                         texrow.newline();
1560                         break;
1561                 }
1562         }
1563
1564         // The encoding "armscii8" is only available when the package "armtex" is loaded.
1565         // armscii8 is used for Armenian.
1566         if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1567                 os << "\\usepackage{armtex}\n";
1568                 texrow.newline();
1569         }
1570 }
1571
1572
1573 string const BufferParams::loadFonts(string const & rm,
1574                                      string const & sf, string const & tt,
1575                                      bool const & sc, bool const & osf,
1576                                      int const & sfscale, int const & ttscale) const
1577 {
1578         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1579            several packages have been replaced by others, that might not
1580            be installed on every system. We have to take care for that
1581            (see psnfss.pdf). We try to support all psnfss fonts as well
1582            as the fonts that have become de facto standard in the LaTeX
1583            world (e.g. Latin Modern). We do not support obsolete fonts
1584            (like PSLatex). In general, it should be possible to mix any
1585            rm font with any sf or tt font, respectively. (JSpitzm)
1586            TODO:
1587                 -- separate math fonts.
1588         */
1589
1590         if (rm == "default" && sf == "default" && tt == "default")
1591                 //nothing to do
1592                 return string();
1593
1594         ostringstream os;
1595
1596         // ROMAN FONTS
1597         // Computer Modern (must be explicitely selectable -- there might be classes
1598         // that define a different default font!
1599         if (rm == "cmr") {
1600                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1601                 // osf for Computer Modern needs eco.sty
1602                 if (osf)
1603                         os << "\\usepackage{eco}\n";
1604         }
1605         // Latin Modern Roman
1606         else if (rm == "lmodern")
1607                 os << "\\usepackage{lmodern}\n";
1608         // AE
1609         else if (rm == "ae") {
1610                 // not needed when using OT1 font encoding.
1611                 if (lyxrc.fontenc != "default")
1612                         os << "\\usepackage{ae,aecompl}\n";
1613         }
1614         // Times
1615         else if (rm == "times") {
1616                 // try to load the best available package
1617                 if (LaTeXFeatures::isAvailable("mathptmx"))
1618                         os << "\\usepackage{mathptmx}\n";
1619                 else if (LaTeXFeatures::isAvailable("mathptm"))
1620                         os << "\\usepackage{mathptm}\n";
1621                 else
1622                         os << "\\usepackage{times}\n";
1623         }
1624         // Palatino
1625         else if (rm == "palatino") {
1626                 // try to load the best available package
1627                 if (LaTeXFeatures::isAvailable("mathpazo")) {
1628                         os << "\\usepackage";
1629                         if (osf || sc) {
1630                                 os << '[';
1631                                 if (!osf)
1632                                         os << "sc";
1633                                 else
1634                                         // "osf" includes "sc"!
1635                                         os << "osf";
1636                                 os << ']';
1637                         }
1638                         os << "{mathpazo}\n";
1639                 }
1640                 else if (LaTeXFeatures::isAvailable("mathpple"))
1641                         os << "\\usepackage{mathpple}\n";
1642                 else
1643                         os << "\\usepackage{palatino}\n";
1644         }
1645         // Utopia
1646         else if (rm == "utopia") {
1647                 // fourier supersedes utopia.sty, but does
1648                 // not work with OT1 encoding.
1649                 if (LaTeXFeatures::isAvailable("fourier")
1650                     && lyxrc.fontenc != "default") {
1651                         os << "\\usepackage";
1652                         if (osf || sc) {
1653                                 os << '[';
1654                                 if (sc)
1655                                         os << "expert";
1656                                 if (osf && sc)
1657                                         os << ',';
1658                                 if (osf)
1659                                         os << "oldstyle";
1660                                 os << ']';
1661                         }
1662                         os << "{fourier}\n";
1663                 }
1664                 else
1665                         os << "\\usepackage{utopia}\n";
1666         }
1667         // Bera (complete fontset)
1668         else if (rm == "bera" && sf == "default" && tt == "default")
1669                 os << "\\usepackage{bera}\n";
1670         // everything else
1671         else if (rm != "default")
1672                 os << "\\usepackage" << "{" << rm << "}\n";
1673
1674         // SANS SERIF
1675         // Helvetica, Bera Sans
1676         if (sf == "helvet" || sf == "berasans") {
1677                 if (sfscale != 100)
1678                         os << "\\usepackage[scaled=" << float(sfscale) / 100
1679                            << "]{" << sf << "}\n";
1680                 else
1681                         os << "\\usepackage{" << sf << "}\n";
1682         }
1683         // Avant Garde
1684         else if (sf == "avant")
1685                 os << "\\usepackage{" << sf << "}\n";
1686         // Computer Modern, Latin Modern, CM Bright
1687         else if (sf != "default")
1688                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1689
1690         // monospaced/typewriter
1691         // Courier, LuxiMono
1692         if (tt == "luximono" || tt == "beramono") {
1693                 if (ttscale != 100)
1694                         os << "\\usepackage[scaled=" << float(ttscale) / 100
1695                            << "]{" << tt << "}\n";
1696                 else
1697                         os << "\\usepackage{" << tt << "}\n";
1698         }
1699         // Courier
1700         else if (tt == "courier" )
1701                 os << "\\usepackage{" << tt << "}\n";
1702         // Computer Modern, Latin Modern, CM Bright
1703         else if  (tt != "default")
1704                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1705
1706         return os.str();
1707 }
1708
1709
1710 Encoding const & BufferParams::encoding() const
1711 {
1712         if (inputenc == "auto" || inputenc == "default")
1713                 return *(language->encoding());
1714         Encoding const * const enc =
1715                 encodings.getFromLaTeXName(inputenc);
1716         if (enc)
1717                 return *enc;
1718         lyxerr << "Unknown inputenc value `" << inputenc
1719                << "'. Using `auto' instead." << endl;
1720         return *(language->encoding());
1721 }
1722
1723
1724 biblio::CiteEngine BufferParams::getEngine() const
1725 {
1726         // FIXME the class should provide the numerical/
1727         // authoryear choice
1728         if (getTextClass().provides("natbib")
1729             && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1730                 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1731         return cite_engine_;
1732 }
1733
1734
1735 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1736 {
1737         cite_engine_ = cite_engine;
1738 }
1739
1740 } // namespace lyx