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