]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
further xetex disambiguation: use the flavor where the flavor is apt.
[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         fontsRoman = "default";
379         fontsSans = "default";
380         fontsTypewriter = "default";
381         fontsDefaultFamily = "default";
382         useXetex = false;
383         fontsSC = false;
384         fontsOSF = false;
385         fontsSansScale = 100;
386         fontsTypewriterScale = 100;
387         inputenc = "auto";
388         graphicsDriver = "default";
389         defaultOutputFormat = "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 >> defaultOutputFormat;
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                 fontsRoman = lex.getString();
622         } else if (token == "\\font_sans") {
623                 lex.eatLine();
624                 fontsSans = lex.getString();
625         } else if (token == "\\font_typewriter") {
626                 lex.eatLine();
627                 fontsTypewriter = lex.getString();
628         } else if (token == "\\font_default_family") {
629                 lex >> fontsDefaultFamily;
630         } else if (token == "\\use_xetex") {
631                 lex >> useXetex;
632         } else if (token == "\\font_sc") {
633                 lex >> fontsSC;
634         } else if (token == "\\font_osf") {
635                 lex >> fontsOSF;
636         } else if (token == "\\font_sf_scale") {
637                 lex >> fontsSansScale;
638         } else if (token == "\\font_tt_scale") {
639                 lex >> fontsTypewriterScale;
640         } else if (token == "\\font_cjk") {
641                 lex >> fontsCJK;
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 (!removedModules_.empty()) {
906                 os << "\\begin_removed_modules" << '\n';
907                 list<string>::const_iterator it = removedModules_.begin();
908                 list<string>::const_iterator en = removedModules_.end();
909                 for (; it != en; it++)
910                         os << *it << '\n';
911                 os << "\\end_removed_modules" << '\n';
912         }
913
914         // the modules
915         if (!layoutModules_.empty()) {
916                 os << "\\begin_modules" << '\n';
917                 LayoutModuleList::const_iterator it = layoutModules_.begin();
918                 LayoutModuleList::const_iterator en = layoutModules_.end();
919                 for (; it != en; it++)
920                         os << *it << '\n';
921                 os << "\\end_modules" << '\n';
922         }
923
924         // includeonly
925         if (!includedChildren_.empty()) {
926                 os << "\\begin_includeonly" << '\n';
927                 list<string>::const_iterator it = includedChildren_.begin();
928                 list<string>::const_iterator en = includedChildren_.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 " << fontsRoman
951            << "\n\\font_sans " << fontsSans
952            << "\n\\font_typewriter " << fontsTypewriter
953            << "\n\\font_default_family " << fontsDefaultFamily
954            << "\n\\use_xetex " << convert<string>(useXetex)
955            << "\n\\font_sc " << convert<string>(fontsSC)
956            << "\n\\font_osf " << convert<string>(fontsOSF)
957            << "\n\\font_sf_scale " << fontsSansScale
958            << "\n\\font_tt_scale " << fontsTypewriterScale
959            << '\n';
960         if (!fontsCJK.empty()) {
961                 os << "\\font_cjk " << fontsCJK << '\n';
962         }
963         os << "\n\\graphics " << graphicsDriver << '\n';
964         os << "\\default_output_format " << defaultOutputFormat << '\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::PDFLATEX:
1124                 case OutputParams::XETEX:
1125                         if (xcolorulem) {
1126                                 features.require("ct-xcolor-ulem");
1127                                 features.require("ulem");
1128                                 features.require("xcolor");
1129                                 // improves color handling in PDF output
1130                                 features.require("pdfcolmk"); 
1131                         } else {
1132                                 features.require("ct-none");
1133                         }
1134                         break;
1135                 default:
1136                         break;
1137                 }
1138         }
1139
1140         // Floats with 'Here definitely' as default setting.
1141         if (float_placement.find('H') != string::npos)
1142                 features.require("float");
1143
1144         // AMS Style is at document level
1145         if (use_amsmath == package_on
1146             || documentClass().provides("amsmath"))
1147                 features.require("amsmath");
1148         if (use_esint == package_on)
1149                 features.require("esint");
1150         if (use_mhchem == package_on)
1151                 features.require("mhchem");
1152         if (use_mathdots == package_on)
1153                 features.require("mathdots");
1154
1155         // Document-level line spacing
1156         if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
1157                 features.require("setspace");
1158
1159         // the bullet shapes are buffer level not paragraph level
1160         // so they are tested here
1161         for (int i = 0; i < 4; ++i) {
1162                 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) 
1163                         continue;
1164                 int const font = user_defined_bullet(i).getFont();
1165                 if (font == 0) {
1166                         int const c = user_defined_bullet(i).getCharacter();
1167                         if (c == 16
1168                             || c == 17
1169                             || c == 25
1170                             || c == 26
1171                             || c == 31) {
1172                                 features.require("latexsym");
1173                         }
1174                 } else if (font == 1) {
1175                         features.require("amssymb");
1176                 } else if (font >= 2 && font <= 5) {
1177                         features.require("pifont");
1178                 }
1179         }
1180
1181         if (pdfoptions().use_hyperref) {
1182                 features.require("hyperref");
1183                 // due to interferences with babel and hyperref, the color package has to
1184                 // be loaded after hyperref when hyperref is used with the colorlinks
1185                 // option, see http://www.lyx.org/trac/ticket/5291
1186                 if (pdfoptions().colorlinks)
1187                         features.require("color");
1188         }
1189
1190         if (features.runparams().flavor == OutputParams::XETEX)
1191                 features.require("polyglossia");
1192
1193         if (language->lang() == "vietnamese")
1194                 features.require("vietnamese");
1195         else if (language->lang() == "japanese")
1196                 features.require("japanese");
1197 }
1198
1199
1200 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
1201                               TexRow & texrow, FileName const & filepath) const
1202 {
1203         os << "\\documentclass";
1204
1205         DocumentClass const & tclass = documentClass();
1206
1207         ostringstream clsoptions; // the document class options.
1208
1209         if (tokenPos(tclass.opt_fontsize(),
1210                      '|', fontsize) >= 0) {
1211                 // only write if existing in list (and not default)
1212                 clsoptions << fontsize << "pt,";
1213         }
1214
1215         // all paper sizes except of A4, A5, B5 and the US sizes need the
1216         // geometry package
1217         bool nonstandard_papersize = papersize != PAPER_DEFAULT
1218                 && papersize != PAPER_USLETTER
1219                 && papersize != PAPER_USLEGAL
1220                 && papersize != PAPER_USEXECUTIVE
1221                 && papersize != PAPER_A4
1222                 && papersize != PAPER_A5
1223                 && papersize != PAPER_B5;
1224
1225         if (!use_geometry) {
1226                 switch (papersize) {
1227                 case PAPER_A4:
1228                         clsoptions << "a4paper,";
1229                         break;
1230                 case PAPER_USLETTER:
1231                         clsoptions << "letterpaper,";
1232                         break;
1233                 case PAPER_A5:
1234                         clsoptions << "a5paper,";
1235                         break;
1236                 case PAPER_B5:
1237                         clsoptions << "b5paper,";
1238                         break;
1239                 case PAPER_USEXECUTIVE:
1240                         clsoptions << "executivepaper,";
1241                         break;
1242                 case PAPER_USLEGAL:
1243                         clsoptions << "legalpaper,";
1244                         break;
1245                 case PAPER_DEFAULT:
1246                 case PAPER_A0:
1247                 case PAPER_A1:
1248                 case PAPER_A2:
1249                 case PAPER_A3:
1250                 case PAPER_A6:
1251                 case PAPER_B0:
1252                 case PAPER_B1:
1253                 case PAPER_B2:
1254                 case PAPER_B3:
1255                 case PAPER_B4:
1256                 case PAPER_B6:
1257                 case PAPER_C0:
1258                 case PAPER_C1:
1259                 case PAPER_C2:
1260                 case PAPER_C3:
1261                 case PAPER_C4:
1262                 case PAPER_C5:
1263                 case PAPER_C6:
1264                 case PAPER_JISB0:
1265                 case PAPER_JISB1:
1266                 case PAPER_JISB2:
1267                 case PAPER_JISB3:
1268                 case PAPER_JISB4:
1269                 case PAPER_JISB5:
1270                 case PAPER_JISB6:
1271                 case PAPER_CUSTOM:
1272                         break;
1273                 }
1274         }
1275
1276         // if needed
1277         if (sides != tclass.sides()) {
1278                 switch (sides) {
1279                 case OneSide:
1280                         clsoptions << "oneside,";
1281                         break;
1282                 case TwoSides:
1283                         clsoptions << "twoside,";
1284                         break;
1285                 }
1286         }
1287
1288         // if needed
1289         if (columns != tclass.columns()) {
1290                 if (columns == 2)
1291                         clsoptions << "twocolumn,";
1292                 else
1293                         clsoptions << "onecolumn,";
1294         }
1295
1296         if (!use_geometry
1297             && orientation == ORIENTATION_LANDSCAPE)
1298                 clsoptions << "landscape,";
1299
1300         // language should be a parameter to \documentclass
1301         if (language->babel() == "hebrew"
1302             && default_language->babel() != "hebrew")
1303                 // This seems necessary
1304                 features.useLanguage(default_language);
1305
1306         ostringstream language_options;
1307         bool const use_babel = features.useBabel() && !tclass.provides("babel");
1308         bool const use_polyglossia = features.usePolyglossia();
1309         bool const global = lyxrc.language_global_options;
1310         if (use_babel || (use_polyglossia && global)) {
1311                 language_options << features.getLanguages();
1312                 if (!language->babel().empty()) {
1313                         if (!language_options.str().empty())
1314                                 language_options << ',';
1315                         language_options << language->babel();
1316                 }
1317                 if (global && !features.needBabelLangOptions())
1318                         clsoptions << language_options.str() << ',';
1319         }
1320
1321         // the predefined options from the layout
1322         if (use_default_options && !tclass.options().empty())
1323                 clsoptions << tclass.options() << ',';
1324
1325         // the user-defined options
1326         if (!options.empty()) {
1327                 clsoptions << options << ',';
1328         }
1329
1330         string strOptions(clsoptions.str());
1331         if (!strOptions.empty()) {
1332                 strOptions = rtrim(strOptions, ",");
1333                 // FIXME UNICODE
1334                 os << '[' << from_utf8(strOptions) << ']';
1335         }
1336
1337         os << '{' << from_ascii(tclass.latexname()) << "}\n";
1338         texrow.newline();
1339         // end of \documentclass defs
1340
1341         if (useXetex) {
1342                 os << "\\usepackage{fontspec}\n";
1343                 texrow.newline();
1344         }
1345
1346         // font selection must be done before loading fontenc.sty
1347         string const fonts =
1348                 loadFonts(fontsRoman, fontsSans,
1349                           fontsTypewriter, fontsSC, fontsOSF,
1350                           fontsSansScale, fontsTypewriterScale, useXetex);
1351         if (!fonts.empty()) {
1352                 os << from_ascii(fonts);
1353                 texrow.newline();
1354         }
1355         if (fontsDefaultFamily != "default")
1356                 os << "\\renewcommand{\\familydefault}{\\"
1357                    << from_ascii(fontsDefaultFamily) << "}\n";
1358
1359         // set font encoding
1360         // for arabic_arabi and farsi we also need to load the LAE and
1361         // LFE encoding
1362         // XeTeX (isFullUnicode() flavor) works without fontenc
1363         if (font_encoding() != "default" && language->lang() != "japanese"
1364             && !features.runparams().isFullUnicode() && !tclass.provides("fontenc")) {
1365                 size_t fars = language_options.str().find("farsi");
1366                 size_t arab = language_options.str().find("arabic");
1367                 if (language->lang() == "arabic_arabi"
1368                         || language->lang() == "farsi" || fars != string::npos
1369                         || arab != string::npos) {
1370                         os << "\\usepackage[" << from_ascii(font_encoding())
1371                            << ",LFE,LAE]{fontenc}\n";
1372                         texrow.newline();
1373                 } else {
1374                         os << "\\usepackage[" << from_ascii(font_encoding())
1375                            << "]{fontenc}\n";
1376                         texrow.newline();
1377                 }
1378         }
1379
1380         // handle inputenc etc.
1381         writeEncodingPreamble(os, features, texrow);
1382
1383         // includeonly
1384         if (!features.runparams().includeall && !includedChildren_.empty()) {
1385                 os << "\\includeonly{";
1386                 list<string>::const_iterator it = includedChildren_.begin();
1387                 bool first = true;
1388                 for (; it != includedChildren_.end() ; ++it) {
1389                         string incfile = *it;
1390                         FileName inc = makeAbsPath(incfile, filepath.absFileName());
1391                         string mangled = DocFileName(changeExtension(inc.absFileName(), ".tex")).
1392                         mangledFileName();
1393                         if (!features.runparams().nice)
1394                                 incfile = mangled;
1395                         // \includeonly doesn't want an extension 
1396                         incfile = changeExtension(incfile, string());
1397                         incfile = support::latex_path(incfile);
1398                         if (!incfile.empty()) {
1399                                 if (!first)
1400                                         os << ",";
1401                                 os << from_utf8(incfile);
1402                         }
1403                         first = false;
1404                 }
1405                 os << "}\n";
1406         }
1407
1408         if (!listings_params.empty() || features.isRequired("listings")) {
1409                 os << "\\usepackage{listings}\n";
1410                 texrow.newline();
1411         }
1412         if (!listings_params.empty()) {
1413                 os << "\\lstset{";
1414                 // do not test validity because listings_params is 
1415                 // supposed to be valid
1416                 string par =
1417                         InsetListingsParams(listings_params).separatedParams(true);
1418                 // we can't support all packages, but we should load the color package
1419                 if (par.find("\\color", 0) != string::npos)
1420                         features.require("color");
1421                 os << from_utf8(par);
1422                 // count the number of newlines
1423                 for (size_t i = 0; i < par.size(); ++i)
1424                         if (par[i] == '\n')
1425                                 texrow.newline();
1426                 os << "}\n";
1427                 texrow.newline();
1428         }
1429         if (!tclass.provides("geometry")
1430             && (use_geometry || nonstandard_papersize)) {
1431                 odocstringstream ods;
1432                 if (!getGraphicsDriver("geometry").empty())
1433                         ods << getGraphicsDriver("geometry");
1434                 if (orientation == ORIENTATION_LANDSCAPE)
1435                         ods << ",landscape";
1436                 switch (papersize) {
1437                 case PAPER_CUSTOM:
1438                         if (!paperwidth.empty())
1439                                 ods << ",paperwidth="
1440                                    << from_ascii(paperwidth);
1441                         if (!paperheight.empty())
1442                                 ods << ",paperheight="
1443                                    << from_ascii(paperheight);
1444                         break;
1445                 case PAPER_USLETTER:
1446                         ods << ",letterpaper";
1447                         break;
1448                 case PAPER_USLEGAL:
1449                         ods << ",legalpaper";
1450                         break;
1451                 case PAPER_USEXECUTIVE:
1452                         ods << ",executivepaper";
1453                         break;
1454                 case PAPER_A0:
1455                         ods << ",a0paper";
1456                         break;
1457                 case PAPER_A1:
1458                         ods << ",a1paper";
1459                         break;
1460                 case PAPER_A2:
1461                         ods << ",a2paper";
1462                         break;
1463                 case PAPER_A3:
1464                         ods << ",a3paper";
1465                         break;
1466                 case PAPER_A4:
1467                         ods << ",a4paper";
1468                         break;
1469                 case PAPER_A5:
1470                         ods << ",a5paper";
1471                         break;
1472                 case PAPER_A6:
1473                         ods << ",a6paper";
1474                         break;
1475                 case PAPER_B0:
1476                         ods << ",b0paper";
1477                         break;
1478                 case PAPER_B1:
1479                         ods << ",b1paper";
1480                         break;
1481                 case PAPER_B2:
1482                         ods << ",b2paper";
1483                         break;
1484                 case PAPER_B3:
1485                         ods << ",b3paper";
1486                         break;
1487                 case PAPER_B4:
1488                         ods << ",b4paper";
1489                         break;
1490                 case PAPER_B5:
1491                         ods << ",b5paper";
1492                         break;
1493                 case PAPER_B6:
1494                         ods << ",b6paper";
1495                         break;
1496                 case PAPER_C0:
1497                         ods << ",c0paper";
1498                         break;
1499                 case PAPER_C1:
1500                         ods << ",c1paper";
1501                         break;
1502                 case PAPER_C2:
1503                         ods << ",c2paper";
1504                         break;
1505                 case PAPER_C3:
1506                         ods << ",c3paper";
1507                         break;
1508                 case PAPER_C4:
1509                         ods << ",c4paper";
1510                         break;
1511                 case PAPER_C5:
1512                         ods << ",c5paper";
1513                         break;
1514                 case PAPER_C6:
1515                         ods << ",c6paper";
1516                         break;
1517                 case PAPER_JISB0:
1518                         ods << ",b0j";
1519                         break;
1520                 case PAPER_JISB1:
1521                         ods << ",b1j";
1522                         break;
1523                 case PAPER_JISB2:
1524                         ods << ",b2j";
1525                         break;
1526                 case PAPER_JISB3:
1527                         ods << ",b3j";
1528                         break;
1529                 case PAPER_JISB4:
1530                         ods << ",b4j";
1531                         break;
1532                 case PAPER_JISB5:
1533                         ods << ",b5j";
1534                         break;
1535                 case PAPER_JISB6:
1536                         ods << ",b6j";
1537                         break;
1538                 default:
1539                         // default papersize ie PAPER_DEFAULT
1540                         switch (lyxrc.default_papersize) {
1541                         case PAPER_DEFAULT: // keep compiler happy
1542                         case PAPER_USLETTER:
1543                                 ods << ",letterpaper";
1544                                 break;
1545                         case PAPER_USLEGAL:
1546                                 ods << ",legalpaper";
1547                                 break;
1548                         case PAPER_USEXECUTIVE:
1549                                 ods << ",executivepaper";
1550                                 break;
1551                         case PAPER_A3:
1552                                 ods << ",a3paper";
1553                                 break;
1554                         case PAPER_A4:
1555                                 ods << ",a4paper";
1556                                 break;
1557                         case PAPER_A5:
1558                                 ods << ",a5paper";
1559                                 break;
1560                         case PAPER_B5:
1561                                 ods << ",b5paper";
1562                                 break;
1563                         case PAPER_A0:
1564                         case PAPER_A1:
1565                         case PAPER_A2:
1566                         case PAPER_A6:
1567                         case PAPER_B0:
1568                         case PAPER_B1:
1569                         case PAPER_B2:
1570                         case PAPER_B3:
1571                         case PAPER_B4:
1572                         case PAPER_B6:
1573                         case PAPER_C0:
1574                         case PAPER_C1:
1575                         case PAPER_C2:
1576                         case PAPER_C3:
1577                         case PAPER_C4:
1578                         case PAPER_C5:
1579                         case PAPER_C6:
1580                         case PAPER_JISB0:
1581                         case PAPER_JISB1:
1582                         case PAPER_JISB2:
1583                         case PAPER_JISB3:
1584                         case PAPER_JISB4:
1585                         case PAPER_JISB5:
1586                         case PAPER_JISB6:
1587                         case PAPER_CUSTOM:
1588                                 break;
1589                         }
1590                 }
1591                 docstring const g_options = trim(ods.str(), ",");
1592                 os << "\\usepackage";
1593                 if (!g_options.empty())
1594                         os << '[' << g_options << ']';
1595                 os << "{geometry}\n";
1596                 texrow.newline();
1597                 // output this only if use_geometry is true
1598                 if (use_geometry) {
1599                         os << "\\geometry{verbose";
1600                         if (!topmargin.empty())
1601                                 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1602                         if (!bottommargin.empty())
1603                                 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1604                         if (!leftmargin.empty())
1605                                 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1606                         if (!rightmargin.empty())
1607                                 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1608                         if (!headheight.empty())
1609                                 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1610                         if (!headsep.empty())
1611                                 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1612                         if (!footskip.empty())
1613                                 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1614                         if (!columnsep.empty())
1615                                 os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1616                         os << "}\n";
1617                         texrow.newline();
1618                 }
1619         } else if (orientation == ORIENTATION_LANDSCAPE
1620                    || papersize != PAPER_DEFAULT) {
1621                 features.require("papersize");
1622         }
1623
1624         if (tokenPos(tclass.opt_pagestyle(),
1625                      '|', pagestyle) >= 0) {
1626                 if (pagestyle == "fancy") {
1627                         os << "\\usepackage{fancyhdr}\n";
1628                         texrow.newline();
1629                 }
1630                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1631                 texrow.newline();
1632         }
1633
1634         // only output when the background color is not default
1635         if (isbackgroundcolor == true) {
1636                 // only require color here, the background color will be defined
1637                 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1638                 // package pdfpages 
1639                 features.require("color");
1640                 features.require("pagecolor");
1641         }
1642
1643         // only output when the font color is not default
1644         if (isfontcolor == true) {
1645                 // only require color here, the font color will be defined
1646                 // in LaTeXFeatures.cpp to avoid interferences with the LaTeX
1647                 // package pdfpages 
1648                 features.require("color");
1649                 features.require("fontcolor");
1650         }
1651
1652         // Only if class has a ToC hierarchy
1653         if (tclass.hasTocLevels()) {
1654                 if (secnumdepth != tclass.secnumdepth()) {
1655                         os << "\\setcounter{secnumdepth}{"
1656                            << secnumdepth
1657                            << "}\n";
1658                         texrow.newline();
1659                 }
1660                 if (tocdepth != tclass.tocdepth()) {
1661                         os << "\\setcounter{tocdepth}{"
1662                            << tocdepth
1663                            << "}\n";
1664                         texrow.newline();
1665                 }
1666         }
1667
1668         if (paragraph_separation) {
1669                 // when skip separation
1670                 switch (getDefSkip().kind()) {
1671                 case VSpace::SMALLSKIP:
1672                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1673                         break;
1674                 case VSpace::MEDSKIP:
1675                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1676                         break;
1677                 case VSpace::BIGSKIP:
1678                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1679                         break;
1680                 case VSpace::LENGTH:
1681                         os << "\\setlength{\\parskip}{"
1682                            << from_utf8(getDefSkip().length().asLatexString())
1683                            << "}\n";
1684                         break;
1685                 default: // should never happen // Then delete it.
1686                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1687                         break;
1688                 }
1689                 texrow.newline();
1690                 os << "\\setlength{\\parindent}{0pt}\n";
1691                 texrow.newline();
1692         } else {
1693                 // when separation by indentation
1694                 // only output something when a width is given
1695                 if (getIndentation().asLyXCommand() != "default") {
1696                         os << "\\setlength{\\parindent}{"
1697                                 << from_utf8(getIndentation().asLatexCommand())
1698                            << "}\n";
1699                         texrow.newline();
1700                 }
1701         }
1702
1703         // Now insert the LyX specific LaTeX commands...
1704         docstring lyxpreamble;
1705
1706         if (output_sync) {
1707                 if (!output_sync_macro.empty())
1708                         lyxpreamble += from_utf8(output_sync_macro) +"\n";
1709                 else if (features.runparams().flavor == OutputParams::LATEX)
1710                         lyxpreamble += "\\usepackage[active]{srcltx}\n";
1711                 else if (features.runparams().flavor == OutputParams::PDFLATEX)
1712                         lyxpreamble += "\\synctex=-1\n";
1713         }
1714
1715         // due to interferences with babel and hyperref, the color package has to
1716         // be loaded (when it is not already loaded) before babel when hyperref
1717         // is used with the colorlinks option, see
1718         // http://www.lyx.org/trac/ticket/5291
1719         // we decided therefore to load color always before babel, see
1720         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1721         lyxpreamble += from_ascii(features.getColorOptions());
1722         
1723         // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1724         if (use_babel
1725             && (features.isRequired("jurabib")
1726                 || features.isRequired("hyperref")
1727                 || features.isRequired("vietnamese")
1728                 || features.isRequired("japanese"))) {
1729                         // FIXME UNICODE
1730                         lyxpreamble += from_utf8(features.getBabelPresettings());
1731                         lyxpreamble += from_utf8(babelCall(language_options.str(),
1732                                                            features.needBabelLangOptions())) + '\n';
1733                         lyxpreamble += from_utf8(features.getBabelPostsettings());
1734         }
1735
1736         // The optional packages;
1737         lyxpreamble += from_ascii(features.getPackages());
1738
1739         // Additional Indices
1740         if (features.isRequired("splitidx")) {
1741                 IndicesList::const_iterator iit = indiceslist().begin();
1742                 IndicesList::const_iterator iend = indiceslist().end();
1743                 for (; iit != iend; ++iit) {
1744                         lyxpreamble += "\\newindex[";
1745                         lyxpreamble += iit->index();
1746                         lyxpreamble += "]{";
1747                         lyxpreamble += iit->shortcut();
1748                         lyxpreamble += "}\n";
1749                 }
1750         }
1751
1752         // Line spacing
1753         lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1754
1755         // PDF support.
1756         // * Hyperref manual: "Make sure it comes last of your loaded
1757         //   packages, to give it a fighting chance of not being over-written,
1758         //   since its job is to redefine many LaTeX commands."
1759         // * Email from Heiko Oberdiek: "It is usually better to load babel
1760         //   before hyperref. Then hyperref has a chance to detect babel.
1761         // * Has to be loaded before the "LyX specific LaTeX commands" to
1762         //   avoid errors with algorithm floats.
1763         // use hyperref explicitly if it is required
1764         if (features.isRequired("hyperref")) {
1765                 // pass what we have to stream here, since we need 
1766                 // to access the stream itself in PDFOptions.
1767                 os << lyxpreamble;
1768
1769                 int lines =
1770                         int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1771
1772                 OutputParams tmp_params = features.runparams();
1773                 lines += pdfoptions().writeLaTeX(tmp_params, os,
1774                                         documentClass().provides("hyperref"));
1775                 texrow.newlines(lines);
1776                 // set back for the rest
1777                 lyxpreamble.clear();
1778         } else if (features.isRequired("nameref"))
1779                 // hyperref loads this automatically
1780                 lyxpreamble += "\\usepackage{nameref}\n";
1781
1782         // Will be surrounded by \makeatletter and \makeatother when not empty
1783         docstring atlyxpreamble;
1784
1785         // Some macros LyX will need
1786         docstring tmppreamble(features.getMacros());
1787
1788         if (!tmppreamble.empty())
1789                 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1790                         "LyX specific LaTeX commands.\n"
1791                         + tmppreamble + '\n';
1792
1793         // the text class specific preamble
1794         tmppreamble = features.getTClassPreamble();
1795         if (!tmppreamble.empty())
1796                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1797                         "Textclass specific LaTeX commands.\n"
1798                         + tmppreamble + '\n';
1799
1800         // suppress date if selected
1801         // use \@ifundefined because we cannot be sure that every document class
1802         // has a \date command
1803         if (suppress_date)
1804                 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1805
1806         /* the user-defined preamble */
1807         if (!containsOnly(preamble, " \n\t"))
1808                 // FIXME UNICODE
1809                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1810                         "User specified LaTeX commands.\n"
1811                         + from_utf8(preamble) + '\n';
1812
1813         // subfig loads internally the LaTeX package "caption". As
1814         // caption is a very popular package, users will load it in
1815         // the preamble. Therefore we must load subfig behind the
1816         // user-defined preamble and check if the caption package was
1817         // loaded or not. For the case that caption is loaded before
1818         // subfig, there is the subfig option "caption=false". This
1819         // option also works when a koma-script class is used and
1820         // koma's own caption commands are used instead of caption. We
1821         // use \PassOptionsToPackage here because the user could have
1822         // already loaded subfig in the preamble.
1823         if (features.isRequired("subfig")) {
1824                 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1825                         " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1826                         "\\usepackage{subfig}\n";
1827         }
1828
1829         // Itemize bullet settings need to be last in case the user
1830         // defines their own bullets that use a package included
1831         // in the user-defined preamble -- ARRae
1832         // Actually it has to be done much later than that
1833         // since some packages like frenchb make modifications
1834         // at \begin{document} time -- JMarc
1835         docstring bullets_def;
1836         for (int i = 0; i < 4; ++i) {
1837                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1838                         if (bullets_def.empty())
1839                                 bullets_def += "\\AtBeginDocument{\n";
1840                         bullets_def += "  \\def\\labelitemi";
1841                         switch (i) {
1842                                 // `i' is one less than the item to modify
1843                         case 0:
1844                                 break;
1845                         case 1:
1846                                 bullets_def += 'i';
1847                                 break;
1848                         case 2:
1849                                 bullets_def += "ii";
1850                                 break;
1851                         case 3:
1852                                 bullets_def += 'v';
1853                                 break;
1854                         }
1855                         bullets_def += '{' +
1856                                 user_defined_bullet(i).getText()
1857                                 + "}\n";
1858                 }
1859         }
1860
1861         if (!bullets_def.empty())
1862                 atlyxpreamble += bullets_def + "}\n\n";
1863
1864         if (!atlyxpreamble.empty())
1865                 lyxpreamble += "\n\\makeatletter\n"
1866                         + atlyxpreamble + "\\makeatother\n\n";
1867
1868         // We try to load babel late, in case it interferes with other packages.
1869         // Jurabib and Hyperref have to be called after babel, though.
1870         if (use_babel && !features.isRequired("jurabib")
1871             && !features.isRequired("hyperref")
1872             && !features.isRequired("vietnamese")
1873             && !features.isRequired("japanese")) {
1874                 // FIXME UNICODE
1875                 lyxpreamble += from_utf8(features.getBabelPresettings());
1876                 lyxpreamble += from_utf8(babelCall(language_options.str(),
1877                                                    features.needBabelLangOptions())) + '\n';
1878                 lyxpreamble += from_utf8(features.getBabelPostsettings());
1879         }
1880
1881         // FIXME Polyglossia?
1882         docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1883         if (!i18npreamble.empty())
1884                 lyxpreamble += i18npreamble + '\n';
1885
1886         int const nlines =
1887                 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1888         texrow.newlines(nlines);
1889
1890         os << lyxpreamble;
1891
1892         // these packages (xunicode, for that matter) need to be loaded at least
1893         // after amsmath, amssymb, esint and the other packages that provide 
1894         // special glyphs
1895         if (features.runparams().flavor == OutputParams::XETEX) {
1896                 os << "\\usepackage{xunicode}\n";
1897                 texrow.newline();
1898                 os << "\\usepackage{xltxtra}\n";
1899                 texrow.newline();
1900         }
1901         // Polyglossia must be loaded after xltxtra
1902         if (use_polyglossia) {
1903                 // call the package
1904                 os << "\\usepackage{polyglossia}\n";
1905                 texrow.newline();
1906                 // set the main language
1907                 os << "\\setdefaultlanguage";
1908                 if (!language->polyglossiaOpts().empty())
1909                         os << "[" << from_ascii(language->polyglossiaOpts()) << "]";
1910                 os << "{" + from_ascii(language->polyglossia()) + "}\n";
1911                 texrow.newline();
1912                 // now setup the other languages
1913                 std::map<std::string, std::string> const polylangs = 
1914                         features.getPolyglossiaLanguages();
1915                 for (std::map<std::string, std::string>::const_iterator mit = polylangs.begin();
1916                      mit != polylangs.end() ; ++mit) {
1917                         os << "\\setotherlanguage";
1918                         if (!mit->second.empty())
1919                                 os << "[" << from_ascii(mit->second) << "]";
1920                         os << "{" << from_ascii(mit->first) << "}\n";
1921                         texrow.newline();
1922                 }
1923         }
1924         return use_babel;
1925 }
1926
1927
1928 void BufferParams::useClassDefaults()
1929 {
1930         DocumentClass const & tclass = documentClass();
1931
1932         sides = tclass.sides();
1933         columns = tclass.columns();
1934         pagestyle = tclass.pagestyle();
1935         use_default_options = true;
1936         // Only if class has a ToC hierarchy
1937         if (tclass.hasTocLevels()) {
1938                 secnumdepth = tclass.secnumdepth();
1939                 tocdepth = tclass.tocdepth();
1940         }
1941 }
1942
1943
1944 bool BufferParams::hasClassDefaults() const
1945 {
1946         DocumentClass const & tclass = documentClass();
1947
1948         return sides == tclass.sides()
1949                 && columns == tclass.columns()
1950                 && pagestyle == tclass.pagestyle()
1951                 && use_default_options
1952                 && secnumdepth == tclass.secnumdepth()
1953                 && tocdepth == tclass.tocdepth();
1954 }
1955
1956
1957 DocumentClass const & BufferParams::documentClass() const
1958 {
1959         return *doc_class_;
1960 }
1961
1962
1963 DocumentClass const * BufferParams::documentClassPtr() const
1964 {
1965         return doc_class_;
1966 }
1967
1968
1969 void BufferParams::setDocumentClass(DocumentClass const * const tc)
1970 {
1971         // evil, but this function is evil
1972         doc_class_ = const_cast<DocumentClass *>(tc);
1973 }
1974
1975
1976 bool BufferParams::setBaseClass(string const & classname)
1977 {
1978         LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1979         LayoutFileList & bcl = LayoutFileList::get();
1980         if (!bcl.haveClass(classname)) {
1981                 docstring s = 
1982                         bformat(_("The layout file:\n"
1983                                 "%1$s\n"
1984                                 "could not be found. A default textclass with default\n"
1985                                 "layouts will be used. LyX will not be able to produce\n"
1986                                 "correct output."),
1987                         from_utf8(classname));
1988                 frontend::Alert::error(_("Document class not found"), s);
1989                 bcl.addEmptyClass(classname);
1990         }
1991
1992         bool const success = bcl[classname].load();
1993         if (!success) {
1994                 docstring s = 
1995                         bformat(_("Due to some error in it, the layout file:\n"
1996                                 "%1$s\n"
1997                                 "could not be loaded. A default textclass with default\n"
1998                                 "layouts will be used. LyX will not be able to produce\n"
1999                                 "correct output."),
2000                         from_utf8(classname));
2001                 frontend::Alert::error(_("Could not load class"), s);
2002                 bcl.addEmptyClass(classname);
2003         }
2004
2005         pimpl_->baseClass_ = classname;
2006         layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
2007         return true;
2008 }
2009
2010
2011 LayoutFile const * BufferParams::baseClass() const
2012 {
2013         if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
2014                 return &(LayoutFileList::get()[pimpl_->baseClass_]);
2015         else 
2016                 return 0;
2017 }
2018
2019
2020 LayoutFileIndex const & BufferParams::baseClassID() const
2021 {
2022         return pimpl_->baseClass_;
2023 }
2024
2025
2026 void BufferParams::makeDocumentClass()
2027 {
2028         if (!baseClass())
2029                 return;
2030
2031         doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
2032
2033         if (!local_layout.empty()) {
2034                 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2035                         docstring const msg = _("Error reading internal layout information");
2036                         frontend::Alert::warning(_("Read Error"), msg);
2037                 }
2038         }
2039 }
2040
2041
2042 bool BufferParams::moduleCanBeAdded(string const & modName) const
2043 {
2044         return layoutModules_.moduleCanBeAdded(modName, baseClass());
2045 }
2046
2047
2048 bool BufferParams::addLayoutModule(string const & modName)
2049 {
2050         LayoutModuleList::const_iterator it = layoutModules_.begin();
2051         LayoutModuleList::const_iterator end = layoutModules_.end();
2052         for (; it != end; it++)
2053                 if (*it == modName) 
2054                         return false;
2055         layoutModules_.push_back(modName);
2056         return true;
2057 }
2058
2059
2060 Font const BufferParams::getFont() const
2061 {
2062         FontInfo f = documentClass().defaultfont();
2063         if (fontsDefaultFamily == "rmdefault")
2064                 f.setFamily(ROMAN_FAMILY);
2065         else if (fontsDefaultFamily == "sfdefault")
2066                 f.setFamily(SANS_FAMILY);
2067         else if (fontsDefaultFamily == "ttdefault")
2068                 f.setFamily(TYPEWRITER_FAMILY);
2069         return Font(f, language);
2070 }
2071
2072
2073 void BufferParams::readPreamble(Lexer & lex)
2074 {
2075         if (lex.getString() != "\\begin_preamble")
2076                 lyxerr << "Error (BufferParams::readPreamble):"
2077                         "consistency check failed." << endl;
2078
2079         preamble = lex.getLongString("\\end_preamble");
2080 }
2081
2082
2083 void BufferParams::readLocalLayout(Lexer & lex)
2084 {
2085         if (lex.getString() != "\\begin_local_layout")
2086                 lyxerr << "Error (BufferParams::readLocalLayout):"
2087                         "consistency check failed." << endl;
2088
2089         local_layout = lex.getLongString("\\end_local_layout");
2090 }
2091
2092
2093 void BufferParams::readLanguage(Lexer & lex)
2094 {
2095         if (!lex.next()) return;
2096
2097         string const tmptok = lex.getString();
2098
2099         // check if tmptok is part of tex_babel in tex-defs.h
2100         language = languages.getLanguage(tmptok);
2101         if (!language) {
2102                 // Language tmptok was not found
2103                 language = default_language;
2104                 lyxerr << "Warning: Setting language `"
2105                        << tmptok << "' to `" << language->lang()
2106                        << "'." << endl;
2107         }
2108 }
2109
2110
2111 void BufferParams::readGraphicsDriver(Lexer & lex)
2112 {
2113         if (!lex.next()) 
2114                 return;
2115
2116         string const tmptok = lex.getString();
2117         // check if tmptok is part of tex_graphics in tex_defs.h
2118         int n = 0;
2119         while (true) {
2120                 string const test = tex_graphics[n++];
2121
2122                 if (test == tmptok) {
2123                         graphicsDriver = tmptok;
2124                         break;
2125                 }
2126                 if (test.empty()) {
2127                         lex.printError(
2128                                 "Warning: graphics driver `$$Token' not recognized!\n"
2129                                 "         Setting graphics driver to `default'.\n");
2130                         graphicsDriver = "default";
2131                         break;
2132                 }
2133         }
2134 }
2135
2136
2137 void BufferParams::readBullets(Lexer & lex)
2138 {
2139         if (!lex.next()) 
2140                 return;
2141
2142         int const index = lex.getInteger();
2143         lex.next();
2144         int temp_int = lex.getInteger();
2145         user_defined_bullet(index).setFont(temp_int);
2146         temp_bullet(index).setFont(temp_int);
2147         lex >> temp_int;
2148         user_defined_bullet(index).setCharacter(temp_int);
2149         temp_bullet(index).setCharacter(temp_int);
2150         lex >> temp_int;
2151         user_defined_bullet(index).setSize(temp_int);
2152         temp_bullet(index).setSize(temp_int);
2153 }
2154
2155
2156 void BufferParams::readBulletsLaTeX(Lexer & lex)
2157 {
2158         // The bullet class should be able to read this.
2159         if (!lex.next()) 
2160                 return;
2161         int const index = lex.getInteger();
2162         lex.next(true);
2163         docstring const temp_str = lex.getDocString();
2164
2165         user_defined_bullet(index).setText(temp_str);
2166         temp_bullet(index).setText(temp_str);
2167 }
2168
2169
2170 void BufferParams::readModules(Lexer & lex)
2171 {
2172         if (!lex.eatLine()) {
2173                 lyxerr << "Error (BufferParams::readModules):"
2174                                 "Unexpected end of input." << endl;
2175                 return;
2176         }
2177         while (true) {
2178                 string mod = lex.getString();
2179                 if (mod == "\\end_modules")
2180                         break;
2181                 addLayoutModule(mod);
2182                 lex.eatLine();
2183         }
2184 }
2185
2186
2187 void BufferParams::readRemovedModules(Lexer & lex)
2188 {
2189         if (!lex.eatLine()) {
2190                 lyxerr << "Error (BufferParams::readRemovedModules):"
2191                                 "Unexpected end of input." << endl;
2192                 return;
2193         }
2194         while (true) {
2195                 string mod = lex.getString();
2196                 if (mod == "\\end_removed_modules")
2197                         break;
2198                 removedModules_.push_back(mod);
2199                 lex.eatLine();
2200         }
2201         // now we want to remove any removed modules that were previously 
2202         // added. normally, that will be because default modules were added in 
2203         // setBaseClass(), which gets called when \textclass is read at the 
2204         // start of the read.
2205         list<string>::const_iterator rit = removedModules_.begin();
2206         list<string>::const_iterator const ren = removedModules_.end();
2207         for (; rit != ren; rit++) {
2208                 LayoutModuleList::iterator const mit = layoutModules_.begin();
2209                 LayoutModuleList::iterator const men = layoutModules_.end();
2210                 LayoutModuleList::iterator found = find(mit, men, *rit);
2211                 if (found == men)
2212                         continue;
2213                 layoutModules_.erase(found);
2214         }
2215 }
2216
2217
2218 void BufferParams::readIncludeonly(Lexer & lex)
2219 {
2220         if (!lex.eatLine()) {
2221                 lyxerr << "Error (BufferParams::readIncludeonly):"
2222                                 "Unexpected end of input." << endl;
2223                 return;
2224         }
2225         while (true) {
2226                 string child = lex.getString();
2227                 if (child == "\\end_includeonly")
2228                         break;
2229                 includedChildren_.push_back(child);
2230                 lex.eatLine();
2231         }
2232 }
2233
2234
2235 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2236 {
2237         char real_papersize = papersize;
2238         if (real_papersize == PAPER_DEFAULT)
2239                 real_papersize = lyxrc.default_papersize;
2240
2241         switch (real_papersize) {
2242         case PAPER_DEFAULT:
2243                 // could be anything, so don't guess
2244                 return string();
2245         case PAPER_CUSTOM: {
2246                 if (purpose == XDVI && !paperwidth.empty() &&
2247                     !paperheight.empty()) {
2248                         // heightxwidth<unit>
2249                         string first = paperwidth;
2250                         string second = paperheight;
2251                         if (orientation == ORIENTATION_LANDSCAPE)
2252                                 first.swap(second);
2253                         // cut off unit.
2254                         return first.erase(first.length() - 2)
2255                                 + "x" + second;
2256                 }
2257                 return string();
2258         }
2259         case PAPER_A0:
2260                 // dvips and dvipdfm do not know this
2261                 if (purpose == DVIPS || purpose == DVIPDFM)
2262                         return string();
2263                 return "a0";
2264         case PAPER_A1:
2265                 if (purpose == DVIPS || purpose == DVIPDFM)
2266                         return string();
2267                 return "a1";
2268         case PAPER_A2:
2269                 if (purpose == DVIPS || purpose == DVIPDFM)
2270                         return string();
2271                 return "a2";
2272         case PAPER_A3:
2273                 return "a3";
2274         case PAPER_A4:
2275                 return "a4";
2276         case PAPER_A5:
2277                 return "a5";
2278         case PAPER_A6:
2279                 if (purpose == DVIPS || purpose == DVIPDFM)
2280                         return string();
2281                 return "a6";
2282         case PAPER_B0:
2283                 if (purpose == DVIPS || purpose == DVIPDFM)
2284                         return string();
2285                 return "b0";
2286         case PAPER_B1:
2287                 if (purpose == DVIPS || purpose == DVIPDFM)
2288                         return string();
2289                 return "b1";
2290         case PAPER_B2:
2291                 if (purpose == DVIPS || purpose == DVIPDFM)
2292                         return string();
2293                 return "b2";
2294         case PAPER_B3:
2295                 if (purpose == DVIPS || purpose == DVIPDFM)
2296                         return string();
2297                 return "b3";
2298         case PAPER_B4:
2299                 // dvipdfm does not know this
2300                 if (purpose == DVIPDFM)
2301                         return string();
2302                 return "b4";
2303         case PAPER_B5:
2304                 if (purpose == DVIPDFM)
2305                         return string();
2306                 return "b5";
2307         case PAPER_B6:
2308                 if (purpose == DVIPS || purpose == DVIPDFM)
2309                         return string();
2310                 return "b6";
2311         case PAPER_C0:
2312                 if (purpose == DVIPS || purpose == DVIPDFM)
2313                         return string();
2314                 return "c0";
2315         case PAPER_C1:
2316                 if (purpose == DVIPS || purpose == DVIPDFM)
2317                         return string();
2318                 return "c1";
2319         case PAPER_C2:
2320                 if (purpose == DVIPS || purpose == DVIPDFM)
2321                         return string();
2322                 return "c2";
2323         case PAPER_C3:
2324                 if (purpose == DVIPS || purpose == DVIPDFM)
2325                         return string();
2326                 return "c3";
2327         case PAPER_C4:
2328                 if (purpose == DVIPS || purpose == DVIPDFM)
2329                         return string();
2330                 return "c4";
2331         case PAPER_C5:
2332                 if (purpose == DVIPS || purpose == DVIPDFM)
2333                         return string();
2334                 return "c5";
2335         case PAPER_C6:
2336                 if (purpose == DVIPS || purpose == DVIPDFM)
2337                         return string();
2338                 return "c6";
2339         case PAPER_JISB0:
2340                 if (purpose == DVIPS || purpose == DVIPDFM)
2341                         return string();
2342                 return "jisb0";
2343         case PAPER_JISB1:
2344                 if (purpose == DVIPS || purpose == DVIPDFM)
2345                         return string();
2346                 return "jisb1";
2347         case PAPER_JISB2:
2348                 if (purpose == DVIPS || purpose == DVIPDFM)
2349                         return string();
2350                 return "jisb2";
2351         case PAPER_JISB3:
2352                 if (purpose == DVIPS || purpose == DVIPDFM)
2353                         return string();
2354                 return "jisb3";
2355         case PAPER_JISB4:
2356                 if (purpose == DVIPS || purpose == DVIPDFM)
2357                         return string();
2358                 return "jisb4";
2359         case PAPER_JISB5:
2360                 if (purpose == DVIPS || purpose == DVIPDFM)
2361                         return string();
2362                 return "jisb5";
2363         case PAPER_JISB6:
2364                 if (purpose == DVIPS || purpose == DVIPDFM)
2365                         return string();
2366                 return "jisb6";
2367         case PAPER_USEXECUTIVE:
2368                 // dvipdfm does not know this
2369                 if (purpose == DVIPDFM)
2370                         return string();
2371                 return "foolscap";
2372         case PAPER_USLEGAL:
2373                 return "legal";
2374         case PAPER_USLETTER:
2375         default:
2376                 if (purpose == XDVI)
2377                         return "us";
2378                 return "letter";
2379         }
2380 }
2381
2382
2383 string const BufferParams::dvips_options() const
2384 {
2385         string result;
2386
2387         if (use_geometry
2388             && papersize == PAPER_CUSTOM
2389             && !lyxrc.print_paper_dimension_flag.empty()
2390             && !paperwidth.empty()
2391             && !paperheight.empty()) {
2392                 // using a custom papersize
2393                 result = lyxrc.print_paper_dimension_flag;
2394                 result += ' ' + paperwidth;
2395                 result += ',' + paperheight;
2396         } else {
2397                 string const paper_option = paperSizeName(DVIPS);
2398                 if (!paper_option.empty() && (paper_option != "letter" ||
2399                     orientation != ORIENTATION_LANDSCAPE)) {
2400                         // dvips won't accept -t letter -t landscape.
2401                         // In all other cases, include the paper size
2402                         // explicitly.
2403                         result = lyxrc.print_paper_flag;
2404                         result += ' ' + paper_option;
2405                 }
2406         }
2407         if (orientation == ORIENTATION_LANDSCAPE &&
2408             papersize != PAPER_CUSTOM)
2409                 result += ' ' + lyxrc.print_landscape_flag;
2410         return result;
2411 }
2412
2413
2414 string const BufferParams::font_encoding() const
2415 {
2416         return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2417 }
2418
2419
2420 string BufferParams::babelCall(string const & lang_opts, bool const langoptions) const
2421 {
2422         if (lyxrc.language_package_selection == LyXRC::LP_CUSTOM)
2423                 return lyxrc.language_custom_package;
2424         // suppress the babel call if there is no BabelName defined
2425         // for the document language in the lib/languages file and if no
2426         // other languages are used (lang_opts is then empty)
2427         if (lang_opts.empty())
2428                 return string();
2429         // either a specific language (AsBabelOptions setting in
2430         // lib/languages) or the prefs require the languages to
2431         // be submitted to babel itself (not the class).
2432         if (langoptions)
2433                 return "\\usepackage[" + lang_opts + "]{babel}";
2434         return "\\usepackage{babel}";
2435 }
2436
2437
2438 docstring BufferParams::getGraphicsDriver(string const & package) const
2439 {
2440         docstring result;
2441
2442         if (package == "geometry") {
2443                 if (graphicsDriver == "dvips"
2444                     || graphicsDriver == "dvipdfm"
2445                     || graphicsDriver == "pdftex"
2446                     || graphicsDriver == "vtex")
2447                         result = from_ascii(graphicsDriver);
2448                 else if (graphicsDriver == "dvipdfmx")
2449                         result = from_ascii("dvipdfm");
2450         }
2451
2452         return result;
2453 }
2454
2455
2456 void BufferParams::writeEncodingPreamble(odocstream & os,
2457                 LaTeXFeatures & features, TexRow & texrow) const
2458 {
2459         // fully unicode-aware backends (such as XeTeX) do not need this
2460         if (features.runparams().isFullUnicode())
2461                 return;
2462         if (inputenc == "auto") {
2463                 string const doc_encoding =
2464                         language->encoding()->latexName();
2465                 Encoding::Package const package =
2466                         language->encoding()->package();
2467
2468                 // Create a list with all the input encodings used
2469                 // in the document
2470                 set<string> encodings =
2471                         features.getEncodingSet(doc_encoding);
2472
2473                 // If the "japanese" package (i.e. pLaTeX) is used,
2474                 // inputenc must be omitted.
2475                 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2476                 if (package == Encoding::japanese)
2477                      features.require("japanese");
2478
2479                 if ((!encodings.empty() || package == Encoding::inputenc)
2480                     && !features.isRequired("japanese")) {
2481                         os << "\\usepackage[";
2482                         set<string>::const_iterator it = encodings.begin();
2483                         set<string>::const_iterator const end = encodings.end();
2484                         if (it != end) {
2485                                 os << from_ascii(*it);
2486                                 ++it;
2487                         }
2488                         for (; it != end; ++it)
2489                                 os << ',' << from_ascii(*it);
2490                         if (package == Encoding::inputenc) {
2491                                 if (!encodings.empty())
2492                                         os << ',';
2493                                 os << from_ascii(doc_encoding);
2494                         }
2495                         os << "]{inputenc}\n";
2496                         texrow.newline();
2497                 }
2498                 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2499                         if (language->encoding()->name() == "utf8-cjk"
2500                             && LaTeXFeatures::isAvailable("CJKutf8"))
2501                                 os << "\\usepackage{CJKutf8}\n";
2502                         else
2503                                 os << "\\usepackage{CJK}\n";
2504                         texrow.newline();
2505                 }
2506         } else if (inputenc != "default") {
2507                 switch (encoding().package()) {
2508                 case Encoding::none:
2509                 case Encoding::japanese:
2510                         break;
2511                 case Encoding::inputenc:
2512                         // do not load inputenc if japanese is used
2513                         if (features.isRequired("japanese"))
2514                                 break;
2515                         os << "\\usepackage[" << from_ascii(inputenc)
2516                            << "]{inputenc}\n";
2517                         texrow.newline();
2518                         break;
2519                 case Encoding::CJK:
2520                         if (encoding().name() == "utf8-cjk"
2521                             && LaTeXFeatures::isAvailable("CJKutf8"))
2522                                 os << "\\usepackage{CJKutf8}\n";
2523                         else
2524                                 os << "\\usepackage{CJK}\n";
2525                         texrow.newline();
2526                         break;
2527                 }
2528         }
2529
2530         // The encoding "armscii8" (for Armenian) is only available when
2531         // the package "armtex" is loaded.
2532         if (language->encoding()->latexName() == "armscii8"
2533             || inputenc == "armscii8") {
2534                 os << "\\usepackage{armtex}\n";
2535                 texrow.newline();
2536         }
2537 }
2538
2539
2540 string const BufferParams::parseFontName(string const & name) const
2541 {
2542         string mangled = name;
2543         size_t const idx = mangled.find('[');
2544         if (idx == string::npos || idx == 0)
2545                 return mangled;
2546         else
2547                 return mangled.substr(0, idx - 1);
2548 }
2549
2550
2551 string const BufferParams::loadFonts(string const & rm,
2552                                      string const & sf, string const & tt,
2553                                      bool const & sc, bool const & osf,
2554                                      int const & sfscale, int const & ttscale,
2555                                      bool const & xetex) const
2556 {
2557         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2558            several packages have been replaced by others, that might not
2559            be installed on every system. We have to take care for that
2560            (see psnfss.pdf). We try to support all psnfss fonts as well
2561            as the fonts that have become de facto standard in the LaTeX
2562            world (e.g. Latin Modern). We do not support obsolete fonts
2563            (like PSLatex). In general, it should be possible to mix any
2564            rm font with any sf or tt font, respectively. (JSpitzm)
2565            TODO:
2566                 -- separate math fonts.
2567         */
2568
2569         if (rm == "default" && sf == "default" && tt == "default")
2570                 //nothing to do
2571                 return string();
2572
2573         ostringstream os;
2574
2575         if (xetex) {
2576                 if (rm != "default") {
2577                         os << "\\setmainfont[Mapping=tex-text";
2578                         if (osf)
2579                                 os << ",Numbers=OldStyle";
2580                         os << "]{" << parseFontName(rm) << "}\n";
2581                 }
2582                 if (sf != "default") {
2583                         string const sans = parseFontName(sf);
2584                         if (sfscale != 100)
2585                                 os << "\\setsansfont[Scale=" 
2586                                    << float(sfscale) / 100 
2587                                    << ",Mapping=tex-text]{"
2588                                    << sans << "}\n";
2589                         else
2590                                 os << "\\setsansfont[Mapping=tex-text]{"
2591                                    << sans << "}\n";
2592                 }
2593                 if (tt != "default") {
2594                         string const mono = parseFontName(tt);
2595                         if (ttscale != 100)
2596                                 os << "\\setmonofont[Scale=" 
2597                                    << float(sfscale) / 100 
2598                                    << "]{"
2599                                    << mono << "}\n";
2600                         else
2601                                 os << "\\setmonofont[Mapping=tex-text]{"
2602                                    << mono << "}\n";
2603                 }
2604                 return os.str();
2605         }
2606
2607         // ROMAN FONTS
2608         // Computer Modern (must be explicitly selectable -- there might be classes
2609         // that define a different default font!
2610         if (rm == "cmr") {
2611                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2612                 // osf for Computer Modern needs eco.sty
2613                 if (osf)
2614                         os << "\\usepackage{eco}\n";
2615         }
2616         // Latin Modern Roman
2617         else if (rm == "lmodern")
2618                 os << "\\usepackage{lmodern}\n";
2619         // AE
2620         else if (rm == "ae") {
2621                 // not needed when using OT1 font encoding.
2622                 if (font_encoding() != "default")
2623                         os << "\\usepackage{ae,aecompl}\n";
2624         }
2625         // Times
2626         else if (rm == "times") {
2627                 // try to load the best available package
2628                 if (LaTeXFeatures::isAvailable("mathptmx"))
2629                         os << "\\usepackage{mathptmx}\n";
2630                 else if (LaTeXFeatures::isAvailable("mathptm"))
2631                         os << "\\usepackage{mathptm}\n";
2632                 else
2633                         os << "\\usepackage{times}\n";
2634         }
2635         // Palatino
2636         else if (rm == "palatino") {
2637                 // try to load the best available package
2638                 if (LaTeXFeatures::isAvailable("mathpazo")) {
2639                         os << "\\usepackage";
2640                         if (osf || sc) {
2641                                 os << '[';
2642                                 if (!osf)
2643                                         os << "sc";
2644                                 else
2645                                         // "osf" includes "sc"!
2646                                         os << "osf";
2647                                 os << ']';
2648                         }
2649                         os << "{mathpazo}\n";
2650                 }
2651                 else if (LaTeXFeatures::isAvailable("mathpple"))
2652                         os << "\\usepackage{mathpple}\n";
2653                 else
2654                         os << "\\usepackage{palatino}\n";
2655         }
2656         // Utopia
2657         else if (rm == "utopia") {
2658                 // fourier supersedes utopia.sty, but does
2659                 // not work with OT1 encoding.
2660                 if (LaTeXFeatures::isAvailable("fourier")
2661                     && font_encoding() != "default") {
2662                         os << "\\usepackage";
2663                         if (osf || sc) {
2664                                 os << '[';
2665                                 if (sc)
2666                                         os << "expert";
2667                                 if (osf && sc)
2668                                         os << ',';
2669                                 if (osf)
2670                                         os << "oldstyle";
2671                                 os << ']';
2672                         }
2673                         os << "{fourier}\n";
2674                 }
2675                 else
2676                         os << "\\usepackage{utopia}\n";
2677         }
2678         // Bera (complete fontset)
2679         else if (rm == "bera" && sf == "default" && tt == "default")
2680                 os << "\\usepackage{bera}\n";
2681         // everything else
2682         else if (rm != "default")
2683                 os << "\\usepackage" << "{" << rm << "}\n";
2684
2685         // SANS SERIF
2686         // Helvetica, Bera Sans
2687         if (sf == "helvet" || sf == "berasans") {
2688                 if (sfscale != 100)
2689                         os << "\\usepackage[scaled=" << float(sfscale) / 100
2690                            << "]{" << sf << "}\n";
2691                 else
2692                         os << "\\usepackage{" << sf << "}\n";
2693         }
2694         // Avant Garde
2695         else if (sf == "avant")
2696                 os << "\\usepackage{" << sf << "}\n";
2697         // Computer Modern, Latin Modern, CM Bright
2698         else if (sf != "default")
2699                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2700
2701         // monospaced/typewriter
2702         // Courier, LuxiMono
2703         if (tt == "luximono" || tt == "beramono") {
2704                 if (ttscale != 100)
2705                         os << "\\usepackage[scaled=" << float(ttscale) / 100
2706                            << "]{" << tt << "}\n";
2707                 else
2708                         os << "\\usepackage{" << tt << "}\n";
2709         }
2710         // Courier
2711         else if (tt == "courier" )
2712                 os << "\\usepackage{" << tt << "}\n";
2713         // Computer Modern, Latin Modern, CM Bright
2714         else if (tt != "default")
2715                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2716
2717         return os.str();
2718 }
2719
2720
2721 Encoding const & BufferParams::encoding() const
2722 {
2723         if (useXetex)
2724                 return *(encodings.fromLaTeXName("utf8-plain"));
2725         if (inputenc == "auto" || inputenc == "default")
2726                 return *language->encoding();
2727         Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2728         if (enc)
2729                 return *enc;
2730         LYXERR0("Unknown inputenc value `" << inputenc
2731                << "'. Using `auto' instead.");
2732         return *language->encoding();
2733 }
2734
2735
2736 CiteEngine BufferParams::citeEngine() const
2737 {
2738         // FIXME the class should provide the numerical/
2739         // authoryear choice
2740         if (documentClass().provides("natbib")
2741             && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2742                 return ENGINE_NATBIB_AUTHORYEAR;
2743         return cite_engine_;
2744 }
2745
2746
2747 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2748 {
2749         cite_engine_ = cite_engine;
2750 }
2751
2752 } // namespace lyx