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