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