]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
42eebeaba0768d10197807b68064f60428c24bf3
[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 "ColorSet.h"
27 #include "Encoding.h"
28 #include "HSpace.h"
29 #include "IndicesList.h"
30 #include "Language.h"
31 #include "LaTeXFeatures.h"
32 #include "ModuleList.h"
33 #include "Font.h"
34 #include "Lexer.h"
35 #include "LyXRC.h"
36 #include "OutputParams.h"
37 #include "Spacing.h"
38 #include "TexRow.h"
39 #include "VSpace.h"
40 #include "PDFOptions.h"
41
42 #include "frontends/alert.h"
43
44 #include "insets/InsetListingsParams.h"
45
46 #include "support/convert.h"
47 #include "support/debug.h"
48 #include "support/docstream.h"
49 #include "support/FileName.h"
50 #include "support/filetools.h"
51 #include "support/gettext.h"
52 #include "support/Messages.h"
53 #include "support/Translator.h"
54 #include "support/lstrings.h"
55
56 #include <algorithm>
57 #include <sstream>
58
59 using namespace std;
60 using namespace lyx::support;
61
62
63 static char const * const string_paragraph_separation[] = {
64         "indent", "skip", ""
65 };
66
67
68 static char const * const string_quotes_language[] = {
69         "english", "swedish", "german", "polish", "french", "danish", ""
70 };
71
72
73 static char const * const string_papersize[] = {
74         "default", "custom", "letterpaper", "legalpaper", "executivepaper",
75         "a0paper", "a1paper", "a2paper", "a3paper",     "a4paper", "a5paper",
76         "a6paper", "b0paper", "b1paper", "b2paper","b3paper", "b4paper",
77         "b5paper", "b6paper", "c0paper", "c1paper", "c2paper", "c3paper",
78         "c4paper", "c5paper", "c6paper", "b0j", "b1j", "b2j", "b3j", "b4j", "b5j",
79         "b6j", ""
80 };
81
82
83 static char const * const string_orientation[] = {
84         "portrait", "landscape", ""
85 };
86
87
88 static char const * const string_footnotekinds[] = {
89         "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
90 };
91
92
93 static char const * const tex_graphics[] = {
94         "default", "dvialw", "dvilaser", "dvipdf", "dvipdfm", "dvipdfmx",
95         "dvips", "dvipsone", "dvitops", "dviwin", "dviwindo", "dvi2ps", "emtex",
96         "ln", "oztex", "pctexhp", "pctexps", "pctexwin", "pctex32", "pdftex",
97         "psprint", "pubps", "tcidvi", "textures", "truetex", "vtex", "xdvi",
98         "xetex", "none", ""
99 };
100
101
102
103 namespace lyx {
104
105 // Local translators
106 namespace {
107
108 // Paragraph separation
109 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
110
111
112 ParSepTranslator const init_parseptranslator()
113 {
114         ParSepTranslator translator
115                 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
116         translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
117         return translator;
118 }
119
120
121 ParSepTranslator const & parseptranslator()
122 {
123         static ParSepTranslator translator = init_parseptranslator();
124         return translator;
125 }
126
127
128 // Quotes language
129 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
130
131
132 QuotesLangTranslator const init_quoteslangtranslator()
133 {
134         QuotesLangTranslator translator
135                 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
136         translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
137         translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
138         translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
139         translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
140         translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
141         return translator;
142 }
143
144
145 QuotesLangTranslator const & quoteslangtranslator()
146 {
147         static QuotesLangTranslator translator = init_quoteslangtranslator();
148         return translator;
149 }
150
151
152 // Paper size
153 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
154
155
156 static PaperSizeTranslator initPaperSizeTranslator()
157 {
158         PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
159         translator.addPair(string_papersize[1], PAPER_CUSTOM);
160         translator.addPair(string_papersize[2], PAPER_USLETTER);
161         translator.addPair(string_papersize[3], PAPER_USLEGAL);
162         translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
163         translator.addPair(string_papersize[5], PAPER_A0);
164         translator.addPair(string_papersize[6], PAPER_A1);
165         translator.addPair(string_papersize[7], PAPER_A2);
166         translator.addPair(string_papersize[8], PAPER_A3);
167         translator.addPair(string_papersize[9], PAPER_A4);
168         translator.addPair(string_papersize[10], PAPER_A5);
169         translator.addPair(string_papersize[11], PAPER_A6);
170         translator.addPair(string_papersize[12], PAPER_B0);
171         translator.addPair(string_papersize[13], PAPER_B1);
172         translator.addPair(string_papersize[14], PAPER_B2);
173         translator.addPair(string_papersize[15], PAPER_B3);
174         translator.addPair(string_papersize[16], PAPER_B4);
175         translator.addPair(string_papersize[17], PAPER_B5);
176         translator.addPair(string_papersize[18], PAPER_B6);
177         translator.addPair(string_papersize[19], PAPER_C0);
178         translator.addPair(string_papersize[20], PAPER_C1);
179         translator.addPair(string_papersize[21], PAPER_C2);
180         translator.addPair(string_papersize[22], PAPER_C3);
181         translator.addPair(string_papersize[23], PAPER_C4);
182         translator.addPair(string_papersize[24], PAPER_C5);
183         translator.addPair(string_papersize[25], PAPER_C6);
184         translator.addPair(string_papersize[26], PAPER_JISB0);
185         translator.addPair(string_papersize[27], PAPER_JISB1);
186         translator.addPair(string_papersize[28], PAPER_JISB2);
187         translator.addPair(string_papersize[29], PAPER_JISB3);
188         translator.addPair(string_papersize[30], PAPER_JISB4);
189         translator.addPair(string_papersize[31], PAPER_JISB5);
190         translator.addPair(string_papersize[32], PAPER_JISB6);
191         return translator;
192 }
193
194
195 PaperSizeTranslator const & papersizetranslator()
196 {
197         static PaperSizeTranslator translator = initPaperSizeTranslator();
198         return translator;
199 }
200
201
202 // Paper orientation
203 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
204
205
206 PaperOrientationTranslator const init_paperorientationtranslator()
207 {
208         PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
209         translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
210         return translator;
211 }
212
213
214 PaperOrientationTranslator const & paperorientationtranslator()
215 {
216         static PaperOrientationTranslator translator = init_paperorientationtranslator();
217         return translator;
218 }
219
220
221 // Page sides
222 typedef Translator<int, PageSides> SidesTranslator;
223
224
225 SidesTranslator const init_sidestranslator()
226 {
227         SidesTranslator translator(1, OneSide);
228         translator.addPair(2, TwoSides);
229         return translator;
230 }
231
232
233 SidesTranslator const & sidestranslator()
234 {
235         static SidesTranslator translator = init_sidestranslator();
236         return translator;
237 }
238
239
240 // LaTeX packages
241 typedef Translator<int, BufferParams::Package> PackageTranslator;
242
243
244 PackageTranslator const init_packagetranslator()
245 {
246         PackageTranslator translator(0, BufferParams::package_off);
247         translator.addPair(1, BufferParams::package_auto);
248         translator.addPair(2, BufferParams::package_on);
249         return translator;
250 }
251
252
253 PackageTranslator const & packagetranslator()
254 {
255         static PackageTranslator translator = init_packagetranslator();
256         return translator;
257 }
258
259
260 // Cite engine
261 typedef Translator<string, CiteEngine> CiteEngineTranslator;
262
263
264 CiteEngineTranslator const init_citeenginetranslator()
265 {
266         CiteEngineTranslator translator("basic", ENGINE_BASIC);
267         translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
268         translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
269         translator.addPair("jurabib", ENGINE_JURABIB);
270         return translator;
271 }
272
273
274 CiteEngineTranslator const & citeenginetranslator()
275 {
276         static CiteEngineTranslator translator = init_citeenginetranslator();
277         return translator;
278 }
279
280
281 // Spacing
282 typedef Translator<string, Spacing::Space> SpaceTranslator;
283
284
285 SpaceTranslator const init_spacetranslator()
286 {
287         SpaceTranslator translator("default", Spacing::Default);
288         translator.addPair("single", Spacing::Single);
289         translator.addPair("onehalf", Spacing::Onehalf);
290         translator.addPair("double", Spacing::Double);
291         translator.addPair("other", Spacing::Other);
292         return translator;
293 }
294
295
296 SpaceTranslator const & spacetranslator()
297 {
298         static SpaceTranslator translator = init_spacetranslator();
299         return translator;
300 }
301
302 } // anon namespace
303
304
305 class BufferParams::Impl
306 {
307 public:
308         Impl();
309
310         AuthorList authorlist;
311         BranchList branchlist;
312         Bullet temp_bullets[4];
313         Bullet user_defined_bullets[4];
314         IndicesList indiceslist;
315         Spacing spacing;
316         /** This is the amount of space used for paragraph_separation "skip",
317          * and for detached paragraphs in "indented" documents.
318          */
319         HSpace indentation;
320         VSpace defskip;
321         PDFOptions pdfoptions;
322         LayoutFileIndex baseClass_;
323 };
324
325
326 BufferParams::Impl::Impl()
327         : defskip(VSpace::MEDSKIP), baseClass_(string(""))
328 {
329         // set initial author
330         // FIXME UNICODE
331         authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
332 }
333
334
335 BufferParams::Impl *
336 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
337 {
338         LASSERT(ptr, /**/);
339
340         return new BufferParams::Impl(*ptr);
341 }
342
343
344 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
345 {
346         delete ptr;
347 }
348
349
350 BufferParams::BufferParams()
351         : pimpl_(new Impl)
352 {
353         setBaseClass(defaultBaseclass());
354         makeDocumentClass();
355         paragraph_separation = ParagraphIndentSeparation;
356         quotes_language = InsetQuotes::EnglishQuotes;
357         fontsize = "default";
358
359         /*  PaperLayout */
360         papersize = PAPER_DEFAULT;
361         orientation = ORIENTATION_PORTRAIT;
362         use_geometry = false;
363         use_amsmath = package_auto;
364         use_esint = package_auto;
365         use_mhchem = package_auto;
366         use_mathdots = package_auto;
367         cite_engine_ = ENGINE_BASIC;
368         use_bibtopic = false;
369         use_indices = false;
370         trackChanges = false;
371         outputChanges = false;
372         use_default_options = true;
373         maintain_unincluded_children = false;
374         secnumdepth = 3;
375         tocdepth = 3;
376         language = default_language;
377         fontenc = "global";
378         fonts_roman = "default";
379         fonts_sans = "default";
380         fonts_typewriter = "default";
381         fonts_default_family = "default";
382         useNonTeXFonts = false;
383         fonts_expert_sc = false;
384         fonts_old_figures = false;
385         fonts_sans_scale = 100;
386         fonts_typewriter_scale = 100;
387         inputenc = "auto";
388         graphics_driver = "default";
389         default_output_format = "default";
390         bibtex_command = "default";
391         index_command = "default";
392         sides = OneSide;
393         columns = 1;
394         listings_params = string();
395         pagestyle = "default";
396         suppress_date = false;
397         // no color is the default (white)
398         backgroundcolor = lyx::rgbFromHexName("#ffffff");
399         isbackgroundcolor = false;
400         // no color is the default (black)
401         fontcolor = lyx::rgbFromHexName("#000000");
402         isfontcolor = false;
403         // light gray is the default font color for greyed-out notes
404         notefontcolor = lyx::rgbFromHexName("#cccccc");
405         boxbgcolor = lyx::rgbFromHexName("#ff0000");
406         compressed = lyxrc.save_compressed;
407         for (int iter = 0; iter < 4; ++iter) {
408                 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
409                 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
410         }
411         // default index
412         indiceslist().addDefault(B_("Index"));
413         html_be_strict = false;
414         html_math_output = MathML;
415         html_math_img_scale = 1.0;
416
417         output_sync = false;
418         use_refstyle = true;
419 }
420
421
422 docstring BufferParams::B_(string const & l10n) const
423 {
424         LASSERT(language, /**/);
425         return getMessages(language->code()).get(l10n);
426 }
427
428
429 AuthorList & BufferParams::authors()
430 {
431         return pimpl_->authorlist;
432 }
433
434
435 AuthorList const & BufferParams::authors() const
436 {
437         return pimpl_->authorlist;
438 }
439
440
441 BranchList & BufferParams::branchlist()
442 {
443         return pimpl_->branchlist;
444 }
445
446
447 BranchList const & BufferParams::branchlist() const
448 {
449         return pimpl_->branchlist;
450 }
451
452
453 IndicesList & BufferParams::indiceslist()
454 {
455         return pimpl_->indiceslist;
456 }
457
458
459 IndicesList const & BufferParams::indiceslist() const
460 {
461         return pimpl_->indiceslist;
462 }
463
464
465 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
466 {
467         LASSERT(index < 4, /**/);
468         return pimpl_->temp_bullets[index];
469 }
470
471
472 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
473 {
474         LASSERT(index < 4, /**/);
475         return pimpl_->temp_bullets[index];
476 }
477
478
479 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
480 {
481         LASSERT(index < 4, /**/);
482         return pimpl_->user_defined_bullets[index];
483 }
484
485
486 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
487 {
488         LASSERT(index < 4, /**/);
489         return pimpl_->user_defined_bullets[index];
490 }
491
492
493 Spacing & BufferParams::spacing()
494 {
495         return pimpl_->spacing;
496 }
497
498
499 Spacing const & BufferParams::spacing() const
500 {
501         return pimpl_->spacing;
502 }
503
504
505 PDFOptions & BufferParams::pdfoptions()
506 {
507         return pimpl_->pdfoptions;
508 }
509
510
511 PDFOptions const & BufferParams::pdfoptions() const
512 {
513         return pimpl_->pdfoptions;
514 }
515
516
517 HSpace const & BufferParams::getIndentation() const
518 {
519         return pimpl_->indentation;
520 }
521
522
523 void BufferParams::setIndentation(HSpace const & indent)
524 {
525         pimpl_->indentation = indent;
526 }
527
528
529 VSpace const & BufferParams::getDefSkip() const
530 {
531         return pimpl_->defskip;
532 }
533
534
535 void BufferParams::setDefSkip(VSpace const & vs)
536 {
537         // DEFSKIP will cause an infinite loop
538         LASSERT(vs.kind() != VSpace::DEFSKIP, return);
539         pimpl_->defskip = vs;
540 }
541
542
543 string BufferParams::readToken(Lexer & lex, string const & token,
544         FileName const & filepath)
545 {
546         if (token == "\\textclass") {
547                 lex.next();
548                 string const classname = lex.getString();
549                 // if there exists a local layout file, ignore the system one
550                 // NOTE: in this case, the textclass (.cls file) is assumed to 
551                 // be available.
552                 string tcp;
553                 LayoutFileList & bcl = LayoutFileList::get();
554                 if (tcp.empty() && !filepath.empty())
555                         tcp = bcl.addLocalLayout(classname, filepath.absFileName());
556                 if (!tcp.empty())
557                         setBaseClass(tcp);
558                 else
559                         setBaseClass(classname);
560                 // We assume that a tex class exists for local or unknown 
561                 // layouts so this warning, will only be given for system layouts.
562                 if (!baseClass()->isTeXClassAvailable()) {
563                         docstring const desc = 
564                                 translateIfPossible(from_utf8(baseClass()->description()));
565                         docstring const prereqs = 
566                                 from_utf8(baseClass()->prerequisites());
567                         docstring const msg =
568                                 bformat(_("The selected document class\n"
569                                                  "\t%1$s\n"
570                                                  "requires external files that are not available.\n"
571                                                  "The document class can still be used, but the\n"
572                                                  "document cannot be compiled until the following\n"
573                                                  "prerequisites are installed:\n"
574                                                  "\t%2$s\n"
575                                                  "See section 3.1.2.2 (Class Availability) of the\n"
576                                                  "User's Guide for more information."), desc, prereqs);
577                         frontend::Alert::warning(_("Document class not available"),
578                                        msg);
579                 }
580         } else if (token == "\\begin_preamble") {
581                 readPreamble(lex);
582         } else if (token == "\\begin_local_layout") {
583                 readLocalLayout(lex);
584         } else if (token == "\\begin_modules") {
585                 readModules(lex);
586         } else if (token == "\\begin_removed_modules") {
587                 readRemovedModules(lex);
588         } else if (token == "\\begin_includeonly") {
589                 readIncludeonly(lex);
590         } else if (token == "\\maintain_unincluded_children") {
591                 lex >> maintain_unincluded_children;
592         } else if (token == "\\options") {
593                 lex.eatLine();
594                 options = lex.getString();
595         } else if (token == "\\use_default_options") {
596                 lex >> use_default_options;
597         } else if (token == "\\master") {
598                 lex.eatLine();
599                 master = lex.getString();
600         } else if (token == "\\suppress_date") {
601                 lex >> suppress_date;
602         } else if (token == "\\language") {
603                 readLanguage(lex);
604         } else if (token == "\\inputencoding") {
605                 lex >> inputenc;
606         } else if (token == "\\graphics") {
607                 readGraphicsDriver(lex);
608         } else if (token == "\\default_output_format") {
609                 lex >> default_output_format;
610         } else if (token == "\\bibtex_command") {
611                 lex.eatLine();
612                 bibtex_command = lex.getString();
613         } else if (token == "\\index_command") {
614                 lex.eatLine();
615                 index_command = lex.getString();
616         } else if (token == "\\fontencoding") {
617                 lex.eatLine();
618                 fontenc = lex.getString();
619         } else if (token == "\\font_roman") {
620                 lex.eatLine();
621                 fonts_roman = lex.getString();
622         } else if (token == "\\font_sans") {
623                 lex.eatLine();
624                 fonts_sans = lex.getString();
625         } else if (token == "\\font_typewriter") {
626                 lex.eatLine();
627                 fonts_typewriter = lex.getString();
628         } else if (token == "\\font_default_family") {
629                 lex >> fonts_default_family;
630         } else if (token == "\\use_non_tex_fonts") {
631                 lex >> useNonTeXFonts;
632         } else if (token == "\\font_sc") {
633                 lex >> fonts_expert_sc;
634         } else if (token == "\\font_osf") {
635                 lex >> fonts_old_figures;
636         } else if (token == "\\font_sf_scale") {
637                 lex >> fonts_sans_scale;
638         } else if (token == "\\font_tt_scale") {
639                 lex >> fonts_typewriter_scale;
640         } else if (token == "\\font_cjk") {
641                 lex >> fonts_cjk;
642         } else if (token == "\\paragraph_separation") {
643                 string parsep;
644                 lex >> parsep;
645                 paragraph_separation = parseptranslator().find(parsep);
646         } else if (token == "\\paragraph_indentation") {
647                 lex.next();
648                 string indentation = lex.getString();
649                 pimpl_->indentation = HSpace(indentation);
650         } else if (token == "\\defskip") {
651                 lex.next();
652                 string const defskip = lex.getString();
653                 pimpl_->defskip = VSpace(defskip);
654                 if (pimpl_->defskip.kind() == VSpace::DEFSKIP)
655                         // that is invalid
656                         pimpl_->defskip = VSpace(VSpace::MEDSKIP);
657         } else if (token == "\\quotes_language") {
658                 string quotes_lang;
659                 lex >> quotes_lang;
660                 quotes_language = quoteslangtranslator().find(quotes_lang);
661         } else if (token == "\\papersize") {
662                 string ppsize;
663                 lex >> ppsize;
664                 papersize = papersizetranslator().find(ppsize);
665         } else if (token == "\\use_geometry") {
666                 lex >> use_geometry;
667         } else if (token == "\\use_amsmath") {
668                 int use_ams;
669                 lex >> use_ams;
670                 use_amsmath = packagetranslator().find(use_ams);
671         } else if (token == "\\use_esint") {
672                 int useesint;
673                 lex >> useesint;
674                 use_esint = packagetranslator().find(useesint);
675         } else if (token == "\\use_mhchem") {
676                 int usemhchem;
677                 lex >> usemhchem;
678                 use_mhchem = packagetranslator().find(usemhchem);
679         } else if (token == "\\use_mathdots") {
680                 int usemathdots;
681                 lex >> usemathdots;
682                 use_mathdots = packagetranslator().find(usemathdots);
683         } else if (token == "\\cite_engine") {
684                 string engine;
685                 lex >> engine;
686                 cite_engine_ = citeenginetranslator().find(engine);
687         } else if (token == "\\use_bibtopic") {
688                 lex >> use_bibtopic;
689         } else if (token == "\\use_indices") {
690                 lex >> use_indices;
691         } else if (token == "\\tracking_changes") {
692                 lex >> trackChanges;
693         } else if (token == "\\output_changes") {
694                 lex >> outputChanges;
695         } else if (token == "\\branch") {
696                 lex.eatLine();
697                 docstring branch = lex.getDocString();
698                 branchlist().add(branch);
699                 while (true) {
700                         lex.next();
701                         string const tok = lex.getString();
702                         if (tok == "\\end_branch")
703                                 break;
704                         Branch * branch_ptr = branchlist().find(branch);
705                         if (tok == "\\selected") {
706                                 lex.next();
707                                 if (branch_ptr)
708                                         branch_ptr->setSelected(lex.getInteger());
709                         }
710                         if (tok == "\\filename_suffix") {
711                                 lex.next();
712                                 if (branch_ptr)
713                                         branch_ptr->setFileNameSuffix(lex.getInteger());
714                         }
715                         if (tok == "\\color") {
716                                 lex.eatLine();
717                                 string color = lex.getString();
718                                 if (branch_ptr)
719                                         branch_ptr->setColor(color);
720                                 // Update also the Color table:
721                                 if (color == "none")
722                                         color = lcolor.getX11Name(Color_background);
723                                 // FIXME UNICODE
724                                 lcolor.setColor(to_utf8(branch), color);
725                         }
726                 }
727         } else if (token == "\\index") {
728                 lex.eatLine();
729                 docstring index = lex.getDocString();
730                 docstring shortcut;
731                 indiceslist().add(index);
732                 while (true) {
733                         lex.next();
734                         string const tok = lex.getString();
735                         if (tok == "\\end_index")
736                                 break;
737                         Index * index_ptr = indiceslist().find(index);
738                         if (tok == "\\shortcut") {
739                                 lex.next();
740                                 shortcut = lex.getDocString();
741                                 if (index_ptr)
742                                         index_ptr->setShortcut(shortcut);
743                         }
744                         if (tok == "\\color") {
745                                 lex.eatLine();
746                                 string color = lex.getString();
747                                 if (index_ptr)
748                                         index_ptr->setColor(color);
749                                 // Update also the Color table:
750                                 if (color == "none")
751                                         color = lcolor.getX11Name(Color_background);
752                                 // FIXME UNICODE
753                                 if (!shortcut.empty())
754                                         lcolor.setColor(to_utf8(shortcut), color);
755                         }
756                 }
757         } else if (token == "\\author") {
758                 lex.eatLine();
759                 istringstream ss(lex.getString());
760                 Author a;
761                 ss >> a;
762                 author_map[a.bufferId()] = pimpl_->authorlist.record(a);
763         } else if (token == "\\paperorientation") {
764                 string orient;
765                 lex >> orient;
766                 orientation = paperorientationtranslator().find(orient);
767         } else if (token == "\\backgroundcolor") {
768                 lex.eatLine();
769                 backgroundcolor = lyx::rgbFromHexName(lex.getString());
770                 isbackgroundcolor = true;
771         } else if (token == "\\fontcolor") {
772                 lex.eatLine();
773                 fontcolor = lyx::rgbFromHexName(lex.getString());
774                 isfontcolor = true;
775         } else if (token == "\\notefontcolor") {
776                 lex.eatLine();
777                 string color = lex.getString();
778                 notefontcolor = lyx::rgbFromHexName(color);
779         } else if (token == "\\boxbgcolor") {
780                 lex.eatLine();
781                 string color = lex.getString();
782                 boxbgcolor = lyx::rgbFromHexName(color);
783         } else if (token == "\\paperwidth") {
784                 lex >> paperwidth;
785         } else if (token == "\\paperheight") {
786                 lex >> paperheight;
787         } else if (token == "\\leftmargin") {
788                 lex >> leftmargin;
789         } else if (token == "\\topmargin") {
790                 lex >> topmargin;
791         } else if (token == "\\rightmargin") {
792                 lex >> rightmargin;
793         } else if (token == "\\bottommargin") {
794                 lex >> bottommargin;
795         } else if (token == "\\headheight") {
796                 lex >> headheight;
797         } else if (token == "\\headsep") {
798                 lex >> headsep;
799         } else if (token == "\\footskip") {
800                 lex >> footskip;
801         } else if (token == "\\columnsep") {
802                 lex >> columnsep;
803         } else if (token == "\\paperfontsize") {
804                 lex >> fontsize;
805         } else if (token == "\\papercolumns") {
806                 lex >> columns;
807         } else if (token == "\\listings_params") {
808                 string par;
809                 lex >> par;
810                 listings_params = InsetListingsParams(par).params();
811         } else if (token == "\\papersides") {
812                 int psides;
813                 lex >> psides;
814                 sides = sidestranslator().find(psides);
815         } else if (token == "\\paperpagestyle") {
816                 lex >> pagestyle;
817         } else if (token == "\\bullet") {
818                 readBullets(lex);
819         } else if (token == "\\bulletLaTeX") {
820                 readBulletsLaTeX(lex);
821         } else if (token == "\\secnumdepth") {
822                 lex >> secnumdepth;
823         } else if (token == "\\tocdepth") {
824                 lex >> tocdepth;
825         } else if (token == "\\spacing") {
826                 string nspacing;
827                 lex >> nspacing;
828                 string tmp_val;
829                 if (nspacing == "other") {
830                         lex >> tmp_val;
831                 }
832                 spacing().set(spacetranslator().find(nspacing), tmp_val);
833         } else if (token == "\\float_placement") {
834                 lex >> float_placement;
835
836         } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
837                 string toktmp = pdfoptions().readToken(lex, token);
838                 if (!toktmp.empty()) {
839                         lyxerr << "PDFOptions::readToken(): Unknown token: " <<
840                                 toktmp << endl;
841                         return toktmp;
842                 }
843         } else if (token == "\\html_math_output") {
844                 int temp;
845                 lex >> temp;
846                 html_math_output = static_cast<MathOutput>(temp);
847         } else if (token == "\\html_be_strict") {
848                 lex >> html_be_strict;
849         } else if (token == "\\html_math_img_scale") {
850                 lex >> html_math_img_scale;
851         } else if (token == "\\html_latex_start") {
852                 lex.eatLine();
853                 html_latex_start = lex.getString();
854         } else if (token == "\\html_latex_end") {
855                 lex.eatLine();
856                 html_latex_end = lex.getString();
857         } else if (token == "\\output_sync") {
858                 lex >> output_sync;
859         } else if (token == "\\output_sync_macro") {
860                 lex >> output_sync_macro;
861         } else if (token == "\\use_refstyle") {
862                 lex >> use_refstyle;
863         } else {
864                 lyxerr << "BufferParams::readToken(): Unknown token: " << 
865                         token << endl;
866                 return token;
867         }
868
869         return string();
870 }
871
872
873 void BufferParams::writeFile(ostream & os) const
874 {
875         // The top of the file is written by the buffer.
876         // Prints out the buffer info into the .lyx file given by file
877
878         // the textclass
879         os << "\\textclass " << baseClass()->name() << '\n';
880
881         // then the preamble
882         if (!preamble.empty()) {
883                 // remove '\n' from the end of preamble
884                 string const tmppreamble = rtrim(preamble, "\n");
885                 os << "\\begin_preamble\n"
886                    << tmppreamble
887                    << "\n\\end_preamble\n";
888         }
889
890         // the options
891         if (!options.empty()) {
892                 os << "\\options " << options << '\n';
893         }
894
895         // use the class options defined in the layout?
896         os << "\\use_default_options " 
897            << convert<string>(use_default_options) << "\n";
898
899         // the master document
900         if (!master.empty()) {
901                 os << "\\master " << master << '\n';
902         }
903         
904         // removed modules
905         if (!removed_modules_.empty()) {
906                 os << "\\begin_removed_modules" << '\n';
907                 list<string>::const_iterator it = removed_modules_.begin();
908                 list<string>::const_iterator en = removed_modules_.end();
909                 for (; it != en; it++)
910                         os << *it << '\n';
911                 os << "\\end_removed_modules" << '\n';
912         }
913
914         // the modules
915         if (!layout_modules_.empty()) {
916                 os << "\\begin_modules" << '\n';
917                 LayoutModuleList::const_iterator it = layout_modules_.begin();
918                 LayoutModuleList::const_iterator en = layout_modules_.end();
919                 for (; it != en; it++)
920                         os << *it << '\n';
921                 os << "\\end_modules" << '\n';
922         }
923
924         // includeonly
925         if (!included_children_.empty()) {
926                 os << "\\begin_includeonly" << '\n';
927                 list<string>::const_iterator it = included_children_.begin();
928                 list<string>::const_iterator en = included_children_.end();
929                 for (; it != en; it++)
930                         os << *it << '\n';
931                 os << "\\end_includeonly" << '\n';
932         }
933         os << "\\maintain_unincluded_children "
934            << convert<string>(maintain_unincluded_children) << '\n';
935
936         // local layout information
937         if (!local_layout.empty()) {
938                 // remove '\n' from the end 
939                 string const tmplocal = rtrim(local_layout, "\n");
940                 os << "\\begin_local_layout\n"
941                    << tmplocal
942                    << "\n\\end_local_layout\n";
943         }
944
945         // then the text parameters
946         if (language != ignore_language)
947                 os << "\\language " << language->lang() << '\n';
948         os << "\\inputencoding " << inputenc
949            << "\n\\fontencoding " << fontenc
950            << "\n\\font_roman " << fonts_roman
951            << "\n\\font_sans " << fonts_sans
952            << "\n\\font_typewriter " << fonts_typewriter
953            << "\n\\font_default_family " << fonts_default_family
954            << "\n\\use_non_tex_fonts " << convert<string>(useNonTeXFonts)
955            << "\n\\font_sc " << convert<string>(fonts_expert_sc)
956            << "\n\\font_osf " << convert<string>(fonts_old_figures)
957            << "\n\\font_sf_scale " << fonts_sans_scale
958            << "\n\\font_tt_scale " << fonts_typewriter_scale
959            << '\n';
960         if (!fonts_cjk.empty()) {
961                 os << "\\font_cjk " << fonts_cjk << '\n';
962         }
963         os << "\n\\graphics " << graphics_driver << '\n';
964         os << "\\default_output_format " << default_output_format << '\n';
965         os << "\\output_sync " << output_sync << '\n';
966         if (!output_sync_macro.empty())
967                 os << "\\output_sync_macro \"" << output_sync_macro << "\"\n";
968         os << "\\bibtex_command " << bibtex_command << '\n';
969         os << "\\index_command " << index_command << '\n';
970
971         if (!float_placement.empty()) {
972                 os << "\\float_placement " << float_placement << '\n';
973         }
974         os << "\\paperfontsize " << fontsize << '\n';
975
976         spacing().writeFile(os);
977         pdfoptions().writeFile(os);
978
979         os << "\\papersize " << string_papersize[papersize]
980            << "\n\\use_geometry " << convert<string>(use_geometry)
981            << "\n\\use_amsmath " << use_amsmath
982            << "\n\\use_esint " << use_esint
983            << "\n\\use_mhchem " << use_mhchem
984            << "\n\\use_mathdots " << use_mathdots
985            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
986            << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
987            << "\n\\use_indices " << convert<string>(use_indices)
988            << "\n\\paperorientation " << string_orientation[orientation]
989            << "\n\\suppress_date " << convert<string>(suppress_date)
990                  << "\n\\use_refstyle " << use_refstyle
991            << '\n';
992         if (isbackgroundcolor == true)
993                 os << "\\backgroundcolor " << lyx::X11hexname(backgroundcolor) << '\n';
994         if (isfontcolor == true)
995                 os << "\\fontcolor " << lyx::X11hexname(fontcolor) << '\n';
996         if (notefontcolor != lyx::rgbFromHexName("#cccccc"))
997                 os << "\\notefontcolor " << lyx::X11hexname(notefontcolor) << '\n';
998         if (boxbgcolor != lyx::rgbFromHexName("#ff0000"))
999                 os << "\\boxbgcolor " << lyx::X11hexname(boxbgcolor) << '\n';
1000
1001         BranchList::const_iterator it = branchlist().begin();
1002         BranchList::const_iterator end = branchlist().end();
1003         for (; it != end; ++it) {
1004                 os << "\\branch " << to_utf8(it->branch())
1005                    << "\n\\selected " << it->isSelected()
1006                    << "\n\\filename_suffix " << it->hasFileNameSuffix()
1007                    << "\n\\color " << lyx::X11hexname(it->color())
1008                    << "\n\\end_branch"
1009                    << "\n";
1010         }
1011
1012         IndicesList::const_iterator iit = indiceslist().begin();
1013         IndicesList::const_iterator iend = indiceslist().end();
1014         for (; iit != iend; ++iit) {
1015                 os << "\\index " << to_utf8(iit->index())
1016                    << "\n\\shortcut " << to_utf8(iit->shortcut())
1017                    << "\n\\color " << lyx::X11hexname(iit->color())
1018                    << "\n\\end_index"
1019                    << "\n";
1020         }
1021
1022         if (!paperwidth.empty())
1023                 os << "\\paperwidth "
1024                    << VSpace(paperwidth).asLyXCommand() << '\n';
1025         if (!paperheight.empty())
1026                 os << "\\paperheight "
1027                    << VSpace(paperheight).asLyXCommand() << '\n';
1028         if (!leftmargin.empty())
1029                 os << "\\leftmargin "
1030                    << VSpace(leftmargin).asLyXCommand() << '\n';
1031         if (!topmargin.empty())
1032                 os << "\\topmargin "
1033                    << VSpace(topmargin).asLyXCommand() << '\n';
1034         if (!rightmargin.empty())
1035                 os << "\\rightmargin "
1036                    << VSpace(rightmargin).asLyXCommand() << '\n';
1037         if (!bottommargin.empty())
1038                 os << "\\bottommargin "
1039                    << VSpace(bottommargin).asLyXCommand() << '\n';
1040         if (!headheight.empty())
1041                 os << "\\headheight "
1042                    << VSpace(headheight).asLyXCommand() << '\n';
1043         if (!headsep.empty())
1044                 os << "\\headsep "
1045                    << VSpace(headsep).asLyXCommand() << '\n';
1046         if (!footskip.empty())
1047                 os << "\\footskip "
1048                    << VSpace(footskip).asLyXCommand() << '\n';
1049         if (!columnsep.empty())
1050                 os << "\\columnsep " 
1051                          << VSpace(columnsep).asLyXCommand() << '\n';
1052         os << "\\secnumdepth " << secnumdepth
1053            << "\n\\tocdepth " << tocdepth
1054            << "\n\\paragraph_separation "
1055            << string_paragraph_separation[paragraph_separation];
1056         if (!paragraph_separation)
1057                 os << "\n\\paragraph_indentation " << getIndentation().asLyXCommand();
1058         else
1059                 os << "\n\\defskip " << getDefSkip().asLyXCommand();
1060         os << "\n\\quotes_language "
1061            << string_quotes_language[quotes_language]
1062            << "\n\\papercolumns " << columns
1063            << "\n\\papersides " << sides
1064            << "\n\\paperpagestyle " << pagestyle << '\n';
1065         if (!listings_params.empty())
1066                 os << "\\listings_params \"" <<
1067                         InsetListingsParams(listings_params).encodedString() << "\"\n";
1068         for (int i = 0; i < 4; ++i) {
1069                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1070                         if (user_defined_bullet(i).getFont() != -1) {
1071                                 os << "\\bullet " << i << " "
1072                                    << user_defined_bullet(i).getFont() << " "
1073                                    << user_defined_bullet(i).getCharacter() << " "
1074                                    << user_defined_bullet(i).getSize() << "\n";
1075                         }
1076                         else {
1077                                 // FIXME UNICODE
1078                                 os << "\\bulletLaTeX " << i << " \""
1079                                    << lyx::to_ascii(user_defined_bullet(i).getText())
1080                                    << "\"\n";
1081                         }
1082                 }
1083         }
1084
1085         os << "\\tracking_changes " << convert<string>(trackChanges) << '\n'
1086                  << "\\output_changes " << convert<string>(outputChanges) << '\n'
1087                  << "\\html_math_output " << html_math_output << '\n'
1088                  << "\\html_be_strict " << convert<string>(html_be_strict) << '\n';
1089         
1090         if (html_math_img_scale != 1.0)
1091                 os << "\\html_math_img_scale " << convert<string>(html_math_img_scale) << '\n';
1092         if (!html_latex_start.empty())
1093                 os << "\\html_latex_start " << html_latex_start << '\n';
1094         if (!html_latex_end.empty())
1095                  os << "\\html_latex_end " << html_latex_end << '\n';
1096
1097         os << pimpl_->authorlist;
1098 }
1099
1100
1101 void BufferParams::validate(LaTeXFeatures & features) const
1102 {
1103         features.require(documentClass().requires());
1104
1105         if (outputChanges) {
1106                 bool dvipost    = LaTeXFeatures::isAvailable("dvipost");
1107                 bool xcolorulem = LaTeXFeatures::isAvailable("ulem") &&
1108                                   LaTeXFeatures::isAvailable("xcolor");
1109
1110                 switch (features.runparams().flavor) {
1111                 case OutputParams::LATEX:
1112                         if (dvipost) {
1113                                 features.require("ct-dvipost");
1114                                 features.require("dvipost");
1115                         } else if (xcolorulem) {
1116                                 features.require("ct-xcolor-ulem");
1117                                 features.require("ulem");
1118                                 features.require("xcolor");
1119                         } else {
1120                                 features.require("ct-none");
1121                         }
1122                         break;
1123                 case OutputParams::LUATEX:
1124                 case OutputParams::PDFLATEX:
1125                 case OutputParams::XETEX:
1126                         if (xcolorulem) {
1127                                 features.require("ct-xcolor-ulem");
1128                                 features.require("ulem");
1129                                 features.require("xcolor");
1130                                 // improves color handling in PDF output
1131                                 features.require("pdfcolmk"); 
1132                         } else {
1133                                 features.require("ct-none");
1134                         }
1135                         break;
1136                 default:
1137                         break;
1138                 }
1139         }
1140
1141         // Floats with 'Here definitely' as default setting.
1142         if (float_placement.find('H') != string::npos)
1143                 features.require("float");
1144
1145         // AMS Style is at document level
1146         if (use_amsmath == package_on
1147             || documentClass().provides("amsmath"))
1148                 features.require("amsmath");
1149         if (use_esint == package_on)
1150                 features.require("esint");
1151         if (use_mhchem == package_on)
1152                 features.require("mhchem");
1153         if (use_mathdots == package_on)
1154                 features.require("mathdots");
1155
1156         // Document-level line spacing
1157         if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1158                 features.require("setspace");
1159
1160         // the bullet shapes are buffer level not paragraph level
1161         // so they are tested here
1162         for (int i = 0; i < 4; ++i) {
1163                 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) 
1164                         continue;
1165                 int const font = user_defined_bullet(i).getFont();
1166                 if (font == 0) {
1167                         int const c = user_defined_bullet(i).getCharacter();
1168                         if (c == 16
1169                             || c == 17
1170                             || c == 25
1171                             || c == 26
1172                             || c == 31) {
1173                                 features.require("latexsym");
1174                         }
1175                 } else if (font == 1) {
1176                         features.require("amssymb");
1177                 } else if (font >= 2 && font <= 5) {
1178                         features.require("pifont");
1179                 }
1180         }
1181
1182         if (pdfoptions().use_hyperref) {
1183                 features.require("hyperref");
1184                 // due to interferences with babel and hyperref, the color package has to
1185                 // be loaded after hyperref when hyperref is used with the colorlinks
1186                 // option, see http://www.lyx.org/trac/ticket/5291
1187                 if (pdfoptions().colorlinks)
1188                         features.require("color");
1189         }
1190
1191         if (features.runparams().flavor == OutputParams::XETEX
1192             && useNonTeXFonts)
1193                 features.require("polyglossia");
1194
1195         if (language->lang() == "vietnamese")
1196                 features.require("vietnamese");
1197         else if (language->lang() == "japanese")
1198                 features.require("japanese");
1199 }
1200
1201
1202 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1203                               TexRow & texrow, FileName const & filepath) const
1204 {
1205         // http://www.tug.org/texmf-dist/doc/latex/base/fixltx2e.pdf
1206         // !! To use the Fix-cm package, load it before \documentclass, and use the command
1207         // \RequirePackage to do so, rather than the normal \usepackage
1208         // Do not to load any other package before the document class, unless you
1209         // have a thorough understanding of the LATEX internals and know exactly what you
1210         // are doing!
1211         if (features.mustProvide("fix-cm")) {
1212                 os << "\\RequirePackage{fix-cm}\n";
1213                 texrow.newline();
1214         }
1215
1216         os << "\\documentclass";
1217
1218         DocumentClass const & tclass = documentClass();
1219
1220         ostringstream clsoptions; // the document class options.
1221
1222         if (tokenPos(tclass.opt_fontsize(),
1223                      '|', fontsize) >= 0) {
1224                 // only write if existing in list (and not default)
1225                 clsoptions << fontsize << "pt,";
1226         }
1227
1228         // all paper sizes except of A4, A5, B5 and the US sizes need the
1229         // geometry package
1230         bool nonstandard_papersize = papersize != PAPER_DEFAULT
1231                 && papersize != PAPER_USLETTER
1232                 && papersize != PAPER_USLEGAL
1233                 && papersize != PAPER_USEXECUTIVE
1234                 && papersize != PAPER_A4
1235                 && papersize != PAPER_A5
1236                 && papersize != PAPER_B5;
1237
1238         if (!use_geometry) {
1239                 switch (papersize) {
1240                 case PAPER_A4:
1241                         clsoptions << "a4paper,";
1242                         break;
1243                 case PAPER_USLETTER:
1244                         clsoptions << "letterpaper,";
1245                         break;
1246                 case PAPER_A5:
1247                         clsoptions << "a5paper,";
1248                         break;
1249                 case PAPER_B5:
1250                         clsoptions << "b5paper,";
1251                         break;
1252                 case PAPER_USEXECUTIVE:
1253                         clsoptions << "executivepaper,";
1254                         break;
1255                 case PAPER_USLEGAL:
1256                         clsoptions << "legalpaper,";
1257                         break;
1258                 case PAPER_DEFAULT:
1259                 case PAPER_A0:
1260                 case PAPER_A1:
1261                 case PAPER_A2:
1262                 case PAPER_A3:
1263                 case PAPER_A6:
1264                 case PAPER_B0:
1265                 case PAPER_B1:
1266                 case PAPER_B2:
1267                 case PAPER_B3:
1268                 case PAPER_B4:
1269                 case PAPER_B6:
1270                 case PAPER_C0:
1271                 case PAPER_C1:
1272                 case PAPER_C2:
1273                 case PAPER_C3:
1274                 case PAPER_C4:
1275                 case PAPER_C5:
1276                 case PAPER_C6:
1277                 case PAPER_JISB0:
1278                 case PAPER_JISB1:
1279                 case PAPER_JISB2:
1280                 case PAPER_JISB3:
1281                 case PAPER_JISB4:
1282                 case PAPER_JISB5:
1283                 case PAPER_JISB6:
1284                 case PAPER_CUSTOM:
1285                         break;
1286                 }
1287         }
1288
1289         // if needed
1290         if (sides != tclass.sides()) {
1291                 switch (sides) {
1292                 case OneSide:
1293                         clsoptions << "oneside,";
1294                         break;
1295                 case TwoSides:
1296                         clsoptions << "twoside,";
1297                         break;
1298                 }
1299         }
1300
1301         // if needed
1302         if (columns != tclass.columns()) {
1303                 if (columns == 2)
1304                         clsoptions << "twocolumn,";
1305                 else
1306                         clsoptions << "onecolumn,";
1307         }
1308
1309         if (!use_geometry
1310             && orientation == ORIENTATION_LANDSCAPE)
1311                 clsoptions << "landscape,";
1312
1313         // language should be a parameter to \documentclass
1314         if (language->babel() == "hebrew"
1315             && default_language->babel() != "hebrew")
1316                 // This seems necessary
1317                 features.useLanguage(default_language);
1318
1319         ostringstream language_options;
1320         bool const use_babel = features.useBabel() && !tclass.provides("babel");
1321         bool const use_polyglossia = features.usePolyglossia();
1322         bool const global = lyxrc.language_global_options;
1323         if (use_babel || (use_polyglossia && global)) {
1324                 language_options << features.getLanguages();
1325                 if (!language->babel().empty()) {
1326                         if (!language_options.str().empty())
1327                                 language_options << ',';
1328                         language_options << language->babel();
1329                 }
1330                 if (global && !features.needBabelLangOptions())
1331                         clsoptions << language_options.str() << ',';
1332         }
1333
1334         // the predefined options from the layout
1335         if (use_default_options && !tclass.options().empty())
1336                 clsoptions << tclass.options() << ',';
1337
1338         // the user-defined options
1339         if (!options.empty()) {
1340                 clsoptions << options << ',';
1341         }
1342
1343         string strOptions(clsoptions.str());
1344         if (!strOptions.empty()) {
1345                 strOptions = rtrim(strOptions, ",");
1346                 // FIXME UNICODE
1347                 os << '[' << from_utf8(strOptions) << ']';
1348         }
1349
1350         os << '{' << from_ascii(tclass.latexname()) << "}\n";
1351         texrow.newline();
1352         // end of \documentclass defs
1353
1354         int nlines;
1355         // if we use fontspec, we have to load the AMS packages here
1356         string const ams = features.loadAMSPackages();
1357         if (useNonTeXFonts && !ams.empty()) {
1358                 os << from_ascii(ams);
1359                 nlines = int(count(ams.begin(), ams.end(), '\n'));
1360                 texrow.newlines(nlines);
1361         }
1362
1363         if (useNonTeXFonts) {
1364                 os << "\\usepackage{fontspec}\n";
1365                 texrow.newline();
1366         }
1367
1368         // font selection must be done before loading fontenc.sty
1369         string const fonts =
1370                 loadFonts(fonts_roman, fonts_sans,
1371                           fonts_typewriter, fonts_expert_sc, fonts_old_figures,
1372                           fonts_sans_scale, fonts_typewriter_scale, useNonTeXFonts);
1373         if (!fonts.empty()) {
1374                 os << from_ascii(fonts);
1375                 nlines =
1376                         int(count(fonts.begin(), fonts.end(), '\n'));
1377                 texrow.newlines(nlines);
1378         }
1379         if (fonts_default_family != "default")
1380                 os << "\\renewcommand{\\familydefault}{\\"
1381                    << from_ascii(fonts_default_family) << "}\n";
1382
1383         // set font encoding
1384         // for arabic_arabi and farsi we also need to load the LAE and
1385         // LFE encoding
1386         // XeTeX and LuaTeX (with OS fonts) work without fontenc
1387         if (font_encoding() != "default" && language->lang() != "japanese"
1388             && !useNonTeXFonts && !tclass.provides("fontenc")) {
1389                 size_t fars = language_options.str().find("farsi");
1390                 size_t arab = language_options.str().find("arabic");
1391                 if (language->lang() == "arabic_arabi"
1392                         || language->lang() == "farsi" || fars != string::npos
1393                         || arab != string::npos) {
1394                         os << "\\usepackage[" << from_ascii(font_encoding())
1395                            << ",LFE,LAE]{fontenc}\n";
1396                         texrow.newline();
1397                 } else {
1398                         os << "\\usepackage[" << from_ascii(font_encoding())
1399                            << "]{fontenc}\n";
1400                         texrow.newline();
1401                 }
1402         }
1403
1404         // handle inputenc etc.
1405         writeEncodingPreamble(os, features, texrow);
1406
1407         // includeonly
1408         if (!features.runparams().includeall && !included_children_.empty()) {
1409                 os << "\\includeonly{";
1410                 list<string>::const_iterator it = included_children_.begin();
1411                 list<string>::const_iterator en = included_children_.end();
1412                 bool first = true;
1413                 for (; it != en; ++it) {
1414                         string incfile = *it;
1415                         FileName inc = makeAbsPath(incfile, filepath.absFileName());
1416                         string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1417                         mangledFileName();
1418                         if (!features.runparams().nice)
1419                                 incfile = mangled;
1420                         // \includeonly doesn't want an extension 
1421                         incfile = changeExtension(incfile, string());
1422                         incfile = support::latex_path(incfile);
1423                         if (!incfile.empty()) {
1424                                 if (!first)
1425                                         os << ",";
1426                                 os << from_utf8(incfile);
1427                         }
1428                         first = false;
1429                 }
1430                 os << "}\n";
1431         }
1432
1433         if (!listings_params.empty() || features.isRequired("listings")) {
1434                 os << "\\usepackage{listings}\n";
1435                 texrow.newline();
1436         }
1437         if (!listings_params.empty()) {
1438                 os << "\\lstset{";
1439                 // do not test validity because listings_params is 
1440                 // supposed to be valid
1441                 string par =
1442                         InsetListingsParams(listings_params).separatedParams(true);
1443                 // we can't support all packages, but we should load the color package
1444                 if (par.find("\\color", 0) != string::npos)
1445                         features.require("color");
1446                 os << from_utf8(par);
1447                 // count the number of newlines
1448                 for (size_t i = 0; i < par.size(); ++i)
1449                         if (par[i] == '\n')
1450                                 texrow.newline();
1451                 os << "}\n";
1452                 texrow.newline();
1453         }
1454         if (!tclass.provides("geometry")
1455             && (use_geometry || nonstandard_papersize)) {
1456                 odocstringstream ods;
1457                 if (!getGraphicsDriver("geometry").empty())
1458                         ods << getGraphicsDriver("geometry");
1459                 if (orientation == ORIENTATION_LANDSCAPE)
1460                         ods << ",landscape";
1461                 switch (papersize) {
1462                 case PAPER_CUSTOM:
1463                         if (!paperwidth.empty())
1464                                 ods << ",paperwidth="
1465                                    << from_ascii(paperwidth);
1466                         if (!paperheight.empty())
1467                                 ods << ",paperheight="
1468                                    << from_ascii(paperheight);
1469                         break;
1470                 case PAPER_USLETTER:
1471                         ods << ",letterpaper";
1472                         break;
1473                 case PAPER_USLEGAL:
1474                         ods << ",legalpaper";
1475                         break;
1476                 case PAPER_USEXECUTIVE:
1477                         ods << ",executivepaper";
1478                         break;
1479                 case PAPER_A0:
1480                         ods << ",a0paper";
1481                         break;
1482                 case PAPER_A1:
1483                         ods << ",a1paper";
1484                         break;
1485                 case PAPER_A2:
1486                         ods << ",a2paper";
1487                         break;
1488                 case PAPER_A3:
1489                         ods << ",a3paper";
1490                         break;
1491                 case PAPER_A4:
1492                         ods << ",a4paper";
1493                         break;
1494                 case PAPER_A5:
1495                         ods << ",a5paper";
1496                         break;
1497                 case PAPER_A6:
1498                         ods << ",a6paper";
1499                         break;
1500                 case PAPER_B0:
1501                         ods << ",b0paper";
1502                         break;
1503                 case PAPER_B1:
1504                         ods << ",b1paper";
1505                         break;
1506                 case PAPER_B2:
1507                         ods << ",b2paper";
1508                         break;
1509                 case PAPER_B3:
1510                         ods << ",b3paper";
1511                         break;
1512                 case PAPER_B4:
1513                         ods << ",b4paper";
1514                         break;
1515                 case PAPER_B5:
1516                         ods << ",b5paper";
1517                         break;
1518                 case PAPER_B6:
1519                         ods << ",b6paper";
1520                         break;
1521                 case PAPER_C0:
1522                         ods << ",c0paper";
1523                         break;
1524                 case PAPER_C1:
1525                         ods << ",c1paper";
1526                         break;
1527                 case PAPER_C2:
1528                         ods << ",c2paper";
1529                         break;
1530                 case PAPER_C3:
1531                         ods << ",c3paper";
1532                         break;
1533                 case PAPER_C4:
1534                         ods << ",c4paper";
1535                         break;
1536                 case PAPER_C5:
1537                         ods << ",c5paper";
1538                         break;
1539                 case PAPER_C6:
1540                         ods << ",c6paper";
1541                         break;
1542                 case PAPER_JISB0:
1543                         ods << ",b0j";
1544                         break;
1545                 case PAPER_JISB1:
1546                         ods << ",b1j";
1547                         break;
1548                 case PAPER_JISB2:
1549                         ods << ",b2j";
1550                         break;
1551                 case PAPER_JISB3:
1552                         ods << ",b3j";
1553                         break;
1554                 case PAPER_JISB4:
1555                         ods << ",b4j";
1556                         break;
1557                 case PAPER_JISB5:
1558                         ods << ",b5j";
1559                         break;
1560                 case PAPER_JISB6:
1561                         ods << ",b6j";
1562                         break;
1563                 default:
1564                         // default papersize ie PAPER_DEFAULT
1565                         switch (lyxrc.default_papersize) {
1566                         case PAPER_DEFAULT: // keep compiler happy
1567                         case PAPER_USLETTER:
1568                                 ods << ",letterpaper";
1569                                 break;
1570                         case PAPER_USLEGAL:
1571                                 ods << ",legalpaper";
1572                                 break;
1573                         case PAPER_USEXECUTIVE:
1574                                 ods << ",executivepaper";
1575                                 break;
1576                         case PAPER_A3:
1577                                 ods << ",a3paper";
1578                                 break;
1579                         case PAPER_A4:
1580                                 ods << ",a4paper";
1581                                 break;
1582                         case PAPER_A5:
1583                                 ods << ",a5paper";
1584                                 break;
1585                         case PAPER_B5:
1586                                 ods << ",b5paper";
1587                                 break;
1588                         case PAPER_A0:
1589                         case PAPER_A1:
1590                         case PAPER_A2:
1591                         case PAPER_A6:
1592                         case PAPER_B0:
1593                         case PAPER_B1:
1594                         case PAPER_B2:
1595                         case PAPER_B3:
1596                         case PAPER_B4:
1597                         case PAPER_B6:
1598                         case PAPER_C0:
1599                         case PAPER_C1:
1600                         case PAPER_C2:
1601                         case PAPER_C3:
1602                         case PAPER_C4:
1603                         case PAPER_C5:
1604                         case PAPER_C6:
1605                         case PAPER_JISB0:
1606                         case PAPER_JISB1:
1607                         case PAPER_JISB2:
1608                         case PAPER_JISB3:
1609                         case PAPER_JISB4:
1610                         case PAPER_JISB5:
1611                         case PAPER_JISB6:
1612                         case PAPER_CUSTOM:
1613                                 break;
1614                         }
1615                 }
1616                 docstring const g_options = trim(ods.str(), ",");
1617                 os << "\\usepackage";
1618                 if (!g_options.empty())
1619                         os << '[' << g_options << ']';
1620                 os << "{geometry}\n";
1621                 texrow.newline();
1622                 // output this only if use_geometry is true
1623                 if (use_geometry) {
1624                         os << "\\geometry{verbose";
1625                         if (!topmargin.empty())
1626                                 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1627                         if (!bottommargin.empty())
1628                                 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1629                         if (!leftmargin.empty())
1630                                 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1631                         if (!rightmargin.empty())
1632                                 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1633                         if (!headheight.empty())
1634                                 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1635                         if (!headsep.empty())
1636                                 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1637                         if (!footskip.empty())
1638                                 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1639                         if (!columnsep.empty())
1640                                 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1641                         os << "}\n";
1642                         texrow.newline();
1643                 }
1644         } else if (orientation == ORIENTATION_LANDSCAPE
1645                    || papersize != PAPER_DEFAULT) {
1646                 features.require("papersize");
1647         }
1648
1649         if (tokenPos(tclass.opt_pagestyle(),
1650                      '|', pagestyle) >= 0) {
1651                 if (pagestyle == "fancy") {
1652                         os << "\\usepackage{fancyhdr}\n";
1653                         texrow.newline();
1654                 }
1655                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1656                 texrow.newline();
1657         }
1658
1659         // only output when the background color is not default
1660         if (isbackgroundcolor == true) {
1661                 // only require color here, the background color will be defined
1662                 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1663                 // package pdfpages 
1664                 features.require("color");
1665                 features.require("pagecolor");
1666         }
1667
1668         // only output when the font color is not default
1669         if (isfontcolor == true) {
1670                 // only require color here, the font color will be defined
1671                 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1672                 // package pdfpages 
1673                 features.require("color");
1674                 features.require("fontcolor");
1675         }
1676
1677         // Only if class has a ToC hierarchy
1678         if (tclass.hasTocLevels()) {
1679                 if (secnumdepth != tclass.secnumdepth()) {
1680                         os << "\\setcounter{secnumdepth}{"
1681                            << secnumdepth
1682                            << "}\n";
1683                         texrow.newline();
1684                 }
1685                 if (tocdepth != tclass.tocdepth()) {
1686                         os << "\\setcounter{tocdepth}{"
1687                            << tocdepth
1688                            << "}\n";
1689                         texrow.newline();
1690                 }
1691         }
1692
1693         if (paragraph_separation) {
1694                 // when skip separation
1695                 switch (getDefSkip().kind()) {
1696                 case VSpace::SMALLSKIP:
1697                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1698                         break;
1699                 case VSpace::MEDSKIP:
1700                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1701                         break;
1702                 case VSpace::BIGSKIP:
1703                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1704                         break;
1705                 case VSpace::LENGTH:
1706                         os << "\\setlength{\\parskip}{"
1707                            << from_utf8(getDefSkip().length().asLatexString())
1708                            << "}\n";
1709                         break;
1710                 default: // should never happen // Then delete it.
1711                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1712                         break;
1713                 }
1714                 texrow.newline();
1715                 os << "\\setlength{\\parindent}{0pt}\n";
1716                 texrow.newline();
1717         } else {
1718                 // when separation by indentation
1719                 // only output something when a width is given
1720                 if (getIndentation().asLyXCommand() != "default") {
1721                         os << "\\setlength{\\parindent}{"
1722                                 << from_utf8(getIndentation().asLatexCommand())
1723                            << "}\n";
1724                         texrow.newline();
1725                 }
1726         }
1727
1728         // Now insert the LyX specific LaTeX commands...
1729         docstring lyxpreamble;
1730
1731         if (output_sync) {
1732                 if (!output_sync_macro.empty())
1733                         lyxpreamble += from_utf8(output_sync_macro) +"\n";
1734                 else if (features.runparams().flavor == OutputParams::LATEX)
1735                         lyxpreamble += "\\usepackage[active]{srcltx}\n";
1736                 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1737                         lyxpreamble += "\\synctex=-1\n";
1738         }
1739
1740         // due to interferences with babel and hyperref, the color package has to
1741         // be loaded (when it is not already loaded) before babel when hyperref
1742         // is used with the colorlinks option, see
1743         // http://www.lyx.org/trac/ticket/5291
1744         // we decided therefore to load color always before babel, see
1745         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1746         lyxpreamble += from_ascii(features.getColorOptions());
1747         
1748         // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1749         if (use_babel
1750             && (features.isRequired("jurabib")
1751                 || features.isRequired("hyperref")
1752                 || features.isRequired("vietnamese")
1753                 || features.isRequired("japanese"))) {
1754                         // FIXME UNICODE
1755                         lyxpreamble += from_utf8(features.getBabelPresettings());
1756                         lyxpreamble += from_utf8(babelCall(language_options.str(),
1757                                                            features.needBabelLangOptions())) + '\n';
1758                         lyxpreamble += from_utf8(features.getBabelPostsettings());
1759         }
1760
1761         // The optional packages;
1762         lyxpreamble += from_ascii(features.getPackages());
1763
1764         // Additional Indices
1765         if (features.isRequired("splitidx")) {
1766                 IndicesList::const_iterator iit = indiceslist().begin();
1767                 IndicesList::const_iterator iend = indiceslist().end();
1768                 for (; iit != iend; ++iit) {
1769                         lyxpreamble += "\\newindex[";
1770                         lyxpreamble += iit->index();
1771                         lyxpreamble += "]{";
1772                         lyxpreamble += iit->shortcut();
1773                         lyxpreamble += "}\n";
1774                 }
1775         }
1776
1777         // Line spacing
1778         lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1779
1780         // PDF support.
1781         // * Hyperref manual: "Make sure it comes last of your loaded
1782         //   packages, to give it a fighting chance of not being over-written,
1783         //   since its job is to redefine many LaTeX commands."
1784         // * Email from Heiko Oberdiek: "It is usually better to load babel
1785         //   before hyperref. Then hyperref has a chance to detect babel.
1786         // * Has to be loaded before the "LyX specific LaTeX commands" to
1787         //   avoid errors with algorithm floats.
1788         // use hyperref explicitly if it is required
1789         if (features.isRequired("hyperref")) {
1790                 // pass what we have to stream here, since we need 
1791                 // to access the stream itself in PDFOptions.
1792                 os << lyxpreamble;
1793
1794                 int lines =
1795                         int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1796
1797                 OutputParams tmp_params = features.runparams();
1798                 lines += pdfoptions().writeLaTeX(tmp_params, os,
1799                                         documentClass().provides("hyperref"));
1800                 texrow.newlines(lines);
1801                 // set back for the rest
1802                 lyxpreamble.clear();
1803                 // correctly break URLs with hyperref and dvi output
1804                 if (features.runparams().flavor == OutputParams::LATEX
1805                     && features.isAvailable("breakurl"))
1806                         lyxpreamble += "\\usepackage{breakurl}\n";
1807         } else if (features.isRequired("nameref"))
1808                 // hyperref loads this automatically
1809                 lyxpreamble += "\\usepackage{nameref}\n";
1810
1811         // Will be surrounded by \makeatletter and \makeatother when not empty
1812         docstring atlyxpreamble;
1813
1814         // Some macros LyX will need
1815         docstring tmppreamble(features.getMacros());
1816
1817         if (!tmppreamble.empty())
1818                 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1819                         "LyX specific LaTeX commands.\n"
1820                         + tmppreamble + '\n';
1821
1822         // the text class specific preamble
1823         tmppreamble = features.getTClassPreamble();
1824         if (!tmppreamble.empty())
1825                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1826                         "Textclass specific LaTeX commands.\n"
1827                         + tmppreamble + '\n';
1828
1829         // suppress date if selected
1830         // use \@ifundefined because we cannot be sure that every document class
1831         // has a \date command
1832         if (suppress_date)
1833                 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1834
1835         /* the user-defined preamble */
1836         if (!containsOnly(preamble, " \n\t"))
1837                 // FIXME UNICODE
1838                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1839                         "User specified LaTeX commands.\n"
1840                         + from_utf8(preamble) + '\n';
1841
1842         // subfig loads internally the LaTeX package "caption". As
1843         // caption is a very popular package, users will load it in
1844         // the preamble. Therefore we must load subfig behind the
1845         // user-defined preamble and check if the caption package was
1846         // loaded or not. For the case that caption is loaded before
1847         // subfig, there is the subfig option "caption=false". This
1848         // option also works when a koma-script class is used and
1849         // koma's own caption commands are used instead of caption. We
1850         // use \PassOptionsToPackage here because the user could have
1851         // already loaded subfig in the preamble.
1852         if (features.isRequired("subfig")) {
1853                 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1854                         " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1855                         "\\usepackage{subfig}\n";
1856         }
1857
1858         // Itemize bullet settings need to be last in case the user
1859         // defines their own bullets that use a package included
1860         // in the user-defined preamble -- ARRae
1861         // Actually it has to be done much later than that
1862         // since some packages like frenchb make modifications
1863         // at \begin{document} time -- JMarc
1864         docstring bullets_def;
1865         for (int i = 0; i < 4; ++i) {
1866                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1867                         if (bullets_def.empty())
1868                                 bullets_def += "\\AtBeginDocument{\n";
1869                         bullets_def += "  \\def\\labelitemi";
1870                         switch (i) {
1871                                 // `i' is one less than the item to modify
1872                         case 0:
1873                                 break;
1874                         case 1:
1875                                 bullets_def += 'i';
1876                                 break;
1877                         case 2:
1878                                 bullets_def += "ii";
1879                                 break;
1880                         case 3:
1881                                 bullets_def += 'v';
1882                                 break;
1883                         }
1884                         bullets_def += '{' +
1885                                 user_defined_bullet(i).getText()
1886                                 + "}\n";
1887                 }
1888         }
1889
1890         if (!bullets_def.empty())
1891                 atlyxpreamble += bullets_def + "}\n\n";
1892
1893         if (!atlyxpreamble.empty())
1894                 lyxpreamble += "\n\\makeatletter\n"
1895                         + atlyxpreamble + "\\makeatother\n\n";
1896
1897         // We try to load babel late, in case it interferes with other packages.
1898         // Jurabib and Hyperref have to be called after babel, though.
1899         if (use_babel && !features.isRequired("jurabib")
1900             && !features.isRequired("hyperref")
1901             && !features.isRequired("vietnamese")
1902             && !features.isRequired("japanese")) {
1903                 // FIXME UNICODE
1904                 lyxpreamble += from_utf8(features.getBabelPresettings());
1905                 lyxpreamble += from_utf8(babelCall(language_options.str(),
1906                                                    features.needBabelLangOptions())) + '\n';
1907                 lyxpreamble += from_utf8(features.getBabelPostsettings());
1908         }
1909
1910         // xunicode needs to be loaded at least after amsmath, amssymb,
1911         // esint and the other packages that provide special glyphs
1912         if (features.runparams().flavor == OutputParams::XETEX)
1913                 lyxpreamble += "\\usepackage{xunicode}\n";
1914
1915         // Polyglossia must be loaded last
1916         if (use_polyglossia) {
1917                 // call the package
1918                 lyxpreamble += "\\usepackage{polyglossia}\n";
1919                 // set the main language
1920                 lyxpreamble += "\\setdefaultlanguage";
1921                 if (!language->polyglossiaOpts().empty())
1922                         lyxpreamble += "[" + from_ascii(language->polyglossiaOpts()) + "]";
1923                 lyxpreamble += "{" + from_ascii(language->polyglossia()) + "}\n";
1924                 // now setup the other languages
1925                 std::map<std::string, std::string> const polylangs = 
1926                         features.getPolyglossiaLanguages();
1927                 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1928                      mit != polylangs.end() ; ++mit) {
1929                         lyxpreamble += "\\setotherlanguage";
1930                         if (!mit->second.empty())
1931                                 lyxpreamble += "[" + from_ascii(mit->second) + "]";
1932                         lyxpreamble += "{" + from_ascii(mit->first) + "}\n";
1933                 }
1934         }
1935
1936         docstring const i18npreamble =
1937                 features.getTClassI18nPreamble(use_babel, use_polyglossia);
1938         if (!i18npreamble.empty())
1939                 lyxpreamble += i18npreamble + '\n';
1940
1941         nlines = int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1942         texrow.newlines(nlines);
1943
1944         os << lyxpreamble;
1945
1946         return use_babel;
1947 }
1948
1949
1950 void BufferParams::useClassDefaults()
1951 {
1952         DocumentClass const & tclass = documentClass();
1953
1954         sides = tclass.sides();
1955         columns = tclass.columns();
1956         pagestyle = tclass.pagestyle();
1957         use_default_options = true;
1958         // Only if class has a ToC hierarchy
1959         if (tclass.hasTocLevels()) {
1960                 secnumdepth = tclass.secnumdepth();
1961                 tocdepth = tclass.tocdepth();
1962         }
1963 }
1964
1965
1966 bool BufferParams::hasClassDefaults() const
1967 {
1968         DocumentClass const & tclass = documentClass();
1969
1970         return sides == tclass.sides()
1971                 && columns == tclass.columns()
1972                 && pagestyle == tclass.pagestyle()
1973                 && use_default_options
1974                 && secnumdepth == tclass.secnumdepth()
1975                 && tocdepth == tclass.tocdepth();
1976 }
1977
1978
1979 DocumentClass const & BufferParams::documentClass() const
1980 {
1981         return *doc_class_;
1982 }
1983
1984
1985 DocumentClass const * BufferParams::documentClassPtr() const
1986 {
1987         return doc_class_;
1988 }
1989
1990
1991 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1992 {
1993         // evil, but this function is evil
1994         doc_class_ = const_cast<DocumentClass *>(tc);
1995 }
1996
1997
1998 bool BufferParams::setBaseClass(string const & classname)
1999 {
2000         LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
2001         LayoutFileList & bcl = LayoutFileList::get();
2002         if (!bcl.haveClass(classname)) {
2003                 docstring s = 
2004                         bformat(_("The layout file:\n"
2005                                 "%1$s\n"
2006                                 "could not be found. A default textclass with default\n"
2007                                 "layouts will be used. LyX will not be able to produce\n"
2008                                 "correct output."),
2009                         from_utf8(classname));
2010                 frontend::Alert::error(_("Document class not found"), s);
2011                 bcl.addEmptyClass(classname);
2012         }
2013
2014         bool const success = bcl[classname].load();
2015         if (!success) {
2016                 docstring s = 
2017                         bformat(_("Due to some error in it, the layout file:\n"
2018                                 "%1$s\n"
2019                                 "could not be loaded. A default textclass with default\n"
2020                                 "layouts will be used. LyX will not be able to produce\n"
2021                                 "correct output."),
2022                         from_utf8(classname));
2023                 frontend::Alert::error(_("Could not load class"), s);
2024                 bcl.addEmptyClass(classname);
2025         }
2026
2027         pimpl_->baseClass_ = classname;
2028         layout_modules_.adaptToBaseClass(baseClass(), removed_modules_);
2029         return true;
2030 }
2031
2032
2033 LayoutFile const * BufferParams::baseClass() const
2034 {
2035         if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2036                 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2037         else 
2038                 return 0;
2039 }
2040
2041
2042 LayoutFileIndex const & BufferParams::baseClassID() const
2043 {
2044         return pimpl_->baseClass_;
2045 }
2046
2047
2048 void BufferParams::makeDocumentClass()
2049 {
2050         if (!baseClass())
2051                 return;
2052
2053         doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layout_modules_));
2054
2055         if (!local_layout.empty()) {
2056                 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2057                         docstring const msg = _("Error reading internal layout information");
2058                         frontend::Alert::warning(_("Read Error"), msg);
2059                 }
2060         }
2061 }
2062
2063
2064 bool BufferParams::moduleCanBeAdded(string const & modName) const
2065 {
2066         return layout_modules_.moduleCanBeAdded(modName, baseClass());
2067 }
2068
2069
2070 bool BufferParams::addLayoutModule(string const & modName)
2071 {
2072         LayoutModuleList::const_iterator it = layout_modules_.begin();
2073         LayoutModuleList::const_iterator end = layout_modules_.end();
2074         for (; it != end; it++)
2075                 if (*it == modName) 
2076                         return false;
2077         layout_modules_.push_back(modName);
2078         return true;
2079 }
2080
2081
2082 Font const BufferParams::getFont() const
2083 {
2084         FontInfo f = documentClass().defaultfont();
2085         if (fonts_default_family == "rmdefault")
2086                 f.setFamily(ROMAN_FAMILY);
2087         else if (fonts_default_family == "sfdefault")
2088                 f.setFamily(SANS_FAMILY);
2089         else if (fonts_default_family == "ttdefault")
2090                 f.setFamily(TYPEWRITER_FAMILY);
2091         return Font(f, language);
2092 }
2093
2094
2095 void BufferParams::readPreamble(Lexer & lex)
2096 {
2097         if (lex.getString() != "\\begin_preamble")
2098                 lyxerr << "Error (BufferParams::readPreamble):"
2099                         "consistency check failed." << endl;
2100
2101         preamble = lex.getLongString("\\end_preamble");
2102 }
2103
2104
2105 void BufferParams::readLocalLayout(Lexer & lex)
2106 {
2107         if (lex.getString() != "\\begin_local_layout")
2108                 lyxerr << "Error (BufferParams::readLocalLayout):"
2109                         "consistency check failed." << endl;
2110
2111         local_layout = lex.getLongString("\\end_local_layout");
2112 }
2113
2114
2115 void BufferParams::readLanguage(Lexer & lex)
2116 {
2117         if (!lex.next()) return;
2118
2119         string const tmptok = lex.getString();
2120
2121         // check if tmptok is part of tex_babel in tex-defs.h
2122         language = languages.getLanguage(tmptok);
2123         if (!language) {
2124                 // Language tmptok was not found
2125                 language = default_language;
2126                 lyxerr << "Warning: Setting language `"
2127                        << tmptok << "' to `" << language->lang()
2128                        << "'." << endl;
2129         }
2130 }
2131
2132
2133 void BufferParams::readGraphicsDriver(Lexer & lex)
2134 {
2135         if (!lex.next()) 
2136                 return;
2137
2138         string const tmptok = lex.getString();
2139         // check if tmptok is part of tex_graphics in tex_defs.h
2140         int n = 0;
2141         while (true) {
2142                 string const test = tex_graphics[n++];
2143
2144                 if (test == tmptok) {
2145                         graphics_driver = tmptok;
2146                         break;
2147                 }
2148                 if (test.empty()) {
2149                         lex.printError(
2150                                 "Warning: graphics driver `$$Token' not recognized!\n"
2151                                 "         Setting graphics driver to `default'.\n");
2152                         graphics_driver = "default";
2153                         break;
2154                 }
2155         }
2156 }
2157
2158
2159 void BufferParams::readBullets(Lexer & lex)
2160 {
2161         if (!lex.next()) 
2162                 return;
2163
2164         int const index = lex.getInteger();
2165         lex.next();
2166         int temp_int = lex.getInteger();
2167         user_defined_bullet(index).setFont(temp_int);
2168         temp_bullet(index).setFont(temp_int);
2169         lex >> temp_int;
2170         user_defined_bullet(index).setCharacter(temp_int);
2171         temp_bullet(index).setCharacter(temp_int);
2172         lex >> temp_int;
2173         user_defined_bullet(index).setSize(temp_int);
2174         temp_bullet(index).setSize(temp_int);
2175 }
2176
2177
2178 void BufferParams::readBulletsLaTeX(Lexer & lex)
2179 {
2180         // The bullet class should be able to read this.
2181         if (!lex.next()) 
2182                 return;
2183         int const index = lex.getInteger();
2184         lex.next(true);
2185         docstring const temp_str = lex.getDocString();
2186
2187         user_defined_bullet(index).setText(temp_str);
2188         temp_bullet(index).setText(temp_str);
2189 }
2190
2191
2192 void BufferParams::readModules(Lexer & lex)
2193 {
2194         if (!lex.eatLine()) {
2195                 lyxerr << "Error (BufferParams::readModules):"
2196                                 "Unexpected end of input." << endl;
2197                 return;
2198         }
2199         while (true) {
2200                 string mod = lex.getString();
2201                 if (mod == "\\end_modules")
2202                         break;
2203                 addLayoutModule(mod);
2204                 lex.eatLine();
2205         }
2206 }
2207
2208
2209 void BufferParams::readRemovedModules(Lexer & lex)
2210 {
2211         if (!lex.eatLine()) {
2212                 lyxerr << "Error (BufferParams::readRemovedModules):"
2213                                 "Unexpected end of input." << endl;
2214                 return;
2215         }
2216         while (true) {
2217                 string mod = lex.getString();
2218                 if (mod == "\\end_removed_modules")
2219                         break;
2220                 removed_modules_.push_back(mod);
2221                 lex.eatLine();
2222         }
2223         // now we want to remove any removed modules that were previously 
2224         // added. normally, that will be because default modules were added in 
2225         // setBaseClass(), which gets called when \textclass is read at the 
2226         // start of the read.
2227         list<string>::const_iterator rit = removed_modules_.begin();
2228         list<string>::const_iterator const ren = removed_modules_.end();
2229         for (; rit != ren; rit++) {
2230                 LayoutModuleList::iterator const mit = layout_modules_.begin();
2231                 LayoutModuleList::iterator const men = layout_modules_.end();
2232                 LayoutModuleList::iterator found = find(mit, men, *rit);
2233                 if (found == men)
2234                         continue;
2235                 layout_modules_.erase(found);
2236         }
2237 }
2238
2239
2240 void BufferParams::readIncludeonly(Lexer & lex)
2241 {
2242         if (!lex.eatLine()) {
2243                 lyxerr << "Error (BufferParams::readIncludeonly):"
2244                                 "Unexpected end of input." << endl;
2245                 return;
2246         }
2247         while (true) {
2248                 string child = lex.getString();
2249                 if (child == "\\end_includeonly")
2250                         break;
2251                 included_children_.push_back(child);
2252                 lex.eatLine();
2253         }
2254 }
2255
2256
2257 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2258 {
2259         char real_papersize = papersize;
2260         if (real_papersize == PAPER_DEFAULT)
2261                 real_papersize = lyxrc.default_papersize;
2262
2263         switch (real_papersize) {
2264         case PAPER_DEFAULT:
2265                 // could be anything, so don't guess
2266                 return string();
2267         case PAPER_CUSTOM: {
2268                 if (purpose == XDVI && !paperwidth.empty() &&
2269                     !paperheight.empty()) {
2270                         // heightxwidth<unit>
2271                         string first = paperwidth;
2272                         string second = paperheight;
2273                         if (orientation == ORIENTATION_LANDSCAPE)
2274                                 first.swap(second);
2275                         // cut off unit.
2276                         return first.erase(first.length() - 2)
2277                                 + "x" + second;
2278                 }
2279                 return string();
2280         }
2281         case PAPER_A0:
2282                 // dvips and dvipdfm do not know this
2283                 if (purpose == DVIPS || purpose == DVIPDFM)
2284                         return string();
2285                 return "a0";
2286         case PAPER_A1:
2287                 if (purpose == DVIPS || purpose == DVIPDFM)
2288                         return string();
2289                 return "a1";
2290         case PAPER_A2:
2291                 if (purpose == DVIPS || purpose == DVIPDFM)
2292                         return string();
2293                 return "a2";
2294         case PAPER_A3:
2295                 return "a3";
2296         case PAPER_A4:
2297                 return "a4";
2298         case PAPER_A5:
2299                 return "a5";
2300         case PAPER_A6:
2301                 if (purpose == DVIPS || purpose == DVIPDFM)
2302                         return string();
2303                 return "a6";
2304         case PAPER_B0:
2305                 if (purpose == DVIPS || purpose == DVIPDFM)
2306                         return string();
2307                 return "b0";
2308         case PAPER_B1:
2309                 if (purpose == DVIPS || purpose == DVIPDFM)
2310                         return string();
2311                 return "b1";
2312         case PAPER_B2:
2313                 if (purpose == DVIPS || purpose == DVIPDFM)
2314                         return string();
2315                 return "b2";
2316         case PAPER_B3:
2317                 if (purpose == DVIPS || purpose == DVIPDFM)
2318                         return string();
2319                 return "b3";
2320         case PAPER_B4:
2321                 // dvipdfm does not know this
2322                 if (purpose == DVIPDFM)
2323                         return string();
2324                 return "b4";
2325         case PAPER_B5:
2326                 if (purpose == DVIPDFM)
2327                         return string();
2328                 return "b5";
2329         case PAPER_B6:
2330                 if (purpose == DVIPS || purpose == DVIPDFM)
2331                         return string();
2332                 return "b6";
2333         case PAPER_C0:
2334                 if (purpose == DVIPS || purpose == DVIPDFM)
2335                         return string();
2336                 return "c0";
2337         case PAPER_C1:
2338                 if (purpose == DVIPS || purpose == DVIPDFM)
2339                         return string();
2340                 return "c1";
2341         case PAPER_C2:
2342                 if (purpose == DVIPS || purpose == DVIPDFM)
2343                         return string();
2344                 return "c2";
2345         case PAPER_C3:
2346                 if (purpose == DVIPS || purpose == DVIPDFM)
2347                         return string();
2348                 return "c3";
2349         case PAPER_C4:
2350                 if (purpose == DVIPS || purpose == DVIPDFM)
2351                         return string();
2352                 return "c4";
2353         case PAPER_C5:
2354                 if (purpose == DVIPS || purpose == DVIPDFM)
2355                         return string();
2356                 return "c5";
2357         case PAPER_C6:
2358                 if (purpose == DVIPS || purpose == DVIPDFM)
2359                         return string();
2360                 return "c6";
2361         case PAPER_JISB0:
2362                 if (purpose == DVIPS || purpose == DVIPDFM)
2363                         return string();
2364                 return "jisb0";
2365         case PAPER_JISB1:
2366                 if (purpose == DVIPS || purpose == DVIPDFM)
2367                         return string();
2368                 return "jisb1";
2369         case PAPER_JISB2:
2370                 if (purpose == DVIPS || purpose == DVIPDFM)
2371                         return string();
2372                 return "jisb2";
2373         case PAPER_JISB3:
2374                 if (purpose == DVIPS || purpose == DVIPDFM)
2375                         return string();
2376                 return "jisb3";
2377         case PAPER_JISB4:
2378                 if (purpose == DVIPS || purpose == DVIPDFM)
2379                         return string();
2380                 return "jisb4";
2381         case PAPER_JISB5:
2382                 if (purpose == DVIPS || purpose == DVIPDFM)
2383                         return string();
2384                 return "jisb5";
2385         case PAPER_JISB6:
2386                 if (purpose == DVIPS || purpose == DVIPDFM)
2387                         return string();
2388                 return "jisb6";
2389         case PAPER_USEXECUTIVE:
2390                 // dvipdfm does not know this
2391                 if (purpose == DVIPDFM)
2392                         return string();
2393                 return "foolscap";
2394         case PAPER_USLEGAL:
2395                 return "legal";
2396         case PAPER_USLETTER:
2397         default:
2398                 if (purpose == XDVI)
2399                         return "us";
2400                 return "letter";
2401         }
2402 }
2403
2404
2405 string const BufferParams::dvips_options() const
2406 {
2407         string result;
2408
2409         if (use_geometry
2410             && papersize == PAPER_CUSTOM
2411             && !lyxrc.print_paper_dimension_flag.empty()
2412             && !paperwidth.empty()
2413             && !paperheight.empty()) {
2414                 // using a custom papersize
2415                 result = lyxrc.print_paper_dimension_flag;
2416                 result += ' ' + paperwidth;
2417                 result += ',' + paperheight;
2418         } else {
2419                 string const paper_option = paperSizeName(DVIPS);
2420                 if (!paper_option.empty() && (paper_option != "letter" ||
2421                     orientation != ORIENTATION_LANDSCAPE)) {
2422                         // dvips won't accept -t letter -t landscape.
2423                         // In all other cases, include the paper size
2424                         // explicitly.
2425                         result = lyxrc.print_paper_flag;
2426                         result += ' ' + paper_option;
2427                 }
2428         }
2429         if (orientation == ORIENTATION_LANDSCAPE &&
2430             papersize != PAPER_CUSTOM)
2431                 result += ' ' + lyxrc.print_landscape_flag;
2432         return result;
2433 }
2434
2435
2436 string const BufferParams::font_encoding() const
2437 {
2438         return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2439 }
2440
2441
2442 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2443 {
2444         if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2445                 return lyxrc.language_custom_package;
2446         // suppress the babel call if there is no BabelName defined
2447         // for the document language in the lib/languages file and if no
2448         // other languages are used (lang_opts is then empty)
2449         if (lang_opts.empty())
2450                 return string();
2451         // either a specific language (AsBabelOptions setting in
2452         // lib/languages) or the prefs require the languages to
2453         // be submitted to babel itself (not the class).
2454         if (langoptions)
2455                 return "\\usepackage[" + lang_opts + "]{babel}";
2456         return "\\usepackage{babel}";
2457 }
2458
2459
2460 docstring BufferParams::getGraphicsDriver(string const & package) const
2461 {
2462         docstring result;
2463
2464         if (package == "geometry") {
2465                 if (graphics_driver == "dvips"
2466                     || graphics_driver == "dvipdfm"
2467                     || graphics_driver == "pdftex"
2468                     || graphics_driver == "vtex")
2469                         result = from_ascii(graphics_driver);
2470                 else if (graphics_driver == "dvipdfmx")
2471                         result = from_ascii("dvipdfm");
2472         }
2473
2474         return result;
2475 }
2476
2477
2478 void BufferParams::writeEncodingPreamble(odocstream & os,
2479                 LaTeXFeatures & features, TexRow & texrow) const
2480 {
2481         // XeTeX does not need this
2482         if (features.runparams().flavor == OutputParams::XETEX)
2483                 return;
2484         // LuaTeX neither, but with tex fonts, we need to load
2485         // the luainputenc package.
2486         if (features.runparams().flavor == OutputParams::LUATEX) {
2487                 if (!useNonTeXFonts) {
2488                         os << "\\usepackage[utf8]{luainputenc}\n";
2489                         texrow.newline();
2490                 }
2491                 return;
2492         }
2493         if (inputenc == "auto") {
2494                 string const doc_encoding =
2495                         language->encoding()->latexName();
2496                 Encoding::Package const package =
2497                         language->encoding()->package();
2498
2499                 // Create a list with all the input encodings used
2500                 // in the document
2501                 set<string> encodings =
2502                         features.getEncodingSet(doc_encoding);
2503
2504                 // If the "japanese" package (i.e. pLaTeX) is used,
2505                 // inputenc must be omitted.
2506                 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2507                 if (package == Encoding::japanese)
2508                      features.require("japanese");
2509
2510                 if ((!encodings.empty() || package == Encoding::inputenc)
2511                     && !features.isRequired("japanese")) {
2512                         os << "\\usepackage[";
2513                         set<string>::const_iterator it = encodings.begin();
2514                         set<string>::const_iterator const end = encodings.end();
2515                         if (it != end) {
2516                                 os << from_ascii(*it);
2517                                 ++it;
2518                         }
2519                         for (; it != end; ++it)
2520                                 os << ',' << from_ascii(*it);
2521                         if (package == Encoding::inputenc) {
2522                                 if (!encodings.empty())
2523                                         os << ',';
2524                                 os << from_ascii(doc_encoding);
2525                         }
2526                         os << "]{inputenc}\n";
2527                         texrow.newline();
2528                 }
2529                 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2530                         if (language->encoding()->name() == "utf8-cjk"
2531                             && LaTeXFeatures::isAvailable("CJKutf8"))
2532                                 os << "\\usepackage{CJKutf8}\n";
2533                         else
2534                                 os << "\\usepackage{CJK}\n";
2535                         texrow.newline();
2536                 }
2537         } else if (inputenc != "default") {
2538                 switch (encoding().package()) {
2539                 case Encoding::none:
2540                 case Encoding::japanese:
2541                         break;
2542                 case Encoding::inputenc:
2543                         // do not load inputenc if japanese is used
2544                         if (features.isRequired("japanese"))
2545                                 break;
2546                         os << "\\usepackage[" << from_ascii(inputenc)
2547                            << "]{inputenc}\n";
2548                         texrow.newline();
2549                         break;
2550                 case Encoding::CJK:
2551                         if (encoding().name() == "utf8-cjk"
2552                             && LaTeXFeatures::isAvailable("CJKutf8"))
2553                                 os << "\\usepackage{CJKutf8}\n";
2554                         else
2555                                 os << "\\usepackage{CJK}\n";
2556                         texrow.newline();
2557                         break;
2558                 }
2559         }
2560
2561         // The encoding "armscii8" (for Armenian) is only available when
2562         // the package "armtex" is loaded.
2563         if (language->encoding()->latexName() == "armscii8"
2564             || inputenc == "armscii8") {
2565                 os << "\\usepackage{armtex}\n";
2566                 texrow.newline();
2567         }
2568 }
2569
2570
2571 string const BufferParams::parseFontName(string const & name) const
2572 {
2573         string mangled = name;
2574         size_t const idx = mangled.find('[');
2575         if (idx == string::npos || idx == 0)
2576                 return mangled;
2577         else
2578                 return mangled.substr(0, idx - 1);
2579 }
2580
2581
2582 string const BufferParams::loadFonts(string const & rm,
2583                                      string const & sf, string const & tt,
2584                                      bool const & sc, bool const & osf,
2585                                      int const & sfscale, int const & ttscale,
2586                                      bool const & use_systemfonts) const
2587 {
2588         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2589            several packages have been replaced by others, that might not
2590            be installed on every system. We have to take care for that
2591            (see psnfss.pdf). We try to support all psnfss fonts as well
2592            as the fonts that have become de facto standard in the LaTeX
2593            world (e.g. Latin Modern). We do not support obsolete fonts
2594            (like PSLatex). In general, it should be possible to mix any
2595            rm font with any sf or tt font, respectively. (JSpitzm)
2596            TODO:
2597                 -- separate math fonts.
2598         */
2599
2600         if (rm == "default" && sf == "default" && tt == "default")
2601                 //nothing to do
2602                 return string();
2603
2604         ostringstream os;
2605
2606         /* Fontspec (XeTeX, LuaTeX): we provide GUI support for oldstyle
2607          * numbers (Numbers=OldStyle) and sf/tt scaling. The Ligatures=TeX
2608          * option assures TeX ligatures (such as "--") are resolved.
2609          * Note that tt does not use these ligatures.
2610          * TODO:
2611          *    -- add more GUI options?
2612          *    -- add more fonts (fonts for other scripts)
2613          *    -- if there's a way to find out if a font really supports
2614          *       OldStyle, enable/disable the widget accordingly. 
2615         */
2616         if (use_systemfonts) {
2617                 if (rm != "default") {
2618                         os << "\\setmainfont[Ligatures=TeX";
2619                         if (osf)
2620                                 os << ",Numbers=OldStyle";
2621                         os << "]{" << parseFontName(rm) << "}\n";
2622                 }
2623                 if (sf != "default") {
2624                         string const sans = parseFontName(sf);
2625                         if (sfscale != 100)
2626                                 os << "\\setsansfont[Scale=" 
2627                                    << float(sfscale) / 100 
2628                                    << ",Ligatures=TeX]{"
2629                                    << sans << "}\n";
2630                         else
2631                                 os << "\\setsansfont[Ligatures=TeX]{"
2632                                    << sans << "}\n";
2633                 }
2634                 if (tt != "default") {
2635                         string const mono = parseFontName(tt);
2636                         if (ttscale != 100)
2637                                 os << "\\setmonofont[Scale=" 
2638                                    << float(ttscale) / 100 
2639                                    << "]{"
2640                                    << mono << "}\n";
2641                         else
2642                                 os << "\\setmonofont{"
2643                                    << mono << "}\n";
2644                 }
2645                 return os.str();
2646         }
2647
2648         // ROMAN FONTS
2649         // Computer Modern (must be explicitly selectable -- there might be classes
2650         // that define a different default font!
2651         if (rm == "cmr") {
2652                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2653                 // osf for Computer Modern needs eco.sty
2654                 if (osf)
2655                         os << "\\usepackage{eco}\n";
2656         }
2657         // Latin Modern Roman
2658         else if (rm == "lmodern")
2659                 os << "\\usepackage{lmodern}\n";
2660         // AE
2661         else if (rm == "ae") {
2662                 // not needed when using OT1 font encoding.
2663                 if (font_encoding() != "default")
2664                         os << "\\usepackage{ae,aecompl}\n";
2665         }
2666         // Times
2667         else if (rm == "times") {
2668                 // try to load the best available package
2669                 if (LaTeXFeatures::isAvailable("mathptmx"))
2670                         os << "\\usepackage{mathptmx}\n";
2671                 else if (LaTeXFeatures::isAvailable("mathptm"))
2672                         os << "\\usepackage{mathptm}\n";
2673                 else
2674                         os << "\\usepackage{times}\n";
2675         }
2676         // Palatino
2677         else if (rm == "palatino") {
2678                 // try to load the best available package
2679                 if (LaTeXFeatures::isAvailable("mathpazo")) {
2680                         os << "\\usepackage";
2681                         if (osf || sc) {
2682                                 os << '[';
2683                                 if (!osf)
2684                                         os << "sc";
2685                                 else
2686                                         // "osf" includes "sc"!
2687                                         os << "osf";
2688                                 os << ']';
2689                         }
2690                         os << "{mathpazo}\n";
2691                 }
2692                 else if (LaTeXFeatures::isAvailable("mathpple"))
2693                         os << "\\usepackage{mathpple}\n";
2694                 else
2695                         os << "\\usepackage{palatino}\n";
2696         }
2697         // Utopia
2698         else if (rm == "utopia") {
2699                 // fourier supersedes utopia.sty, but does
2700                 // not work with OT1 encoding.
2701                 if (LaTeXFeatures::isAvailable("fourier")
2702                     && font_encoding() != "default") {
2703                         os << "\\usepackage";
2704                         if (osf || sc) {
2705                                 os << '[';
2706                                 if (sc)
2707                                         os << "expert";
2708                                 if (osf && sc)
2709                                         os << ',';
2710                                 if (osf)
2711                                         os << "oldstyle";
2712                                 os << ']';
2713                         }
2714                         os << "{fourier}\n";
2715                 }
2716                 else
2717                         os << "\\usepackage{utopia}\n";
2718         }
2719         // Bera (complete fontset)
2720         else if (rm == "bera" && sf == "default" && tt == "default")
2721                 os << "\\usepackage{bera}\n";
2722         // everything else
2723         else if (rm != "default")
2724                 os << "\\usepackage" << "{" << rm << "}\n";
2725
2726         // SANS SERIF
2727         // Helvetica, Bera Sans
2728         if (sf == "helvet" || sf == "berasans") {
2729                 if (sfscale != 100)
2730                         os << "\\usepackage[scaled=" << float(sfscale) / 100
2731                            << "]{" << sf << "}\n";
2732                 else
2733                         os << "\\usepackage{" << sf << "}\n";
2734         }
2735         // Avant Garde
2736         else if (sf == "avant")
2737                 os << "\\usepackage{" << sf << "}\n";
2738         // Computer Modern, Latin Modern, CM Bright
2739         else if (sf != "default")
2740                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2741
2742         // monospaced/typewriter
2743         // Courier, LuxiMono
2744         if (tt == "luximono" || tt == "beramono") {
2745                 if (ttscale != 100)
2746                         os << "\\usepackage[scaled=" << float(ttscale) / 100
2747                            << "]{" << tt << "}\n";
2748                 else
2749                         os << "\\usepackage{" << tt << "}\n";
2750         }
2751         // Courier
2752         else if (tt == "courier" )
2753                 os << "\\usepackage{" << tt << "}\n";
2754         // Computer Modern, Latin Modern, CM Bright
2755         else if (tt != "default")
2756                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2757
2758         return os.str();
2759 }
2760
2761
2762 Encoding const & BufferParams::encoding() const
2763 {
2764         // FIXME: actually, we should check for the flavor
2765         // or runparams.isFullyUnicode() here:
2766         // This check will not work with XeTeX/LuaTeX and tex fonts.
2767         // Thus we have to reset the encoding in Buffer::makeLaTeXFile.
2768         if (useNonTeXFonts)
2769                 return *(encodings.fromLaTeXName("utf8-plain"));
2770         if (inputenc == "auto" || inputenc == "default")
2771                 return *language->encoding();
2772         Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2773         if (enc)
2774                 return *enc;
2775         LYXERR0("Unknown inputenc value `" << inputenc
2776                << "'. Using `auto' instead.");
2777         return *language->encoding();
2778 }
2779
2780
2781 CiteEngine BufferParams::citeEngine() const
2782 {
2783         // FIXME the class should provide the numerical/
2784         // authoryear choice
2785         if (documentClass().provides("natbib")
2786             && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2787                 return ENGINE_NATBIB_AUTHORYEAR;
2788         return cite_engine_;
2789 }
2790
2791
2792 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2793 {
2794         cite_engine_ = cite_engine;
2795 }
2796
2797 } // namespace lyx