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