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