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