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