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