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