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