]> git.lyx.org Git - features.git/blob - src/BufferParams.cpp
support for the ISO C-series paper formats; fileformat change
[features.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 desc = 
559                                 translateIfPossible(from_utf8(baseClass()->description()));
560                         docstring const msg =
561                                 bformat(_("The selected document class\n"
562                                                  "\t%1$s\n"
563                                                  "requires external files that are not available.\n"
564                                                  "The document class can still be used, but LyX\n"
565                                                  "will not be able to produce output until the\n"
566                                                  "following prerequisites are installed:\n"
567                                                  "\t%2$s\n"
568                                                  "See section 3.1.2.2 of the User's Guide for\n"
569                                                  "more information."), 
570                                                  desc, from_utf8(baseClass()->prerequisites()));
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();
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         }
1779
1780         // Will be surrounded by \makeatletter and \makeatother when not empty
1781         docstring atlyxpreamble;
1782
1783         // Some macros LyX will need
1784         docstring tmppreamble(features.getMacros());
1785
1786         if (!tmppreamble.empty())
1787                 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1788                         "LyX specific LaTeX commands.\n"
1789                         + tmppreamble + '\n';
1790
1791         // the text class specific preamble
1792         tmppreamble = features.getTClassPreamble();
1793         if (!tmppreamble.empty())
1794                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1795                         "Textclass specific LaTeX commands.\n"
1796                         + tmppreamble + '\n';
1797
1798         // suppress date if selected
1799         // use \@ifundefined because we cannot be sure that every document class
1800         // has a \date command
1801         if (suppress_date)
1802                 atlyxpreamble += "\\@ifundefined{date}{}{\\date{}}\n";
1803
1804         /* the user-defined preamble */
1805         if (!containsOnly(preamble, " \n\t"))
1806                 // FIXME UNICODE
1807                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1808                         "User specified LaTeX commands.\n"
1809                         + from_utf8(preamble) + '\n';
1810
1811         // subfig loads internally the LaTeX package "caption". As
1812         // caption is a very popular package, users will load it in
1813         // the preamble. Therefore we must load subfig behind the
1814         // user-defined preamble and check if the caption package was
1815         // loaded or not. For the case that caption is loaded before
1816         // subfig, there is the subfig option "caption=false". This
1817         // option also works when a koma-script class is used and
1818         // koma's own caption commands are used instead of caption. We
1819         // use \PassOptionsToPackage here because the user could have
1820         // already loaded subfig in the preamble.
1821         if (features.isRequired("subfig")) {
1822                 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1823                         " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1824                         "\\usepackage{subfig}\n";
1825         }
1826
1827         // Itemize bullet settings need to be last in case the user
1828         // defines their own bullets that use a package included
1829         // in the user-defined preamble -- ARRae
1830         // Actually it has to be done much later than that
1831         // since some packages like frenchb make modifications
1832         // at \begin{document} time -- JMarc
1833         docstring bullets_def;
1834         for (int i = 0; i < 4; ++i) {
1835                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1836                         if (bullets_def.empty())
1837                                 bullets_def += "\\AtBeginDocument{\n";
1838                         bullets_def += "  \\def\\labelitemi";
1839                         switch (i) {
1840                                 // `i' is one less than the item to modify
1841                         case 0:
1842                                 break;
1843                         case 1:
1844                                 bullets_def += 'i';
1845                                 break;
1846                         case 2:
1847                                 bullets_def += "ii";
1848                                 break;
1849                         case 3:
1850                                 bullets_def += 'v';
1851                                 break;
1852                         }
1853                         bullets_def += '{' +
1854                                 user_defined_bullet(i).getText()
1855                                 + "}\n";
1856                 }
1857         }
1858
1859         if (!bullets_def.empty())
1860                 atlyxpreamble += bullets_def + "}\n\n";
1861
1862         if (!atlyxpreamble.empty())
1863                 lyxpreamble += "\n\\makeatletter\n"
1864                         + atlyxpreamble + "\\makeatother\n\n";
1865
1866         // We try to load babel late, in case it interferes with other packages.
1867         // Jurabib and Hyperref have to be called after babel, though.
1868         if (use_babel && !features.isRequired("jurabib")
1869             && !features.isRequired("hyperref")
1870             && !features.isRequired("vietnamese")
1871             && !features.isRequired("japanese")) {
1872                 // FIXME UNICODE
1873                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1874                 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1875         }
1876
1877         docstring const i18npreamble = features.getTClassI18nPreamble(use_babel);
1878         if (!i18npreamble.empty())
1879                 lyxpreamble += i18npreamble + '\n';
1880
1881         int const nlines =
1882                 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1883         texrow.newlines(nlines);
1884
1885         os << lyxpreamble;
1886
1887         // these packages (xunicode, for that matter) need to be loaded at least
1888         // after amsmath, amssymb, esint and the other packages that provide 
1889         // special glyphs
1890         if (useXetex) {
1891                 os << "\\usepackage{xunicode}\n";
1892                 texrow.newline();
1893                 os << "\\usepackage{xltxtra}\n";
1894                 texrow.newline();
1895         }
1896         return use_babel;
1897 }
1898
1899
1900 void BufferParams::useClassDefaults()
1901 {
1902         DocumentClass const & tclass = documentClass();
1903
1904         sides = tclass.sides();
1905         columns = tclass.columns();
1906         pagestyle = tclass.pagestyle();
1907         use_default_options = true;
1908         // Only if class has a ToC hierarchy
1909         if (tclass.hasTocLevels()) {
1910                 secnumdepth = tclass.secnumdepth();
1911                 tocdepth = tclass.tocdepth();
1912         }
1913 }
1914
1915
1916 bool BufferParams::hasClassDefaults() const
1917 {
1918         DocumentClass const & tclass = documentClass();
1919
1920         return sides == tclass.sides()
1921                 && columns == tclass.columns()
1922                 && pagestyle == tclass.pagestyle()
1923                 && use_default_options
1924                 && secnumdepth == tclass.secnumdepth()
1925                 && tocdepth == tclass.tocdepth();
1926 }
1927
1928
1929 DocumentClass const & BufferParams::documentClass() const
1930 {
1931         return *doc_class_;
1932 }
1933
1934
1935 DocumentClass const * BufferParams::documentClassPtr() const {
1936         return doc_class_;
1937 }
1938
1939
1940 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1941         // evil, but this function is evil
1942         doc_class_ = const_cast<DocumentClass *>(tc);
1943 }
1944
1945
1946 bool BufferParams::setBaseClass(string const & classname)
1947 {
1948         LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1949         LayoutFileList & bcl = LayoutFileList::get();
1950         if (!bcl.haveClass(classname)) {
1951                 docstring s = 
1952                         bformat(_("The layout file:\n"
1953                                 "%1$s\n"
1954                                 "could not be found. A default textclass with default\n"
1955                                 "layouts will be used. LyX will not be able to produce\n"
1956                                 "correct output."),
1957                         from_utf8(classname));
1958                 frontend::Alert::error(_("Document class not found"), s);
1959                 bcl.addEmptyClass(classname);
1960         }
1961
1962         bool const success = bcl[classname].load();
1963         if (!success) {
1964                 docstring s = 
1965                         bformat(_("Due to some error in it, the layout file:\n"
1966                                 "%1$s\n"
1967                                 "could not be loaded. A default textclass with default\n"
1968                                 "layouts will be used. LyX will not be able to produce\n"
1969                                 "correct output."),
1970                         from_utf8(classname));
1971                 frontend::Alert::error(_("Could not load class"), s);
1972                 bcl.addEmptyClass(classname);
1973         }
1974
1975         pimpl_->baseClass_ = classname;
1976         layoutModules_.adaptToBaseClass(baseClass(), removedModules_);
1977         return true;
1978 }
1979
1980
1981 LayoutFile const * BufferParams::baseClass() const
1982 {
1983         if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1984                 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1985         else 
1986                 return 0;
1987 }
1988
1989
1990 LayoutFileIndex const & BufferParams::baseClassID() const
1991 {
1992         return pimpl_->baseClass_;
1993 }
1994
1995
1996 void BufferParams::makeDocumentClass()
1997 {
1998         if (!baseClass())
1999                 return;
2000
2001         doc_class_ = &(DocumentClassBundle::get().makeDocumentClass(*baseClass(), layoutModules_));
2002
2003         if (!local_layout.empty()) {
2004                 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
2005                         docstring const msg = _("Error reading internal layout information");
2006                         frontend::Alert::warning(_("Read Error"), msg);
2007                 }
2008         }
2009 }
2010
2011
2012 bool BufferParams::moduleCanBeAdded(string const & modName) const
2013 {
2014         return layoutModules_.moduleCanBeAdded(modName, baseClass());
2015 }
2016
2017
2018 bool BufferParams::addLayoutModule(string const & modName)
2019 {
2020         LayoutModuleList::const_iterator it = layoutModules_.begin();
2021         LayoutModuleList::const_iterator end = layoutModules_.end();
2022         for (; it != end; it++)
2023                 if (*it == modName) 
2024                         return false;
2025         layoutModules_.push_back(modName);
2026         return true;
2027 }
2028
2029
2030 Font const BufferParams::getFont() const
2031 {
2032         FontInfo f = documentClass().defaultfont();
2033         if (fontsDefaultFamily == "rmdefault")
2034                 f.setFamily(ROMAN_FAMILY);
2035         else if (fontsDefaultFamily == "sfdefault")
2036                 f.setFamily(SANS_FAMILY);
2037         else if (fontsDefaultFamily == "ttdefault")
2038                 f.setFamily(TYPEWRITER_FAMILY);
2039         return Font(f, language);
2040 }
2041
2042
2043 void BufferParams::readPreamble(Lexer & lex)
2044 {
2045         if (lex.getString() != "\\begin_preamble")
2046                 lyxerr << "Error (BufferParams::readPreamble):"
2047                         "consistency check failed." << endl;
2048
2049         preamble = lex.getLongString("\\end_preamble");
2050 }
2051
2052
2053 void BufferParams::readLocalLayout(Lexer & lex)
2054 {
2055         if (lex.getString() != "\\begin_local_layout")
2056                 lyxerr << "Error (BufferParams::readLocalLayout):"
2057                         "consistency check failed." << endl;
2058
2059         local_layout = lex.getLongString("\\end_local_layout");
2060 }
2061
2062
2063 void BufferParams::readLanguage(Lexer & lex)
2064 {
2065         if (!lex.next()) return;
2066
2067         string const tmptok = lex.getString();
2068
2069         // check if tmptok is part of tex_babel in tex-defs.h
2070         language = languages.getLanguage(tmptok);
2071         if (!language) {
2072                 // Language tmptok was not found
2073                 language = default_language;
2074                 lyxerr << "Warning: Setting language `"
2075                        << tmptok << "' to `" << language->lang()
2076                        << "'." << endl;
2077         }
2078 }
2079
2080
2081 void BufferParams::readGraphicsDriver(Lexer & lex)
2082 {
2083         if (!lex.next()) 
2084                 return;
2085
2086         string const tmptok = lex.getString();
2087         // check if tmptok is part of tex_graphics in tex_defs.h
2088         int n = 0;
2089         while (true) {
2090                 string const test = tex_graphics[n++];
2091
2092                 if (test == tmptok) {
2093                         graphicsDriver = tmptok;
2094                         break;
2095                 }
2096                 if (test.empty()) {
2097                         lex.printError(
2098                                 "Warning: graphics driver `$$Token' not recognized!\n"
2099                                 "         Setting graphics driver to `default'.\n");
2100                         graphicsDriver = "default";
2101                         break;
2102                 }
2103         }
2104 }
2105
2106
2107 void BufferParams::readBullets(Lexer & lex)
2108 {
2109         if (!lex.next()) 
2110                 return;
2111
2112         int const index = lex.getInteger();
2113         lex.next();
2114         int temp_int = lex.getInteger();
2115         user_defined_bullet(index).setFont(temp_int);
2116         temp_bullet(index).setFont(temp_int);
2117         lex >> temp_int;
2118         user_defined_bullet(index).setCharacter(temp_int);
2119         temp_bullet(index).setCharacter(temp_int);
2120         lex >> temp_int;
2121         user_defined_bullet(index).setSize(temp_int);
2122         temp_bullet(index).setSize(temp_int);
2123 }
2124
2125
2126 void BufferParams::readBulletsLaTeX(Lexer & lex)
2127 {
2128         // The bullet class should be able to read this.
2129         if (!lex.next()) 
2130                 return;
2131         int const index = lex.getInteger();
2132         lex.next(true);
2133         docstring const temp_str = lex.getDocString();
2134
2135         user_defined_bullet(index).setText(temp_str);
2136         temp_bullet(index).setText(temp_str);
2137 }
2138
2139
2140 void BufferParams::readModules(Lexer & lex)
2141 {
2142         if (!lex.eatLine()) {
2143                 lyxerr << "Error (BufferParams::readModules):"
2144                                 "Unexpected end of input." << endl;
2145                 return;
2146         }
2147         while (true) {
2148                 string mod = lex.getString();
2149                 if (mod == "\\end_modules")
2150                         break;
2151                 addLayoutModule(mod);
2152                 lex.eatLine();
2153         }
2154 }
2155
2156
2157 void BufferParams::readRemovedModules(Lexer & lex)
2158 {
2159         if (!lex.eatLine()) {
2160                 lyxerr << "Error (BufferParams::readRemovedModules):"
2161                                 "Unexpected end of input." << endl;
2162                 return;
2163         }
2164         while (true) {
2165                 string mod = lex.getString();
2166                 if (mod == "\\end_removed_modules")
2167                         break;
2168                 removedModules_.push_back(mod);
2169                 lex.eatLine();
2170         }
2171         // now we want to remove any removed modules that were previously 
2172         // added. normally, that will be because default modules were added in 
2173         // setBaseClass(), which gets called when \textclass is read at the 
2174         // start of the read.
2175         list<string>::const_iterator rit = removedModules_.begin();
2176         list<string>::const_iterator const ren = removedModules_.end();
2177         for (; rit != ren; rit++) {
2178                 LayoutModuleList::iterator const mit = layoutModules_.begin();
2179                 LayoutModuleList::iterator const men = layoutModules_.end();
2180                 LayoutModuleList::iterator found = find(mit, men, *rit);
2181                 if (found == men)
2182                         continue;
2183                 layoutModules_.erase(found);
2184         }
2185 }
2186
2187
2188 void BufferParams::readIncludeonly(Lexer & lex)
2189 {
2190         if (!lex.eatLine()) {
2191                 lyxerr << "Error (BufferParams::readIncludeonly):"
2192                                 "Unexpected end of input." << endl;
2193                 return;
2194         }
2195         while (true) {
2196                 string child = lex.getString();
2197                 if (child == "\\end_includeonly")
2198                         break;
2199                 includedChildren_.push_back(child);
2200                 lex.eatLine();
2201         }
2202 }
2203
2204
2205 string BufferParams::paperSizeName(PapersizePurpose purpose) const
2206 {
2207         char real_papersize = papersize;
2208         if (real_papersize == PAPER_DEFAULT)
2209                 real_papersize = lyxrc.default_papersize;
2210
2211         switch (real_papersize) {
2212         case PAPER_DEFAULT:
2213                 // could be anything, so don't guess
2214                 return string();
2215         case PAPER_CUSTOM: {
2216                 if (purpose == XDVI && !paperwidth.empty() &&
2217                     !paperheight.empty()) {
2218                         // heightxwidth<unit>
2219                         string first = paperwidth;
2220                         string second = paperheight;
2221                         if (orientation == ORIENTATION_LANDSCAPE)
2222                                 first.swap(second);
2223                         // cut off unit.
2224                         return first.erase(first.length() - 2)
2225                                 + "x" + second;
2226                 }
2227                 return string();
2228         }
2229         case PAPER_A0:
2230                 // dvips and dvipdfm do not know this
2231                 if (purpose == DVIPS || purpose == DVIPDFM)
2232                         return string();
2233                 return "a0";
2234         case PAPER_A1:
2235                 if (purpose == DVIPS || purpose == DVIPDFM)
2236                         return string();
2237                 return "a1";
2238         case PAPER_A2:
2239                 if (purpose == DVIPS || purpose == DVIPDFM)
2240                         return string();
2241                 return "a2";
2242         case PAPER_A3:
2243                 return "a3";
2244         case PAPER_A4:
2245                 return "a4";
2246         case PAPER_A5:
2247                 return "a5";
2248         case PAPER_A6:
2249                 if (purpose == DVIPS || purpose == DVIPDFM)
2250                         return string();
2251                 return "a6";
2252         case PAPER_B0:
2253                 if (purpose == DVIPS || purpose == DVIPDFM)
2254                         return string();
2255                 return "b0";
2256         case PAPER_B1:
2257                 if (purpose == DVIPS || purpose == DVIPDFM)
2258                         return string();
2259                 return "b1";
2260         case PAPER_B2:
2261                 if (purpose == DVIPS || purpose == DVIPDFM)
2262                         return string();
2263                 return "b2";
2264         case PAPER_B3:
2265                 if (purpose == DVIPS || purpose == DVIPDFM)
2266                         return string();
2267                 return "b3";
2268         case PAPER_B4:
2269                 // dvipdfm does not know this
2270                 if (purpose == DVIPDFM)
2271                         return string();
2272                 return "b4";
2273         case PAPER_B5:
2274                 if (purpose == DVIPDFM)
2275                         return string();
2276                 return "b5";
2277         case PAPER_B6:
2278                 if (purpose == DVIPS || purpose == DVIPDFM)
2279                         return string();
2280                 return "b6";
2281         case PAPER_C0:
2282                 if (purpose == DVIPS || purpose == DVIPDFM)
2283                         return string();
2284                 return "c0";
2285         case PAPER_C1:
2286                 if (purpose == DVIPS || purpose == DVIPDFM)
2287                         return string();
2288                 return "c1";
2289         case PAPER_C2:
2290                 if (purpose == DVIPS || purpose == DVIPDFM)
2291                         return string();
2292                 return "c2";
2293         case PAPER_C3:
2294                 if (purpose == DVIPS || purpose == DVIPDFM)
2295                         return string();
2296                 return "c3";
2297         case PAPER_C4:
2298                 if (purpose == DVIPS || purpose == DVIPDFM)
2299                         return string();
2300                 return "c4";
2301         case PAPER_C5:
2302                 if (purpose == DVIPS || purpose == DVIPDFM)
2303                         return string();
2304                 return "c5";
2305         case PAPER_C6:
2306                 if (purpose == DVIPS || purpose == DVIPDFM)
2307                         return string();
2308                 return "c6";
2309         case PAPER_JISB0:
2310                 if (purpose == DVIPS || purpose == DVIPDFM)
2311                         return string();
2312                 return "jisb0";
2313         case PAPER_JISB1:
2314                 if (purpose == DVIPS || purpose == DVIPDFM)
2315                         return string();
2316                 return "jisb1";
2317         case PAPER_JISB2:
2318                 if (purpose == DVIPS || purpose == DVIPDFM)
2319                         return string();
2320                 return "jisb2";
2321         case PAPER_JISB3:
2322                 if (purpose == DVIPS || purpose == DVIPDFM)
2323                         return string();
2324                 return "jisb3";
2325         case PAPER_JISB4:
2326                 if (purpose == DVIPS || purpose == DVIPDFM)
2327                         return string();
2328                 return "jisb4";
2329         case PAPER_JISB5:
2330                 if (purpose == DVIPS || purpose == DVIPDFM)
2331                         return string();
2332                 return "jisb5";
2333         case PAPER_JISB6:
2334                 if (purpose == DVIPS || purpose == DVIPDFM)
2335                         return string();
2336                 return "jisb6";
2337         case PAPER_USEXECUTIVE:
2338                 // dvipdfm does not know this
2339                 if (purpose == DVIPDFM)
2340                         return string();
2341                 return "foolscap";
2342         case PAPER_USLEGAL:
2343                 return "legal";
2344         case PAPER_USLETTER:
2345         default:
2346                 if (purpose == XDVI)
2347                         return "us";
2348                 return "letter";
2349         }
2350 }
2351
2352
2353 string const BufferParams::dvips_options() const
2354 {
2355         string result;
2356
2357         if (use_geometry
2358             && papersize == PAPER_CUSTOM
2359             && !lyxrc.print_paper_dimension_flag.empty()
2360             && !paperwidth.empty()
2361             && !paperheight.empty()) {
2362                 // using a custom papersize
2363                 result = lyxrc.print_paper_dimension_flag;
2364                 result += ' ' + paperwidth;
2365                 result += ',' + paperheight;
2366         } else {
2367                 string const paper_option = paperSizeName(DVIPS);
2368                 if (!paper_option.empty() && (paper_option != "letter" ||
2369                     orientation != ORIENTATION_LANDSCAPE)) {
2370                         // dvips won't accept -t letter -t landscape.
2371                         // In all other cases, include the paper size
2372                         // explicitly.
2373                         result = lyxrc.print_paper_flag;
2374                         result += ' ' + paper_option;
2375                 }
2376         }
2377         if (orientation == ORIENTATION_LANDSCAPE &&
2378             papersize != PAPER_CUSTOM)
2379                 result += ' ' + lyxrc.print_landscape_flag;
2380         return result;
2381 }
2382
2383
2384 string const BufferParams::font_encoding() const
2385 {
2386         return (fontenc == "global") ? lyxrc.fontenc : fontenc;
2387 }
2388
2389
2390 string BufferParams::babelCall(string const & lang_opts) const
2391 {
2392         string lang_pack = lyxrc.language_package;
2393         if (lang_pack != "\\usepackage{babel}")
2394                 return lang_pack;
2395         // suppress the babel call when there is no babel language defined
2396         // for the document language in the lib/languages file and if no
2397         // other languages are used (lang_opts is then empty)
2398         if (lang_opts.empty())
2399                 return string();
2400         // If Vietnamese is used, babel must directly be loaded with the
2401         // language options, see
2402         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
2403         size_t viet = lang_opts.find("vietnam");
2404         // viet = string::npos when not found
2405         // the same is for all other languages that are not directly supported by
2406         // babel, but where LaTeX-packages add babel support.
2407         // this is currently the case for Latvian, Lithuanian, Mongolian
2408         // and Turkmen
2409         size_t latvian = lang_opts.find("latvian");
2410         size_t lithu = lang_opts.find("lithuanian");
2411         size_t mongo = lang_opts.find("mongolian");
2412         size_t turkmen = lang_opts.find("turkmen");
2413         // If Japanese is used, babel must directly be loaded with the
2414         // language options, see
2415         // http://www.lyx.org/trac/ticket/4597#c4
2416         size_t japan = lang_opts.find("japanese");
2417         if (!lyxrc.language_global_options || viet != string::npos
2418                 || japan != string::npos || latvian != string::npos
2419                 || lithu != string::npos || mongo != string::npos
2420                 || turkmen != string::npos)
2421                 return "\\usepackage[" + lang_opts + "]{babel}";
2422         return lang_pack;
2423 }
2424
2425
2426 docstring BufferParams::getGraphicsDriver(string const & package) const
2427 {
2428         docstring result;
2429
2430         if (package == "geometry") {
2431                 if (graphicsDriver == "dvips"
2432                     || graphicsDriver == "dvipdfm"
2433                     || graphicsDriver == "pdftex"
2434                     || graphicsDriver == "vtex")
2435                         result = from_ascii(graphicsDriver);
2436                 else if (graphicsDriver == "dvipdfmx")
2437                         result = from_ascii("dvipdfm");
2438         }
2439
2440         return result;
2441 }
2442
2443
2444 void BufferParams::writeEncodingPreamble(odocstream & os,
2445                 LaTeXFeatures & features, TexRow & texrow) const
2446 {
2447         if (useXetex)
2448                 return;
2449         if (inputenc == "auto") {
2450                 string const doc_encoding =
2451                         language->encoding()->latexName();
2452                 Encoding::Package const package =
2453                         language->encoding()->package();
2454
2455                 // Create a list with all the input encodings used
2456                 // in the document
2457                 set<string> encodings =
2458                         features.getEncodingSet(doc_encoding);
2459
2460                 // If the "japanese" package (i.e. pLaTeX) is used,
2461                 // inputenc must be omitted.
2462                 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
2463                 if (package == Encoding::japanese)
2464                      features.require("japanese");
2465
2466                 if ((!encodings.empty() || package == Encoding::inputenc)
2467                     && !features.isRequired("japanese")) {
2468                         os << "\\usepackage[";
2469                         set<string>::const_iterator it = encodings.begin();
2470                         set<string>::const_iterator const end = encodings.end();
2471                         if (it != end) {
2472                                 os << from_ascii(*it);
2473                                 ++it;
2474                         }
2475                         for (; it != end; ++it)
2476                                 os << ',' << from_ascii(*it);
2477                         if (package == Encoding::inputenc) {
2478                                 if (!encodings.empty())
2479                                         os << ',';
2480                                 os << from_ascii(doc_encoding);
2481                         }
2482                         os << "]{inputenc}\n";
2483                         texrow.newline();
2484                 }
2485                 if (package == Encoding::CJK || features.mustProvide("CJK")) {
2486                         if (language->encoding()->name() == "utf8-cjk"
2487                             && LaTeXFeatures::isAvailable("CJKutf8"))
2488                                 os << "\\usepackage{CJKutf8}\n";
2489                         else
2490                                 os << "\\usepackage{CJK}\n";
2491                         texrow.newline();
2492                 }
2493         } else if (inputenc != "default") {
2494                 switch (encoding().package()) {
2495                 case Encoding::none:
2496                 case Encoding::japanese:
2497                         break;
2498                 case Encoding::inputenc:
2499                         // do not load inputenc if japanese is used
2500                         if (features.isRequired("japanese"))
2501                                 break;
2502                         os << "\\usepackage[" << from_ascii(inputenc)
2503                            << "]{inputenc}\n";
2504                         texrow.newline();
2505                         break;
2506                 case Encoding::CJK:
2507                         if (encoding().name() == "utf8-cjk"
2508                             && LaTeXFeatures::isAvailable("CJKutf8"))
2509                                 os << "\\usepackage{CJKutf8}\n";
2510                         else
2511                                 os << "\\usepackage{CJK}\n";
2512                         texrow.newline();
2513                         break;
2514                 }
2515         }
2516
2517         // The encoding "armscii8" (for Armenian) is only available when
2518         // the package "armtex" is loaded.
2519         if (language->encoding()->latexName() == "armscii8"
2520             || inputenc == "armscii8") {
2521                 os << "\\usepackage{armtex}\n";
2522                 texrow.newline();
2523         }
2524 }
2525
2526
2527 string const BufferParams::parseFontName(string const & name) const
2528 {
2529         string mangled = name;
2530         size_t const idx = mangled.find('[');
2531         if (idx == string::npos || idx == 0)
2532                 return mangled;
2533         else
2534                 return mangled.substr(0, idx - 1);
2535 }
2536
2537
2538 string const BufferParams::loadFonts(string const & rm,
2539                                      string const & sf, string const & tt,
2540                                      bool const & sc, bool const & osf,
2541                                      int const & sfscale, int const & ttscale,
2542                                      bool const & xetex) const
2543 {
2544         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
2545            several packages have been replaced by others, that might not
2546            be installed on every system. We have to take care for that
2547            (see psnfss.pdf). We try to support all psnfss fonts as well
2548            as the fonts that have become de facto standard in the LaTeX
2549            world (e.g. Latin Modern). We do not support obsolete fonts
2550            (like PSLatex). In general, it should be possible to mix any
2551            rm font with any sf or tt font, respectively. (JSpitzm)
2552            TODO:
2553                 -- separate math fonts.
2554         */
2555
2556         if (rm == "default" && sf == "default" && tt == "default")
2557                 //nothing to do
2558                 return string();
2559
2560         ostringstream os;
2561
2562         if (xetex) {
2563                 if (rm != "default")
2564                         os << "\\setmainfont[Mapping=tex-text]{"
2565                            << parseFontName(rm) << "}\n";
2566                 if (sf != "default") {
2567                         string const sans = parseFontName(sf);
2568                         if (sfscale != 100)
2569                                 os << "\\setsansfont[Scale=" 
2570                                    << float(sfscale) / 100 
2571                                    << ",Mapping=tex-text]{"
2572                                    << sans << "}\n";
2573                         else
2574                                 os << "\\setsansfont[Mapping=tex-text]{"
2575                                    << sans << "}\n";
2576                 }
2577                 if (tt != "default") {
2578                         string const mono = parseFontName(tt);
2579                         if (ttscale != 100)
2580                                 os << "\\setmonofont[Scale=" 
2581                                    << float(sfscale) / 100 
2582                                    << "]{"
2583                                    << mono << "}\n";
2584                         else
2585                                 os << "\\setmonofont[Mapping=tex-text]{"
2586                                    << mono << "}\n";
2587                 }
2588                 if (osf)
2589                         os << "\\defaultfontfeatures{Numbers=OldStyle}\n";
2590                 return os.str();
2591         }
2592
2593         // ROMAN FONTS
2594         // Computer Modern (must be explicitly selectable -- there might be classes
2595         // that define a different default font!
2596         if (rm == "cmr") {
2597                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
2598                 // osf for Computer Modern needs eco.sty
2599                 if (osf)
2600                         os << "\\usepackage{eco}\n";
2601         }
2602         // Latin Modern Roman
2603         else if (rm == "lmodern")
2604                 os << "\\usepackage{lmodern}\n";
2605         // AE
2606         else if (rm == "ae") {
2607                 // not needed when using OT1 font encoding.
2608                 if (font_encoding() != "default")
2609                         os << "\\usepackage{ae,aecompl}\n";
2610         }
2611         // Times
2612         else if (rm == "times") {
2613                 // try to load the best available package
2614                 if (LaTeXFeatures::isAvailable("mathptmx"))
2615                         os << "\\usepackage{mathptmx}\n";
2616                 else if (LaTeXFeatures::isAvailable("mathptm"))
2617                         os << "\\usepackage{mathptm}\n";
2618                 else
2619                         os << "\\usepackage{times}\n";
2620         }
2621         // Palatino
2622         else if (rm == "palatino") {
2623                 // try to load the best available package
2624                 if (LaTeXFeatures::isAvailable("mathpazo")) {
2625                         os << "\\usepackage";
2626                         if (osf || sc) {
2627                                 os << '[';
2628                                 if (!osf)
2629                                         os << "sc";
2630                                 else
2631                                         // "osf" includes "sc"!
2632                                         os << "osf";
2633                                 os << ']';
2634                         }
2635                         os << "{mathpazo}\n";
2636                 }
2637                 else if (LaTeXFeatures::isAvailable("mathpple"))
2638                         os << "\\usepackage{mathpple}\n";
2639                 else
2640                         os << "\\usepackage{palatino}\n";
2641         }
2642         // Utopia
2643         else if (rm == "utopia") {
2644                 // fourier supersedes utopia.sty, but does
2645                 // not work with OT1 encoding.
2646                 if (LaTeXFeatures::isAvailable("fourier")
2647                     && font_encoding() != "default") {
2648                         os << "\\usepackage";
2649                         if (osf || sc) {
2650                                 os << '[';
2651                                 if (sc)
2652                                         os << "expert";
2653                                 if (osf && sc)
2654                                         os << ',';
2655                                 if (osf)
2656                                         os << "oldstyle";
2657                                 os << ']';
2658                         }
2659                         os << "{fourier}\n";
2660                 }
2661                 else
2662                         os << "\\usepackage{utopia}\n";
2663         }
2664         // Bera (complete fontset)
2665         else if (rm == "bera" && sf == "default" && tt == "default")
2666                 os << "\\usepackage{bera}\n";
2667         // everything else
2668         else if (rm != "default")
2669                 os << "\\usepackage" << "{" << rm << "}\n";
2670
2671         // SANS SERIF
2672         // Helvetica, Bera Sans
2673         if (sf == "helvet" || sf == "berasans") {
2674                 if (sfscale != 100)
2675                         os << "\\usepackage[scaled=" << float(sfscale) / 100
2676                            << "]{" << sf << "}\n";
2677                 else
2678                         os << "\\usepackage{" << sf << "}\n";
2679         }
2680         // Avant Garde
2681         else if (sf == "avant")
2682                 os << "\\usepackage{" << sf << "}\n";
2683         // Computer Modern, Latin Modern, CM Bright
2684         else if (sf != "default")
2685                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2686
2687         // monospaced/typewriter
2688         // Courier, LuxiMono
2689         if (tt == "luximono" || tt == "beramono") {
2690                 if (ttscale != 100)
2691                         os << "\\usepackage[scaled=" << float(ttscale) / 100
2692                            << "]{" << tt << "}\n";
2693                 else
2694                         os << "\\usepackage{" << tt << "}\n";
2695         }
2696         // Courier
2697         else if (tt == "courier" )
2698                 os << "\\usepackage{" << tt << "}\n";
2699         // Computer Modern, Latin Modern, CM Bright
2700         else if (tt != "default")
2701                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2702
2703         return os.str();
2704 }
2705
2706
2707 Encoding const & BufferParams::encoding() const
2708 {
2709         if (useXetex)
2710                 return *(encodings.fromLaTeXName("utf8-plain"));
2711         if (inputenc == "auto" || inputenc == "default")
2712                 return *language->encoding();
2713         Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2714         if (enc)
2715                 return *enc;
2716         LYXERR0("Unknown inputenc value `" << inputenc
2717                << "'. Using `auto' instead.");
2718         return *language->encoding();
2719 }
2720
2721
2722 CiteEngine BufferParams::citeEngine() const
2723 {
2724         // FIXME the class should provide the numerical/
2725         // authoryear choice
2726         if (documentClass().provides("natbib")
2727             && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2728                 return ENGINE_NATBIB_AUTHORYEAR;
2729         return cite_engine_;
2730 }
2731
2732
2733 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2734 {
2735         cite_engine_ = cite_engine;
2736 }
2737
2738 } // namespace lyx