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