]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
BufferParams.cpp: make Lithuanian documents compilable, fixes http://bugzilla.lyx...
[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 "LayoutFile.h"
22 #include "BranchList.h"
23 #include "buffer_funcs.h"
24 #include "Bullet.h"
25 #include "Color.h"
26 #include "Encoding.h"
27 #include "Language.h"
28 #include "LaTeXFeatures.h"
29 #include "ModuleList.h"
30 #include "Font.h"
31 #include "Lexer.h"
32 #include "LyXRC.h"
33 #include "OutputParams.h"
34 #include "Spacing.h"
35 #include "TexRow.h"
36 #include "VSpace.h"
37 #include "PDFOptions.h"
38
39 #include "frontends/alert.h"
40
41 #include "insets/InsetListingsParams.h"
42
43 #include "support/convert.h"
44 #include "support/debug.h"
45 #include "support/docstream.h"
46 #include "support/FileName.h"
47 #include "support/filetools.h"
48 #include "support/gettext.h"
49 #include "support/Messages.h"
50 #include "support/Translator.h"
51 #include "support/lstrings.h"
52
53 #include <algorithm>
54 #include <sstream>
55
56 using namespace std;
57 using namespace lyx::support;
58
59
60 static char const * const string_paragraph_separation[] = {
61         "indent", "skip", ""
62 };
63
64
65 static char const * const string_quotes_language[] = {
66         "english", "swedish", "german", "polish", "french", "danish", ""
67 };
68
69
70 static char const * const string_papersize[] = {
71         "default", "custom", "letterpaper", "legalpaper", "executivepaper",
72         "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
73 };
74
75
76 static char const * const string_orientation[] = {
77         "portrait", "landscape", ""
78 };
79
80
81 static char const * const string_footnotekinds[] = {
82         "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
83 };
84
85
86 static char const * const tex_graphics[] = {
87         "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
88         "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
89         "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
90         "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
91         "xetex", "none", ""
92 };
93
94
95 namespace lyx {
96
97 // Local translators
98 namespace {
99
100 // Paragraph separation
101 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
102
103
104 ParSepTranslator const init_parseptranslator()
105 {
106         ParSepTranslator translator
107                 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
108         translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
109         return translator;
110 }
111
112
113 ParSepTranslator const & parseptranslator()
114 {
115         static ParSepTranslator translator = init_parseptranslator();
116         return translator;
117 }
118
119
120 // Quotes language
121 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
122
123
124 QuotesLangTranslator const init_quoteslangtranslator()
125 {
126         QuotesLangTranslator translator
127                 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
128         translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
129         translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
130         translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
131         translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
132         translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
133         return translator;
134 }
135
136
137 QuotesLangTranslator const & quoteslangtranslator()
138 {
139         static QuotesLangTranslator translator = init_quoteslangtranslator();
140         return translator;
141 }
142
143
144 // Paper size
145 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
146
147
148 static PaperSizeTranslator initPaperSizeTranslator()
149 {
150         PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
151         translator.addPair(string_papersize[1], PAPER_CUSTOM);
152         translator.addPair(string_papersize[2], PAPER_USLETTER);
153         translator.addPair(string_papersize[3], PAPER_USLEGAL);
154         translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
155         translator.addPair(string_papersize[5], PAPER_A3);
156         translator.addPair(string_papersize[6], PAPER_A4);
157         translator.addPair(string_papersize[7], PAPER_A5);
158         translator.addPair(string_papersize[8], PAPER_B3);
159         translator.addPair(string_papersize[9], PAPER_B4);
160         translator.addPair(string_papersize[10], PAPER_B5);
161         return translator;
162 }
163
164
165 PaperSizeTranslator const & papersizetranslator()
166 {
167         static PaperSizeTranslator translator = initPaperSizeTranslator();
168         return translator;
169 }
170
171
172 // Paper orientation
173 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
174
175
176 PaperOrientationTranslator const init_paperorientationtranslator()
177 {
178         PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
179         translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
180         return translator;
181 }
182
183
184 PaperOrientationTranslator const & paperorientationtranslator()
185 {
186         static PaperOrientationTranslator translator = init_paperorientationtranslator();
187         return translator;
188 }
189
190
191 // Page sides
192 typedef Translator<int, PageSides> SidesTranslator;
193
194
195 SidesTranslator const init_sidestranslator()
196 {
197         SidesTranslator translator(1, OneSide);
198         translator.addPair(2, TwoSides);
199         return translator;
200 }
201
202
203 SidesTranslator const & sidestranslator()
204 {
205         static SidesTranslator translator = init_sidestranslator();
206         return translator;
207 }
208
209
210 // LaTeX packages
211 typedef Translator<int, BufferParams::Package> PackageTranslator;
212
213
214 PackageTranslator const init_packagetranslator()
215 {
216         PackageTranslator translator(0, BufferParams::package_off);
217         translator.addPair(1, BufferParams::package_auto);
218         translator.addPair(2, BufferParams::package_on);
219         return translator;
220 }
221
222
223 PackageTranslator const & packagetranslator()
224 {
225         static PackageTranslator translator = init_packagetranslator();
226         return translator;
227 }
228
229
230 // Cite engine
231 typedef Translator<string, CiteEngine> CiteEngineTranslator;
232
233
234 CiteEngineTranslator const init_citeenginetranslator()
235 {
236         CiteEngineTranslator translator("basic", ENGINE_BASIC);
237         translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
238         translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
239         translator.addPair("jurabib", ENGINE_JURABIB);
240         return translator;
241 }
242
243
244 CiteEngineTranslator const & citeenginetranslator()
245 {
246         static CiteEngineTranslator translator = init_citeenginetranslator();
247         return translator;
248 }
249
250
251 // Spacing
252 typedef Translator<string, Spacing::Space> SpaceTranslator;
253
254
255 SpaceTranslator const init_spacetranslator()
256 {
257         SpaceTranslator translator("default", Spacing::Default);
258         translator.addPair("single", Spacing::Single);
259         translator.addPair("onehalf", Spacing::Onehalf);
260         translator.addPair("double", Spacing::Double);
261         translator.addPair("other", Spacing::Other);
262         return translator;
263 }
264
265
266 SpaceTranslator const & spacetranslator()
267 {
268         static SpaceTranslator translator = init_spacetranslator();
269         return translator;
270 }
271
272
273 } // anon namespace
274
275
276 class BufferParams::Impl
277 {
278 public:
279         Impl();
280
281         AuthorList authorlist;
282         BranchList branchlist;
283         Bullet temp_bullets[4];
284         Bullet user_defined_bullets[4];
285         Spacing spacing;
286         /** This is the amount of space used for paragraph_separation "skip",
287          * and for detached paragraphs in "indented" documents.
288          */
289         VSpace defskip;
290         PDFOptions pdfoptions;
291         LayoutFileIndex baseClass_;
292 };
293
294
295 BufferParams::Impl::Impl()
296         : defskip(VSpace::MEDSKIP), baseClass_(string(""))
297 {
298         // set initial author
299         // FIXME UNICODE
300         authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
301 }
302
303
304 BufferParams::Impl *
305 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
306 {
307         LASSERT(ptr, /**/);
308
309         return new BufferParams::Impl(*ptr);
310 }
311
312
313 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
314 {
315         delete ptr;
316 }
317
318
319 BufferParams::BufferParams()
320         : pimpl_(new Impl)
321 {
322         setBaseClass(defaultBaseclass());
323         makeDocumentClass();
324         paragraph_separation = ParagraphIndentSeparation;
325         quotes_language = InsetQuotes::EnglishQuotes;
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_ = 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 = OneSide;
352         columns = 1;
353         listings_params = string();
354         pagestyle = "default";
355         compressed = false;
356         for (int iter = 0; iter < 4; ++iter) {
357                 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
358                 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
359         }
360 }
361
362
363 docstring BufferParams::B_(string const & l10n) const
364 {
365         LASSERT(language, /**/);
366         return getMessages(language->code()).get(l10n);
367 }
368
369
370 AuthorList & BufferParams::authors()
371 {
372         return pimpl_->authorlist;
373 }
374
375
376 AuthorList const & BufferParams::authors() const
377 {
378         return pimpl_->authorlist;
379 }
380
381
382 BranchList & BufferParams::branchlist()
383 {
384         return pimpl_->branchlist;
385 }
386
387
388 BranchList const & BufferParams::branchlist() const
389 {
390         return pimpl_->branchlist;
391 }
392
393
394 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
395 {
396         LASSERT(index < 4, /**/);
397         return pimpl_->temp_bullets[index];
398 }
399
400
401 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
402 {
403         LASSERT(index < 4, /**/);
404         return pimpl_->temp_bullets[index];
405 }
406
407
408 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
409 {
410         LASSERT(index < 4, /**/);
411         return pimpl_->user_defined_bullets[index];
412 }
413
414
415 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
416 {
417         LASSERT(index < 4, /**/);
418         return pimpl_->user_defined_bullets[index];
419 }
420
421
422 Spacing & BufferParams::spacing()
423 {
424         return pimpl_->spacing;
425 }
426
427
428 Spacing const & BufferParams::spacing() const
429 {
430         return pimpl_->spacing;
431 }
432
433
434 PDFOptions & BufferParams::pdfoptions()
435 {
436         return pimpl_->pdfoptions;
437 }
438
439
440 PDFOptions const & BufferParams::pdfoptions() const
441 {
442         return pimpl_->pdfoptions;
443 }
444
445
446 VSpace const & BufferParams::getDefSkip() const
447 {
448         return pimpl_->defskip;
449 }
450
451
452 void BufferParams::setDefSkip(VSpace const & vs)
453 {
454         pimpl_->defskip = vs;
455 }
456
457
458 string BufferParams::readToken(Lexer & lex, string const & token,
459         FileName const & filepath)
460 {
461         if (token == "\\textclass") {
462                 lex.next();
463                 string const classname = lex.getString();
464                 // if there exists a local layout file, ignore the system one
465                 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
466                 string tcp;
467                 LayoutFileList & bcl = LayoutFileList::get();
468                 if (tcp.empty() && !filepath.empty())
469                         tcp = bcl.addLocalLayout(classname, filepath.absFilename());
470                 if (!tcp.empty())
471                         setBaseClass(tcp);
472                 else
473                         setBaseClass(classname);
474                 // We assume that a tex class exists for local or unknown layouts so this warning
475                 // will only be given for system layouts.
476                 if (!baseClass()->isTeXClassAvailable()) {
477                         docstring const msg =
478                                 bformat(_("The layout file requested by this document,\n"
479                                                  "%1$s.layout,\n"
480                                                  "is not usable. This is probably because a LaTeX\n"
481                                                  "class or style file required by it is not\n"
482                                                  "available. See the Customization documentation\n"
483                                                  "for more information.\n"), from_utf8(classname));
484                         frontend::Alert::warning(_("Document class not available"),
485                                        msg + _("LyX will not be able to produce output."));
486                 } 
487         } else if (token == "\\begin_preamble") {
488                 readPreamble(lex);
489         } else if (token == "\\begin_local_layout") {
490                 readLocalLayout(lex);
491         } else if (token == "\\begin_modules") {
492                 readModules(lex);
493         } else if (token == "\\begin_removed_modules") {
494                 readRemovedModules(lex);
495         } else if (token == "\\options") {
496                 lex.eatLine();
497                 options = lex.getString();
498         } else if (token == "\\master") {
499                 lex.eatLine();
500                 master = lex.getString();
501         } else if (token == "\\language") {
502                 readLanguage(lex);
503         } else if (token == "\\inputencoding") {
504                 lex >> inputenc;
505         } else if (token == "\\graphics") {
506                 readGraphicsDriver(lex);
507         } else if (token == "\\font_roman") {
508                 lex >> fontsRoman;
509         } else if (token == "\\font_sans") {
510                 lex >> fontsSans;
511         } else if (token == "\\font_typewriter") {
512                 lex >> fontsTypewriter;
513         } else if (token == "\\font_default_family") {
514                 lex >> fontsDefaultFamily;
515         } else if (token == "\\font_sc") {
516                 lex >> fontsSC;
517         } else if (token == "\\font_osf") {
518                 lex >> fontsOSF;
519         } else if (token == "\\font_sf_scale") {
520                 lex >> fontsSansScale;
521         } else if (token == "\\font_tt_scale") {
522                 lex >> fontsTypewriterScale;
523         } else if (token == "\\font_cjk") {
524                 lex >> fontsCJK;
525         } else if (token == "\\paragraph_separation") {
526                 string parsep;
527                 lex >> parsep;
528                 paragraph_separation = parseptranslator().find(parsep);
529         } else if (token == "\\defskip") {
530                 lex.next();
531                 string defskip = lex.getString();
532                 if (defskip == "defskip")
533                         // this is invalid
534                         defskip = "medskip";
535                 pimpl_->defskip = VSpace(defskip);
536         } else if (token == "\\quotes_language") {
537                 string quotes_lang;
538                 lex >> quotes_lang;
539                 quotes_language = quoteslangtranslator().find(quotes_lang);
540         } else if (token == "\\papersize") {
541                 string ppsize;
542                 lex >> ppsize;
543                 papersize = papersizetranslator().find(ppsize);
544         } else if (token == "\\use_geometry") {
545                 lex >> use_geometry;
546         } else if (token == "\\use_amsmath") {
547                 int use_ams;
548                 lex >> use_ams;
549                 use_amsmath = packagetranslator().find(use_ams);
550         } else if (token == "\\use_esint") {
551                 int useesint;
552                 lex >> useesint;
553                 use_esint = packagetranslator().find(useesint);
554         } else if (token == "\\cite_engine") {
555                 string engine;
556                 lex >> engine;
557                 cite_engine_ = citeenginetranslator().find(engine);
558         } else if (token == "\\use_bibtopic") {
559                 lex >> use_bibtopic;
560         } else if (token == "\\tracking_changes") {
561                 lex >> trackChanges;
562         } else if (token == "\\output_changes") {
563                 lex >> outputChanges;
564         } else if (token == "\\branch") {
565                 lex.next();
566                 docstring branch = lex.getDocString();
567                 branchlist().add(branch);
568                 while (true) {
569                         lex.next();
570                         string const tok = lex.getString();
571                         if (tok == "\\end_branch")
572                                 break;
573                         Branch * branch_ptr = branchlist().find(branch);
574                         if (tok == "\\selected") {
575                                 lex.next();
576                                 if (branch_ptr)
577                                         branch_ptr->setSelected(lex.getInteger());
578                         }
579                         // not yet operational
580                         if (tok == "\\color") {
581                                 lex.eatLine();
582                                 string color = lex.getString();
583                                 if (branch_ptr)
584                                         branch_ptr->setColor(color);
585                                 // Update also the Color table:
586                                 if (color == "none")
587                                         color = lcolor.getX11Name(Color_background);
588                                 // FIXME UNICODE
589                                 lcolor.setColor(to_utf8(branch), color);
590
591                         }
592                 }
593         } else if (token == "\\author") {
594                 lex.eatLine();
595                 istringstream ss(lex.getString());
596                 Author a;
597                 ss >> a;
598                 author_map.push_back(pimpl_->authorlist.record(a));
599         } else if (token == "\\paperorientation") {
600                 string orient;
601                 lex >> orient;
602                 orientation = paperorientationtranslator().find(orient);
603         } else if (token == "\\paperwidth") {
604                 lex >> paperwidth;
605         } else if (token == "\\paperheight") {
606                 lex >> paperheight;
607         } else if (token == "\\leftmargin") {
608                 lex >> leftmargin;
609         } else if (token == "\\topmargin") {
610                 lex >> topmargin;
611         } else if (token == "\\rightmargin") {
612                 lex >> rightmargin;
613         } else if (token == "\\bottommargin") {
614                 lex >> bottommargin;
615         } else if (token == "\\headheight") {
616                 lex >> headheight;
617         } else if (token == "\\headsep") {
618                 lex >> headsep;
619         } else if (token == "\\footskip") {
620                 lex >> footskip;
621         } else if (token == "\\columnsep") {
622                 lex >> columnsep;
623         } else if (token == "\\paperfontsize") {
624                 lex >> fontsize;
625         } else if (token == "\\papercolumns") {
626                 lex >> columns;
627         } else if (token == "\\listings_params") {
628                 string par;
629                 lex >> par;
630                 listings_params = InsetListingsParams(par).params();
631         } else if (token == "\\papersides") {
632                 int psides;
633                 lex >> psides;
634                 sides = sidestranslator().find(psides);
635         } else if (token == "\\paperpagestyle") {
636                 lex >> pagestyle;
637         } else if (token == "\\bullet") {
638                 readBullets(lex);
639         } else if (token == "\\bulletLaTeX") {
640                 readBulletsLaTeX(lex);
641         } else if (token == "\\secnumdepth") {
642                 lex >> secnumdepth;
643         } else if (token == "\\tocdepth") {
644                 lex >> tocdepth;
645         } else if (token == "\\spacing") {
646                 string nspacing;
647                 lex >> nspacing;
648                 string tmp_val;
649                 if (nspacing == "other") {
650                         lex >> tmp_val;
651                 }
652                 spacing().set(spacetranslator().find(nspacing), tmp_val);
653         } else if (token == "\\float_placement") {
654                 lex >> float_placement;
655
656         } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
657                 string toktmp = pdfoptions().readToken(lex, token);
658                 if (!toktmp.empty()) {
659                         lyxerr << "PDFOptions::readToken(): Unknown token: " <<
660                                 toktmp << endl;
661                         return toktmp;
662                 }
663         } else {
664                 lyxerr << "BufferParams::readToken(): Unknown token: " << 
665                         token << endl;
666                 return token;
667         }
668
669         return string();
670 }
671
672
673 void BufferParams::writeFile(ostream & os) const
674 {
675         // The top of the file is written by the buffer.
676         // Prints out the buffer info into the .lyx file given by file
677
678         // the textclass
679         os << "\\textclass " << baseClass()->name() << '\n';
680
681         // then the preamble
682         if (!preamble.empty()) {
683                 // remove '\n' from the end of preamble
684                 string const tmppreamble = rtrim(preamble, "\n");
685                 os << "\\begin_preamble\n"
686                    << tmppreamble
687                    << "\n\\end_preamble\n";
688         }
689
690         // the options
691         if (!options.empty()) {
692                 os << "\\options " << options << '\n';
693         }
694
695         // the master document
696         if (!master.empty()) {
697                 os << "\\master " << master << '\n';
698         }
699         
700         // removed modules
701         if (!removedModules_.empty()) {
702                 os << "\\begin_removed_modules" << '\n';
703                 set<string>::const_iterator it = removedModules_.begin();
704                 set<string>::const_iterator en = removedModules_.end();
705                 for (; it != en; it++)
706                         os << *it << '\n';
707                 os << "\\end_removed_modules" << '\n';
708         }
709
710         // the modules
711         if (!layoutModules_.empty()) {
712                 os << "\\begin_modules" << '\n';
713                 LayoutModuleList::const_iterator it = layoutModules_.begin();
714                 LayoutModuleList::const_iterator en = layoutModules_.end();
715                 for (; it != en; it++)
716                         os << *it << '\n';
717                 os << "\\end_modules" << '\n';
718         }
719         
720         // local layout information
721         if (!local_layout.empty()) {
722                 // remove '\n' from the end 
723                 string const tmplocal = rtrim(local_layout, "\n");
724                 os << "\\begin_local_layout\n"
725                    << tmplocal
726                    << "\n\\end_local_layout\n";
727         }
728
729         // then the text parameters
730         if (language != ignore_language)
731                 os << "\\language " << language->lang() << '\n';
732         os << "\\inputencoding " << inputenc
733            << "\n\\font_roman " << fontsRoman
734            << "\n\\font_sans " << fontsSans
735            << "\n\\font_typewriter " << fontsTypewriter
736            << "\n\\font_default_family " << fontsDefaultFamily
737            << "\n\\font_sc " << convert<string>(fontsSC)
738            << "\n\\font_osf " << convert<string>(fontsOSF)
739            << "\n\\font_sf_scale " << fontsSansScale
740            << "\n\\font_tt_scale " << fontsTypewriterScale
741            << '\n';
742         if (!fontsCJK.empty()) {
743                 os << "\\font_cjk " << fontsCJK << '\n';
744         }
745         os << "\n\\graphics " << graphicsDriver << '\n';
746
747         if (!float_placement.empty()) {
748                 os << "\\float_placement " << float_placement << '\n';
749         }
750         os << "\\paperfontsize " << fontsize << '\n';
751
752         spacing().writeFile(os);
753         pdfoptions().writeFile(os);
754
755         os << "\\papersize " << string_papersize[papersize]
756            << "\n\\use_geometry " << convert<string>(use_geometry)
757            << "\n\\use_amsmath " << use_amsmath
758            << "\n\\use_esint " << use_esint
759            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
760            << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
761            << "\n\\paperorientation " << string_orientation[orientation]
762            << '\n';
763
764         BranchList::const_iterator it = branchlist().begin();
765         BranchList::const_iterator end = branchlist().end();
766         for (; it != end; ++it) {
767                 os << "\\branch " << to_utf8(it->branch())
768                    << "\n\\selected " << it->isSelected()
769                    << "\n\\color " << lyx::X11hexname(it->color())
770                    << "\n\\end_branch"
771                    << "\n";
772         }
773
774         if (!paperwidth.empty())
775                 os << "\\paperwidth "
776                    << VSpace(paperwidth).asLyXCommand() << '\n';
777         if (!paperheight.empty())
778                 os << "\\paperheight "
779                    << VSpace(paperheight).asLyXCommand() << '\n';
780         if (!leftmargin.empty())
781                 os << "\\leftmargin "
782                    << VSpace(leftmargin).asLyXCommand() << '\n';
783         if (!topmargin.empty())
784                 os << "\\topmargin "
785                    << VSpace(topmargin).asLyXCommand() << '\n';
786         if (!rightmargin.empty())
787                 os << "\\rightmargin "
788                    << VSpace(rightmargin).asLyXCommand() << '\n';
789         if (!bottommargin.empty())
790                 os << "\\bottommargin "
791                    << VSpace(bottommargin).asLyXCommand() << '\n';
792         if (!headheight.empty())
793                 os << "\\headheight "
794                    << VSpace(headheight).asLyXCommand() << '\n';
795         if (!headsep.empty())
796                 os << "\\headsep "
797                    << VSpace(headsep).asLyXCommand() << '\n';
798         if (!footskip.empty())
799                 os << "\\footskip "
800                    << VSpace(footskip).asLyXCommand() << '\n';
801         if (!columnsep.empty())
802                 os << "\\columnsep " 
803                          << VSpace(columnsep).asLyXCommand() << '\n';
804         os << "\\secnumdepth " << secnumdepth
805            << "\n\\tocdepth " << tocdepth
806            << "\n\\paragraph_separation "
807            << string_paragraph_separation[paragraph_separation]
808            << "\n\\defskip " << getDefSkip().asLyXCommand()
809            << "\n\\quotes_language "
810            << string_quotes_language[quotes_language]
811            << "\n\\papercolumns " << columns
812            << "\n\\papersides " << sides
813            << "\n\\paperpagestyle " << pagestyle << '\n';
814         if (!listings_params.empty())
815                 os << "\\listings_params \"" <<
816                         InsetListingsParams(listings_params).encodedString() << "\"\n";
817         for (int i = 0; i < 4; ++i) {
818                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
819                         if (user_defined_bullet(i).getFont() != -1) {
820                                 os << "\\bullet " << i << " "
821                                    << user_defined_bullet(i).getFont() << " "
822                                    << user_defined_bullet(i).getCharacter() << " "
823                                    << user_defined_bullet(i).getSize() << "\n";
824                         }
825                         else {
826                                 // FIXME UNICODE
827                                 os << "\\bulletLaTeX " << i << " \""
828                                    << lyx::to_ascii(user_defined_bullet(i).getText())
829                                    << "\"\n";
830                         }
831                 }
832         }
833
834         os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
835         os << "\\output_changes " << convert<string>(outputChanges) << "\n";
836
837         AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
838         AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
839         for (; a_it != a_end; ++a_it) {
840                 if (a_it->second.used())
841                         os << "\\author " << a_it->second << "\n";
842                 else
843                         os << "\\author " << Author() << "\n";
844         }
845 }
846
847
848 void BufferParams::validate(LaTeXFeatures & features) const
849 {
850         features.require(documentClass().requires());
851
852         if (outputChanges) {
853                 bool dvipost    = LaTeXFeatures::isAvailable("dvipost");
854                 bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
855                                   LaTeXFeatures::isAvailable("xcolor");
856
857                 switch (features.runparams().flavor) {
858                 case OutputParams::LATEX:
859                         if (dvipost) {
860                                 features.require("ct-dvipost");
861                                 features.require("dvipost");
862                         } else if (xcolorsoul) {
863                                 features.require("ct-xcolor-soul");
864                                 features.require("soul");
865                                 features.require("xcolor");
866                         } else {
867                                 features.require("ct-none");
868                         }
869                         break;
870                 case OutputParams::PDFLATEX:
871                         if (xcolorsoul) {
872                                 features.require("ct-xcolor-soul");
873                                 features.require("soul");
874                                 features.require("xcolor");
875                                 // improves color handling in PDF output
876                                 features.require("pdfcolmk"); 
877                         } else {
878                                 features.require("ct-none");
879                         }
880                         break;
881                 default:
882                         break;
883                 }
884         }
885
886         // Floats with 'Here definitely' as default setting.
887         if (float_placement.find('H') != string::npos)
888                 features.require("float");
889
890         // AMS Style is at document level
891         if (use_amsmath == package_on
892             || documentClass().provides("amsmath"))
893                 features.require("amsmath");
894         if (use_esint == package_on)
895                 features.require("esint");
896
897         // Document-level line spacing
898         if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
899                 features.require("setspace");
900
901         // the bullet shapes are buffer level not paragraph level
902         // so they are tested here
903         for (int i = 0; i < 4; ++i) {
904                 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) 
905                         continue;
906                 int const font = user_defined_bullet(i).getFont();
907                 if (font == 0) {
908                         int const c = user_defined_bullet(i).getCharacter();
909                         if (c == 16
910                             || c == 17
911                             || c == 25
912                             || c == 26
913                             || c == 31) {
914                                 features.require("latexsym");
915                         }
916                 } else if (font == 1) {
917                         features.require("amssymb");
918                 } else if (font >= 2 && font <= 5) {
919                         features.require("pifont");
920                 }
921         }
922
923         if (pdfoptions().use_hyperref) {
924                 features.require("hyperref");
925                 // due to interferences with babel and hyperref, the color package has to
926                 // be loaded after hyperref when hyperref is used with the colorlinks
927                 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
928                 if (pdfoptions().colorlinks)
929                         features.require("color");
930         }
931
932         if (language->lang() == "vietnamese")
933                 features.require("vietnamese");
934         else if (language->lang() == "japanese")
935                 features.require("japanese");
936 }
937
938
939 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
940                               TexRow & texrow) const
941 {
942         os << "\\documentclass";
943
944         DocumentClass const & tclass = documentClass();
945
946         ostringstream clsoptions; // the document class options.
947
948         if (tokenPos(tclass.opt_fontsize(),
949                      '|', fontsize) >= 0) {
950                 // only write if existing in list (and not default)
951                 clsoptions << fontsize << "pt,";
952         }
953
954         // custom, A3, B3 and B4 paper sizes need geometry
955         bool nonstandard_papersize = papersize == PAPER_B3
956                 || papersize == PAPER_B4
957                 || papersize == PAPER_A3
958                 || papersize == PAPER_CUSTOM;
959
960         if (!use_geometry) {
961                 switch (papersize) {
962                 case PAPER_A4:
963                         clsoptions << "a4paper,";
964                         break;
965                 case PAPER_USLETTER:
966                         clsoptions << "letterpaper,";
967                         break;
968                 case PAPER_A5:
969                         clsoptions << "a5paper,";
970                         break;
971                 case PAPER_B5:
972                         clsoptions << "b5paper,";
973                         break;
974                 case PAPER_USEXECUTIVE:
975                         clsoptions << "executivepaper,";
976                         break;
977                 case PAPER_USLEGAL:
978                         clsoptions << "legalpaper,";
979                         break;
980                 case PAPER_DEFAULT:
981                 case PAPER_A3:
982                 case PAPER_B3:
983                 case PAPER_B4:
984                 case PAPER_CUSTOM:
985                         break;
986                 }
987         }
988
989         // if needed
990         if (sides != tclass.sides()) {
991                 switch (sides) {
992                 case OneSide:
993                         clsoptions << "oneside,";
994                         break;
995                 case TwoSides:
996                         clsoptions << "twoside,";
997                         break;
998                 }
999         }
1000
1001         // if needed
1002         if (columns != tclass.columns()) {
1003                 if (columns == 2)
1004                         clsoptions << "twocolumn,";
1005                 else
1006                         clsoptions << "onecolumn,";
1007         }
1008
1009         if (!use_geometry
1010             && orientation == ORIENTATION_LANDSCAPE)
1011                 clsoptions << "landscape,";
1012
1013         // language should be a parameter to \documentclass
1014         if (language->babel() == "hebrew"
1015             && default_language->babel() != "hebrew")
1016                 // This seems necessary
1017                 features.useLanguage(default_language);
1018
1019         ostringstream language_options;
1020         bool const use_babel = features.useBabel();
1021         if (use_babel) {
1022                 language_options << features.getLanguages();
1023                 if (!language->babel().empty()) {
1024                         if (!language_options.str().empty())
1025                                 language_options << ',';
1026                         language_options << language->babel();
1027                 }
1028                 // if Vietnamese is used, babel must directly be loaded
1029                 // with language options, not in the class options, see
1030                 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1031                 size_t viet = language_options.str().find("vietnam");
1032                 // viet = string::npos when not found
1033                 // if Japanese is used, babel must directly be loaded
1034                 // with language options, not in the class options, see
1035                 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1036                 size_t japan = language_options.str().find("japanese");
1037                 // japan = string::npos when not found
1038                 // if Lithuanian is used, babel must directly be loaded
1039                 // with language options, not in the class options, see
1040                 // http://bugzilla.lyx.org/show_bug.cgi?id=5323
1041                 size_t lithu = language_options.str().find("lithuanian");
1042                 // lithu = string::npos when not found
1043                 if (lyxrc.language_global_options
1044                         && !language_options.str().empty()
1045                         && viet == string::npos && japan == string::npos
1046                         && lithu == string::npos)
1047                         clsoptions << language_options.str() << ',';
1048         }
1049
1050         // the user-defined options
1051         if (!options.empty()) {
1052                 clsoptions << options << ',';
1053         }
1054
1055         string strOptions(clsoptions.str());
1056         if (!strOptions.empty()) {
1057                 strOptions = rtrim(strOptions, ",");
1058                 // FIXME UNICODE
1059                 os << '[' << from_utf8(strOptions) << ']';
1060         }
1061
1062         os << '{' << from_ascii(tclass.latexname()) << "}\n";
1063         texrow.newline();
1064         // end of \documentclass defs
1065
1066         // font selection must be done before loading fontenc.sty
1067         string const fonts =
1068                 loadFonts(fontsRoman, fontsSans,
1069                           fontsTypewriter, fontsSC, fontsOSF,
1070                           fontsSansScale, fontsTypewriterScale);
1071         if (!fonts.empty()) {
1072                 os << from_ascii(fonts);
1073                 texrow.newline();
1074         }
1075         if (fontsDefaultFamily != "default")
1076                 os << "\\renewcommand{\\familydefault}{\\"
1077                    << from_ascii(fontsDefaultFamily) << "}\n";
1078
1079         // set font encoding
1080         // this one is not per buffer
1081         // for arabic_arabi and farsi we also need to load the LAE and
1082         // LFE encoding
1083         if (lyxrc.fontenc != "default" && language->lang() != "japanese") {
1084                 if (language->lang() == "arabic_arabi"
1085                     || language->lang() == "farsi") {
1086                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1087                            << ",LFE,LAE]{fontenc}\n";
1088                         texrow.newline();
1089                 } else {
1090                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1091                            << "]{fontenc}\n";
1092                         texrow.newline();
1093                 }
1094         }
1095
1096         // handle inputenc etc.
1097         writeEncodingPreamble(os, features, texrow);
1098
1099         if (!listings_params.empty() || features.isRequired("listings")) {
1100                 os << "\\usepackage{listings}\n";
1101                 texrow.newline();
1102         }
1103         if (!listings_params.empty()) {
1104                 os << "\\lstset{";
1105                 // do not test validity because listings_params is 
1106                 // supposed to be valid
1107                 string par =
1108                         InsetListingsParams(listings_params).separatedParams(true);
1109                 // we can't support all packages, but we should load the color package
1110                 if (par.find("\\color", 0) != string::npos)
1111                         features.require("color");
1112                 os << from_utf8(par);
1113                 // count the number of newlines
1114                 for (size_t i = 0; i < par.size(); ++i)
1115                         if (par[i] == '\n')
1116                                 texrow.newline();
1117                 os << "}\n";
1118                 texrow.newline();
1119         }
1120         if (use_geometry || nonstandard_papersize) {
1121                 os << "\\usepackage{geometry}\n";
1122                 texrow.newline();
1123                 os << "\\geometry{verbose";
1124                 if (orientation == ORIENTATION_LANDSCAPE)
1125                         os << ",landscape";
1126                 switch (papersize) {
1127                 case PAPER_CUSTOM:
1128                         if (!paperwidth.empty())
1129                                 os << ",paperwidth="
1130                                    << from_ascii(paperwidth);
1131                         if (!paperheight.empty())
1132                                 os << ",paperheight="
1133                                    << from_ascii(paperheight);
1134                         break;
1135                 case PAPER_USLETTER:
1136                         os << ",letterpaper";
1137                         break;
1138                 case PAPER_USLEGAL:
1139                         os << ",legalpaper";
1140                         break;
1141                 case PAPER_USEXECUTIVE:
1142                         os << ",executivepaper";
1143                         break;
1144                 case PAPER_A3:
1145                         os << ",a3paper";
1146                         break;
1147                 case PAPER_A4:
1148                         os << ",a4paper";
1149                         break;
1150                 case PAPER_A5:
1151                         os << ",a5paper";
1152                         break;
1153                 case PAPER_B3:
1154                         os << ",b3paper";
1155                         break;
1156                 case PAPER_B4:
1157                         os << ",b4paper";
1158                         break;
1159                 case PAPER_B5:
1160                         os << ",b5paper";
1161                         break;
1162                 default:
1163                         // default papersize ie PAPER_DEFAULT
1164                         switch (lyxrc.default_papersize) {
1165                         case PAPER_DEFAULT: // keep compiler happy
1166                         case PAPER_USLETTER:
1167                                 os << ",letterpaper";
1168                                 break;
1169                         case PAPER_USLEGAL:
1170                                 os << ",legalpaper";
1171                                 break;
1172                         case PAPER_USEXECUTIVE:
1173                                 os << ",executivepaper";
1174                                 break;
1175                         case PAPER_A3:
1176                                 os << ",a3paper";
1177                                 break;
1178                         case PAPER_A4:
1179                                 os << ",a4paper";
1180                                 break;
1181                         case PAPER_A5:
1182                                 os << ",a5paper";
1183                                 break;
1184                         case PAPER_B5:
1185                                 os << ",b5paper";
1186                                 break;
1187                         case PAPER_B3:
1188                         case PAPER_B4:
1189                         case PAPER_CUSTOM:
1190                                 break;
1191                         }
1192                 }
1193                 if (!topmargin.empty())
1194                         os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1195                 if (!bottommargin.empty())
1196                         os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1197                 if (!leftmargin.empty())
1198                         os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1199                 if (!rightmargin.empty())
1200                         os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1201                 if (!headheight.empty())
1202                         os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1203                 if (!headsep.empty())
1204                         os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1205                 if (!footskip.empty())
1206                         os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1207                 if (!columnsep.empty())
1208                         os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1209                 os << "}\n";
1210                 texrow.newline();
1211         } else if (orientation == ORIENTATION_LANDSCAPE) {
1212                 features.require("papersize");
1213         }
1214
1215         if (tokenPos(tclass.opt_pagestyle(),
1216                      '|', pagestyle) >= 0) {
1217                 if (pagestyle == "fancy") {
1218                         os << "\\usepackage{fancyhdr}\n";
1219                         texrow.newline();
1220                 }
1221                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1222                 texrow.newline();
1223         }
1224
1225         // Only if class has a ToC hierarchy
1226         if (tclass.hasTocLevels()) {
1227                 if (secnumdepth != tclass.secnumdepth()) {
1228                         os << "\\setcounter{secnumdepth}{"
1229                            << secnumdepth
1230                            << "}\n";
1231                         texrow.newline();
1232                 }
1233                 if (tocdepth != tclass.tocdepth()) {
1234                         os << "\\setcounter{tocdepth}{"
1235                            << tocdepth
1236                            << "}\n";
1237                         texrow.newline();
1238                 }
1239         }
1240
1241         if (paragraph_separation) {
1242                 switch (getDefSkip().kind()) {
1243                 case VSpace::SMALLSKIP:
1244                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1245                         break;
1246                 case VSpace::MEDSKIP:
1247                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1248                         break;
1249                 case VSpace::BIGSKIP:
1250                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1251                         break;
1252                 case VSpace::LENGTH:
1253                         os << "\\setlength{\\parskip}{"
1254                            << from_utf8(getDefSkip().length().asLatexString())
1255                            << "}\n";
1256                         break;
1257                 default: // should never happen // Then delete it.
1258                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1259                         break;
1260                 }
1261                 texrow.newline();
1262
1263                 os << "\\setlength{\\parindent}{0pt}\n";
1264                 texrow.newline();
1265         }
1266
1267         // Now insert the LyX specific LaTeX commands...
1268         docstring lyxpreamble;
1269
1270         // due to interferences with babel and hyperref, the color package has to
1271         // be loaded (when it is not already loaded) before babel when hyperref
1272         // is used with the colorlinks option, see
1273         // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1274         // we decided therefore to load color always before babel, see
1275         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1276         lyxpreamble += from_ascii(features.getColorOptions());
1277         
1278         // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1279         if (use_babel
1280                 && (features.isRequired("jurabib")
1281                         || features.isRequired("hyperref")
1282                         || features.isRequired("vietnamese")
1283                         || features.isRequired("japanese") ) ) {
1284                                 // FIXME UNICODE
1285                                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1286                                 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1287         }
1288
1289         // The optional packages;
1290         lyxpreamble += from_ascii(features.getPackages());
1291
1292         // Line spacing
1293         lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1294
1295         // PDF support.
1296         // * Hyperref manual: "Make sure it comes last of your loaded
1297         //   packages, to give it a fighting chance of not being over-written,
1298         //   since its job is to redefine many LATEX commands."
1299         // * Email from Heiko Oberdiek: "It is usually better to load babel
1300         //   before hyperref. Then hyperref has a chance to detect babel.
1301         // * Has to be loaded before the "LyX specific LaTeX commands" to
1302         //   avoid errors with algorithm floats.
1303         // use hyperref explicitely when it is required
1304         if (features.isRequired("hyperref")) {
1305                 odocstringstream oss;
1306                 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1307                 lyxpreamble += oss.str();
1308         }
1309         
1310         // Will be surrounded by \makeatletter and \makeatother when needed
1311         docstring atlyxpreamble;
1312
1313         // Some macros LyX will need
1314         docstring tmppreamble(from_ascii(features.getMacros()));
1315
1316         if (!tmppreamble.empty())
1317                 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1318                         "LyX specific LaTeX commands.\n"
1319                         + tmppreamble + '\n';
1320
1321         // the text class specific preamble
1322         tmppreamble = features.getTClassPreamble();
1323         if (!tmppreamble.empty())
1324                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1325                         "Textclass specific LaTeX commands.\n"
1326                         + tmppreamble + '\n';
1327
1328         /* the user-defined preamble */
1329         if (!preamble.empty())
1330                 // FIXME UNICODE
1331                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1332                         "User specified LaTeX commands.\n"
1333                         + from_utf8(preamble) + '\n';
1334
1335         // subfig loads internally the LaTeX package "caption". As
1336         // caption is a very popular package, users will load it in
1337         // the preamble. Therefore we must load subfig behind the
1338         // user-defined preamble and check if the caption package was
1339         // loaded or not. For the case that caption is loaded before
1340         // subfig, there is the subfig option "caption=false". This
1341         // option also works when a koma-script class is used and
1342         // koma's own caption commands are used instead of caption. We
1343         // use \PassOptionsToPackage here because the user could have
1344         // already loaded subfig in the preamble.
1345         if (features.isRequired("subfig")) {
1346                 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1347                         " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1348                         "\\usepackage{subfig}\n";
1349         }
1350
1351         // Itemize bullet settings need to be last in case the user
1352         // defines their own bullets that use a package included
1353         // in the user-defined preamble -- ARRae
1354         // Actually it has to be done much later than that
1355         // since some packages like frenchb make modifications
1356         // at \begin{document} time -- JMarc
1357         docstring bullets_def;
1358         for (int i = 0; i < 4; ++i) {
1359                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1360                         if (bullets_def.empty())
1361                                 bullets_def += "\\AtBeginDocument{\n";
1362                         bullets_def += "  \\def\\labelitemi";
1363                         switch (i) {
1364                                 // `i' is one less than the item to modify
1365                         case 0:
1366                                 break;
1367                         case 1:
1368                                 bullets_def += 'i';
1369                                 break;
1370                         case 2:
1371                                 bullets_def += "ii";
1372                                 break;
1373                         case 3:
1374                                 bullets_def += 'v';
1375                                 break;
1376                         }
1377                         bullets_def += '{' +
1378                                 user_defined_bullet(i).getText()
1379                                 + "}\n";
1380                 }
1381         }
1382
1383         if (!bullets_def.empty())
1384                 atlyxpreamble += bullets_def + "}\n\n";
1385
1386         if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1387                 lyxpreamble += "\n\\makeatletter\n"
1388                         + atlyxpreamble + "\\makeatother\n\n";
1389         else
1390                 lyxpreamble += '\n' + atlyxpreamble;
1391
1392         // We try to load babel late, in case it interferes with other packages.
1393         // Jurabib and Hyperref have to be called after babel, though.
1394         if (use_babel && !features.isRequired("jurabib")
1395             && !features.isRequired("hyperref")
1396             && !features.isRequired("vietnamese")
1397             && !features.isRequired("japanese")) {
1398                 // FIXME UNICODE
1399                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1400                 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1401         }
1402
1403         int const nlines =
1404                 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1405         for (int j = 0; j != nlines; ++j) {
1406                 texrow.newline();
1407         }
1408
1409         os << lyxpreamble;
1410         return use_babel;
1411 }
1412
1413
1414 void BufferParams::useClassDefaults()
1415 {
1416         DocumentClass const & tclass = documentClass();
1417
1418         sides = tclass.sides();
1419         columns = tclass.columns();
1420         pagestyle = tclass.pagestyle();
1421         options = tclass.options();
1422         // Only if class has a ToC hierarchy
1423         if (tclass.hasTocLevels()) {
1424                 secnumdepth = tclass.secnumdepth();
1425                 tocdepth = tclass.tocdepth();
1426         }
1427 }
1428
1429
1430 bool BufferParams::hasClassDefaults() const
1431 {
1432         DocumentClass const & tclass = documentClass();
1433
1434         return sides == tclass.sides()
1435                 && columns == tclass.columns()
1436                 && pagestyle == tclass.pagestyle()
1437                 && options == tclass.options()
1438                 && secnumdepth == tclass.secnumdepth()
1439                 && tocdepth == tclass.tocdepth();
1440 }
1441
1442
1443 DocumentClass const & BufferParams::documentClass() const
1444 {
1445         return *doc_class_;
1446 }
1447
1448
1449 DocumentClass const * BufferParams::documentClassPtr() const {
1450         return doc_class_;
1451 }
1452
1453
1454 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1455         // evil, but this function is evil
1456         doc_class_ = const_cast<DocumentClass *>(tc);
1457 }
1458
1459
1460 bool BufferParams::setBaseClass(string const & classname)
1461 {
1462         LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1463         LayoutFileList & bcl = LayoutFileList::get();
1464         if (!bcl.haveClass(classname)) {
1465                 docstring s = 
1466                         bformat(_("The document class %1$s could not be found. "
1467                                 "A default textclass with default layouts will be used. "
1468                                 "LyX might not be able to produce output unless a correct "
1469                                 "textclass is selected from the document settings dialog."),
1470                         from_utf8(classname));
1471                 frontend::Alert::error(_("Document class not found"), s);
1472                 bcl.addEmptyClass(classname);
1473         }
1474
1475         bool const success = bcl[classname].load();
1476         if (!success) { 
1477                 docstring s = 
1478                         bformat(_("The document class %1$s could not be loaded."),
1479                         from_utf8(classname));
1480                 frontend::Alert::error(_("Could not load class"), s);
1481                 return false;
1482         }
1483
1484         pimpl_->baseClass_ = classname;
1485
1486         // add any required modules not already in use
1487         set<string> const & mods = baseClass()->defaultModules();
1488         set<string>::const_iterator mit = mods.begin();
1489         set<string>::const_iterator men = mods.end();
1490         for (; mit != men; mit++) {
1491                 string const & modName = *mit;
1492                 // see if we're already in use
1493                 if (find(layoutModules_.begin(), layoutModules_.end(), modName) != 
1494                     layoutModules_.end()) {
1495                         LYXERR(Debug::TCLASS, "Default module `" << modName << 
1496                                         "' not added because already used.");
1497                         continue;
1498                 }
1499                 // make sure the user hasn't removed it
1500                 if (find(removedModules_.begin(), removedModules_.end(), modName) != 
1501                     removedModules_.end()) {
1502                         LYXERR(Debug::TCLASS, "Default module `" << modName << 
1503                                         "' not added because removed by user.");
1504                         continue;
1505                 }
1506                 // Now we want to check the list of selected modules to see if any of them
1507                 // exclude this one.
1508                 bool foundit = false;
1509                 // so iterate over the selected modules...
1510                 LayoutModuleList::const_iterator lit = layoutModules_.begin();
1511                 LayoutModuleList::const_iterator len = layoutModules_.end();
1512                 for (; lit != len; lit++) {
1513                         LyXModule * lm = moduleList[*lit];
1514                         if (!lm)
1515                                 continue;
1516                         vector<string> const & exc = lm->getExcludedModules();
1517                         // ...and see if this one excludes us.
1518                         if (find(exc.begin(), exc.end(), modName) != exc.end()) {
1519                                 foundit = true;
1520                                 LYXERR(Debug::TCLASS, "Default module `" << modName << 
1521                                                 "' not added because excluded by loaded module `" << 
1522                                                 *lit << "'.");
1523                                 break;
1524                         }
1525                 }
1526                 if (!foundit) {
1527                         LYXERR(Debug::TCLASS, "Default module `" << modName << "' added.");
1528                         layoutModules_.push_back(modName);
1529                 }
1530         }
1531         return true;
1532 }
1533
1534
1535 LayoutFile const * BufferParams::baseClass() const
1536 {
1537         if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1538                 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1539         else 
1540                 return 0;
1541 }
1542
1543
1544 LayoutFileIndex const & BufferParams::baseClassID() const
1545 {
1546         return pimpl_->baseClass_;
1547 }
1548
1549
1550 void BufferParams::makeDocumentClass()
1551 {
1552         if (!baseClass())
1553                 return;
1554
1555         doc_class_ = &(DocumentClassBundle::get().newClass(*baseClass()));
1556
1557         // FIXME It might be worth loading the children's modules here,
1558         // just as we load their bibliographies and such, instead of just 
1559         // doing a check in InsetInclude.
1560         LayoutModuleList::const_iterator it = layoutModules_.begin();
1561         for (; it != layoutModules_.end(); it++) {
1562                 string const modName = *it;
1563                 LyXModule * lm = moduleList[modName];
1564                 if (!lm) {
1565                         docstring const msg =
1566                                 bformat(_("The module %1$s has been requested by\n"
1567                                         "this document but has not been found in the list of\n"
1568                                         "available modules. If you recently installed it, you\n"
1569                                         "probably need to reconfigure LyX.\n"), from_utf8(modName));
1570                         frontend::Alert::warning(_("Module not available"),
1571                                         msg + _("Some layouts may not be available."));
1572                         LYXERR0("BufferParams::makeDocumentClass(): Module " <<
1573                                         modName << " requested but not found in module list.");
1574                         continue;
1575                 }
1576                 if (!lm->isAvailable()) {
1577                         docstring const msg =
1578                                                 bformat(_("The module %1$s requires a package that is\n"
1579                                                 "not available in your LaTeX installation. LaTeX output\n"
1580                                                 "may not be possible.\n"), from_utf8(modName));
1581                         frontend::Alert::warning(_("Package not available"), msg);
1582                 }
1583                 FileName layout_file = libFileSearch("layouts", lm->getFilename());
1584                 if (!doc_class_->read(layout_file, TextClass::MODULE)) {
1585                         docstring const msg =
1586                                 bformat(_("Error reading module %1$s\n"), from_utf8(modName));
1587                         frontend::Alert::warning(_("Read Error"), msg);
1588                 }
1589         }
1590         if (!local_layout.empty()) {
1591                 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1592                         docstring const msg = _("Error reading internal layout information");
1593                         frontend::Alert::warning(_("Read Error"), msg);
1594                 }
1595         }
1596 }
1597
1598
1599 bool BufferParams::addLayoutModule(string const & modName) 
1600 {
1601         LayoutModuleList::const_iterator it = layoutModules_.begin();
1602         LayoutModuleList::const_iterator end = layoutModules_.end();
1603         for (; it != end; it++)
1604                 if (*it == modName) 
1605                         return false;
1606         layoutModules_.push_back(modName);
1607         return true;
1608 }
1609
1610
1611 Font const BufferParams::getFont() const
1612 {
1613         FontInfo f = documentClass().defaultfont();
1614         if (fontsDefaultFamily == "rmdefault")
1615                 f.setFamily(ROMAN_FAMILY);
1616         else if (fontsDefaultFamily == "sfdefault")
1617                 f.setFamily(SANS_FAMILY);
1618         else if (fontsDefaultFamily == "ttdefault")
1619                 f.setFamily(TYPEWRITER_FAMILY);
1620         return Font(f, language);
1621 }
1622
1623
1624 void BufferParams::readPreamble(Lexer & lex)
1625 {
1626         if (lex.getString() != "\\begin_preamble")
1627                 lyxerr << "Error (BufferParams::readPreamble):"
1628                         "consistency check failed." << endl;
1629
1630         preamble = lex.getLongString("\\end_preamble");
1631 }
1632
1633
1634 void BufferParams::readLocalLayout(Lexer & lex)
1635 {
1636         if (lex.getString() != "\\begin_local_layout")
1637                 lyxerr << "Error (BufferParams::readLocalLayout):"
1638                         "consistency check failed." << endl;
1639
1640         local_layout = lex.getLongString("\\end_local_layout");
1641 }
1642
1643
1644 void BufferParams::readLanguage(Lexer & lex)
1645 {
1646         if (!lex.next()) return;
1647
1648         string const tmptok = lex.getString();
1649
1650         // check if tmptok is part of tex_babel in tex-defs.h
1651         language = languages.getLanguage(tmptok);
1652         if (!language) {
1653                 // Language tmptok was not found
1654                 language = default_language;
1655                 lyxerr << "Warning: Setting language `"
1656                        << tmptok << "' to `" << language->lang()
1657                        << "'." << endl;
1658         }
1659 }
1660
1661
1662 void BufferParams::readGraphicsDriver(Lexer & lex)
1663 {
1664         if (!lex.next()) 
1665                 return;
1666
1667         string const tmptok = lex.getString();
1668         // check if tmptok is part of tex_graphics in tex_defs.h
1669         int n = 0;
1670         while (true) {
1671                 string const test = tex_graphics[n++];
1672
1673                 if (test == tmptok) {
1674                         graphicsDriver = tmptok;
1675                         break;
1676                 }
1677                 if (test.empty()) {
1678                         lex.printError(
1679                                 "Warning: graphics driver `$$Token' not recognized!\n"
1680                                 "         Setting graphics driver to `default'.\n");
1681                         graphicsDriver = "default";
1682                         break;
1683                 }
1684         }
1685 }
1686
1687
1688 void BufferParams::readBullets(Lexer & lex)
1689 {
1690         if (!lex.next()) 
1691                 return;
1692
1693         int const index = lex.getInteger();
1694         lex.next();
1695         int temp_int = lex.getInteger();
1696         user_defined_bullet(index).setFont(temp_int);
1697         temp_bullet(index).setFont(temp_int);
1698         lex >> temp_int;
1699         user_defined_bullet(index).setCharacter(temp_int);
1700         temp_bullet(index).setCharacter(temp_int);
1701         lex >> temp_int;
1702         user_defined_bullet(index).setSize(temp_int);
1703         temp_bullet(index).setSize(temp_int);
1704 }
1705
1706
1707 void BufferParams::readBulletsLaTeX(Lexer & lex)
1708 {
1709         // The bullet class should be able to read this.
1710         if (!lex.next()) 
1711                 return;
1712         int const index = lex.getInteger();
1713         lex.next(true);
1714         docstring const temp_str = lex.getDocString();
1715
1716         user_defined_bullet(index).setText(temp_str);
1717         temp_bullet(index).setText(temp_str);
1718 }
1719
1720
1721 void BufferParams::readModules(Lexer & lex)
1722 {
1723         if (!lex.eatLine()) {
1724                 lyxerr << "Error (BufferParams::readModules):"
1725                                 "Unexpected end of input." << endl;
1726                 return;
1727         }
1728         while (true) {
1729                 string mod = lex.getString();
1730                 if (mod == "\\end_modules")
1731                         break;
1732                 addLayoutModule(mod);
1733                 lex.eatLine();
1734         }
1735 }
1736
1737
1738 void BufferParams::readRemovedModules(Lexer & lex)
1739 {
1740         if (!lex.eatLine()) {
1741                 lyxerr << "Error (BufferParams::readRemovedModules):"
1742                                 "Unexpected end of input." << endl;
1743                 return;
1744         }
1745         while (true) {
1746                 string mod = lex.getString();
1747                 if (mod == "\\end_removed_modules")
1748                         break;
1749                 removedModules_.insert(mod);
1750                 lex.eatLine();
1751         }
1752         // now we want to remove any removed modules that were previously 
1753         // added. normally, that will be because default modules were added in 
1754         // setBaseClass(), which gets called when \textclass is read at the 
1755         // start of the read.
1756         set<string>::const_iterator rit = removedModules_.begin();
1757         set<string>::const_iterator const ren = removedModules_.end();
1758         for (; rit != ren; rit++) {
1759                 LayoutModuleList::iterator const mit = layoutModules_.begin();
1760                 LayoutModuleList::iterator const men = layoutModules_.end();
1761                 LayoutModuleList::iterator found = find(mit, men, *rit);
1762                 if (found == men)
1763                         continue;
1764                 layoutModules_.erase(found);
1765         }
1766 }
1767
1768
1769 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1770 {
1771         char real_papersize = papersize;
1772         if (real_papersize == PAPER_DEFAULT)
1773                 real_papersize = lyxrc.default_papersize;
1774
1775         switch (real_papersize) {
1776         case PAPER_DEFAULT:
1777                 // could be anything, so don't guess
1778                 return string();
1779         case PAPER_CUSTOM: {
1780                 if (purpose == XDVI && !paperwidth.empty() &&
1781                     !paperheight.empty()) {
1782                         // heightxwidth<unit>
1783                         string first = paperwidth;
1784                         string second = paperheight;
1785                         if (orientation == ORIENTATION_LANDSCAPE)
1786                                 first.swap(second);
1787                         // cut off unit.
1788                         return first.erase(first.length() - 2)
1789                                 + "x" + second;
1790                 }
1791                 return string();
1792         }
1793         case PAPER_A3:
1794                 return "a3";
1795         case PAPER_A4:
1796                 return "a4";
1797         case PAPER_A5:
1798                 return "a5";
1799         case PAPER_B3:
1800                 // dvips and dvipdfm do not know this
1801                 if (purpose == DVIPS || purpose == DVIPDFM)
1802                         return string();
1803                 return "b3";
1804         case PAPER_B4:
1805                 // dvipdfm does not know this
1806                 if (purpose == DVIPDFM)
1807                         return string();
1808                 return "b4";
1809         case PAPER_B5:
1810                 // dvipdfm does not know this
1811                 if (purpose == DVIPDFM)
1812                         return string();
1813                 return "b5";
1814         case PAPER_USEXECUTIVE:
1815                 // dvipdfm does not know this
1816                 if (purpose == DVIPDFM)
1817                         return string();
1818                 return "foolscap";
1819         case PAPER_USLEGAL:
1820                 return "legal";
1821         case PAPER_USLETTER:
1822         default:
1823                 if (purpose == XDVI)
1824                         return "us";
1825                 return "letter";
1826         }
1827 }
1828
1829
1830 string const BufferParams::dvips_options() const
1831 {
1832         string result;
1833
1834         if (use_geometry
1835             && papersize == PAPER_CUSTOM
1836             && !lyxrc.print_paper_dimension_flag.empty()
1837             && !paperwidth.empty()
1838             && !paperheight.empty()) {
1839                 // using a custom papersize
1840                 result = lyxrc.print_paper_dimension_flag;
1841                 result += ' ' + paperwidth;
1842                 result += ',' + paperheight;
1843         } else {
1844                 string const paper_option = paperSizeName(DVIPS);
1845                 if (!paper_option.empty() && (paper_option != "letter" ||
1846                     orientation != ORIENTATION_LANDSCAPE)) {
1847                         // dvips won't accept -t letter -t landscape.
1848                         // In all other cases, include the paper size
1849                         // explicitly.
1850                         result = lyxrc.print_paper_flag;
1851                         result += ' ' + paper_option;
1852                 }
1853         }
1854         if (orientation == ORIENTATION_LANDSCAPE &&
1855             papersize != PAPER_CUSTOM)
1856                 result += ' ' + lyxrc.print_landscape_flag;
1857         return result;
1858 }
1859
1860
1861 string BufferParams::babelCall(string const & lang_opts) const
1862 {
1863         string lang_pack = lyxrc.language_package;
1864         if (lang_pack != "\\usepackage{babel}")
1865                 return lang_pack;
1866         // suppress the babel call when there is no babel language defined
1867         // for the document language in the lib/languages file and if no
1868         // other languages are used (lang_opts is then empty)
1869         if (lang_opts.empty())
1870                 return string();
1871         // If Vietnamese is used, babel must directly be loaded with the
1872         // language options, see
1873         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1874         size_t viet = lang_opts.find("vietnam");
1875         // viet = string::npos when not found
1876         // If Japanese is used, babel must directly be loaded with the
1877         // language options, see
1878         // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1879         size_t japan = lang_opts.find("japanese");
1880         // japan = string::npos when not found
1881         // If Lithuanian is used, babel must directly be loaded with the
1882         // language options, see
1883         // http://bugzilla.lyx.org/show_bug.cgi?id=5323
1884         size_t lithu = lang_opts.find("lithuanian");
1885         // lithu = string::npos when not found
1886         if (!lyxrc.language_global_options || viet != string::npos
1887                 || japan != string::npos || lithu != string::npos)
1888                 return "\\usepackage[" + lang_opts + "]{babel}";
1889         return lang_pack;
1890 }
1891
1892
1893 void BufferParams::writeEncodingPreamble(odocstream & os,
1894                 LaTeXFeatures & features, TexRow & texrow) const
1895 {
1896         if (inputenc == "auto") {
1897                 string const doc_encoding =
1898                         language->encoding()->latexName();
1899                 Encoding::Package const package =
1900                         language->encoding()->package();
1901
1902                 // Create a list with all the input encodings used
1903                 // in the document
1904                 set<string> encodings =
1905                         features.getEncodingSet(doc_encoding);
1906
1907                 // If the "japanese" package (i.e. pLaTeX) is used,
1908                 // inputenc must be omitted.
1909                 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1910                 if (package == Encoding::japanese)
1911                      features.require("japanese");
1912
1913                 if ((!encodings.empty() || package == Encoding::inputenc)
1914                     && !features.isRequired("japanese")) {
1915                         os << "\\usepackage[";
1916                         set<string>::const_iterator it = encodings.begin();
1917                         set<string>::const_iterator const end = encodings.end();
1918                         if (it != end) {
1919                                 os << from_ascii(*it);
1920                                 ++it;
1921                         }
1922                         for (; it != end; ++it)
1923                                 os << ',' << from_ascii(*it);
1924                         if (package == Encoding::inputenc) {
1925                                 if (!encodings.empty())
1926                                         os << ',';
1927                                 os << from_ascii(doc_encoding);
1928                         }
1929                         os << "]{inputenc}\n";
1930                         texrow.newline();
1931                 }
1932                 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1933                         os << "\\usepackage{CJK}\n";
1934                         texrow.newline();
1935                 }
1936         } else if (inputenc != "default") {
1937                 switch (encoding().package()) {
1938                 case Encoding::none:
1939                 case Encoding::japanese:
1940                         break;
1941                 case Encoding::inputenc:
1942                         // do not load inputenc if japanese is used
1943                         if (features.isRequired("japanese"))
1944                                 break;
1945                         os << "\\usepackage[" << from_ascii(inputenc)
1946                            << "]{inputenc}\n";
1947                         texrow.newline();
1948                         break;
1949                 case Encoding::CJK:
1950                         os << "\\usepackage{CJK}\n";
1951                         texrow.newline();
1952                         break;
1953                 }
1954         }
1955
1956         // The encoding "armscii8" (for Armenian) is only available when
1957         // the package "armtex" is loaded.
1958         if (language->encoding()->latexName() == "armscii8"
1959             || inputenc == "armscii8") {
1960                 os << "\\usepackage{armtex}\n";
1961                 texrow.newline();
1962         }
1963 }
1964
1965
1966 string const BufferParams::loadFonts(string const & rm,
1967                                      string const & sf, string const & tt,
1968                                      bool const & sc, bool const & osf,
1969                                      int const & sfscale, int const & ttscale) const
1970 {
1971         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1972            several packages have been replaced by others, that might not
1973            be installed on every system. We have to take care for that
1974            (see psnfss.pdf). We try to support all psnfss fonts as well
1975            as the fonts that have become de facto standard in the LaTeX
1976            world (e.g. Latin Modern). We do not support obsolete fonts
1977            (like PSLatex). In general, it should be possible to mix any
1978            rm font with any sf or tt font, respectively. (JSpitzm)
1979            TODO:
1980                 -- separate math fonts.
1981         */
1982
1983         if (rm == "default" && sf == "default" && tt == "default")
1984                 //nothing to do
1985                 return string();
1986
1987         ostringstream os;
1988
1989         // ROMAN FONTS
1990         // Computer Modern (must be explicitely selectable -- there might be classes
1991         // that define a different default font!
1992         if (rm == "cmr") {
1993                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1994                 // osf for Computer Modern needs eco.sty
1995                 if (osf)
1996                         os << "\\usepackage{eco}\n";
1997         }
1998         // Latin Modern Roman
1999         else if (rm == "lmodern")
2000                 os << "\\usepackage{lmodern}\n";
2001         // AE
2002         else if (rm == "ae") {
2003                 // not needed when using OT1 font encoding.
2004                 if (lyxrc.fontenc != "default")
2005                         os << "\\usepackage{ae,aecompl}\n";
2006         }
2007         // Times
2008         else if (rm == "times") {
2009                 // try to load the best available package
2010                 if (LaTeXFeatures::isAvailable("mathptmx"))
2011                         os << "\\usepackage{mathptmx}\n";
2012                 else if (LaTeXFeatures::isAvailable("mathptm"))
2013                         os << "\\usepackage{mathptm}\n";
2014                 else
2015                         os << "\\usepackage{times}\n";
2016         }
2017         // Palatino
2018         else if (rm == "palatino") {
2019                 // try to load the best available package
2020                 if (LaTeXFeatures::isAvailable("mathpazo")) {
2021                         os << "\\usepackage";
2022                         if (osf || sc) {
2023                                 os << '[';
2024                                 if (!osf)
2025                                         os << "sc";
2026                                 else
2027                                         // "osf" includes "sc"!
2028                                         os << "osf";
2029                                 os << ']';
2030                         }
2031                         os << "{mathpazo}\n";
2032                 }
2033                 else if (LaTeXFeatures::isAvailable("mathpple"))
2034                         os << "\\usepackage{mathpple}\n";
2035                 else
2036                         os << "\\usepackage{palatino}\n";
2037         }
2038         // Utopia
2039         else if (rm == "utopia") {
2040                 // fourier supersedes utopia.sty, but does
2041                 // not work with OT1 encoding.
2042                 if (LaTeXFeatures::isAvailable("fourier")
2043                     && lyxrc.fontenc != "default") {
2044                         os << "\\usepackage";
2045                         if (osf || sc) {
2046                                 os << '[';
2047                                 if (sc)
2048                                         os << "expert";
2049                                 if (osf && sc)
2050                                         os << ',';
2051                                 if (osf)
2052                                         os << "oldstyle";
2053                                 os << ']';
2054                         }
2055                         os << "{fourier}\n";
2056                 }
2057                 else
2058                         os << "\\usepackage{utopia}\n";
2059         }
2060         // Bera (complete fontset)
2061         else if (rm == "bera" && sf == "default" && tt == "default")
2062                 os << "\\usepackage{bera}\n";
2063         // everything else
2064         else if (rm != "default")
2065                 os << "\\usepackage" << "{" << rm << "}\n";
2066
2067         // SANS SERIF
2068         // Helvetica, Bera Sans
2069         if (sf == "helvet" || sf == "berasans") {
2070                 if (sfscale != 100)
2071                         os << "\\usepackage[scaled=" << float(sfscale) / 100
2072                            << "]{" << sf << "}\n";
2073                 else
2074                         os << "\\usepackage{" << sf << "}\n";
2075         }
2076         // Avant Garde
2077         else if (sf == "avant")
2078                 os << "\\usepackage{" << sf << "}\n";
2079         // Computer Modern, Latin Modern, CM Bright
2080         else if (sf != "default")
2081                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2082
2083         // monospaced/typewriter
2084         // Courier, LuxiMono
2085         if (tt == "luximono" || tt == "beramono") {
2086                 if (ttscale != 100)
2087                         os << "\\usepackage[scaled=" << float(ttscale) / 100
2088                            << "]{" << tt << "}\n";
2089                 else
2090                         os << "\\usepackage{" << tt << "}\n";
2091         }
2092         // Courier
2093         else if (tt == "courier" )
2094                 os << "\\usepackage{" << tt << "}\n";
2095         // Computer Modern, Latin Modern, CM Bright
2096         else if (tt != "default")
2097                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2098
2099         return os.str();
2100 }
2101
2102
2103 Encoding const & BufferParams::encoding() const
2104 {
2105         if (inputenc == "auto" || inputenc == "default")
2106                 return *language->encoding();
2107         Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2108         if (enc)
2109                 return *enc;
2110         LYXERR0("Unknown inputenc value `" << inputenc
2111                << "'. Using `auto' instead.");
2112         return *language->encoding();
2113 }
2114
2115
2116 CiteEngine BufferParams::citeEngine() const
2117 {
2118         // FIXME the class should provide the numerical/
2119         // authoryear choice
2120         if (documentClass().provides("natbib")
2121             && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2122                 return ENGINE_NATBIB_AUTHORYEAR;
2123         return cite_engine_;
2124 }
2125
2126
2127 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2128 {
2129         cite_engine_ = cite_engine;
2130 }
2131
2132 } // namespace lyx