]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
1f7d0db19686464135593a3d64b471b0eeb35ce6
[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 "Encoding.h"
27 #include "Language.h"
28 #include "LaTeXFeatures.h"
29 #include "ModuleList.h"
30 #include "Font.h"
31 #include "Lexer.h"
32 #include "LyXRC.h"
33 #include "OutputParams.h"
34 #include "Spacing.h"
35 #include "TexRow.h"
36 #include "VSpace.h"
37 #include "PDFOptions.h"
38
39 #include "frontends/alert.h"
40
41 #include "insets/InsetListingsParams.h"
42
43 #include "support/convert.h"
44 #include "support/debug.h"
45 #include "support/docstream.h"
46 #include "support/FileName.h"
47 #include "support/filetools.h"
48 #include "support/gettext.h"
49 #include "support/Messages.h"
50 #include "support/Translator.h"
51 #include "support/lstrings.h"
52
53 #include <algorithm>
54 #include <sstream>
55
56 using namespace std;
57 using namespace lyx::support;
58
59
60 static char const * const string_paragraph_separation[] = {
61         "indent", "skip", ""
62 };
63
64
65 static char const * const string_quotes_language[] = {
66         "english", "swedish", "german", "polish", "french", "danish", ""
67 };
68
69
70 static char const * const string_papersize[] = {
71         "default", "custom", "letterpaper", "legalpaper", "executivepaper",
72         "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
73 };
74
75
76 static char const * const string_orientation[] = {
77         "portrait", "landscape", ""
78 };
79
80
81 static char const * const string_footnotekinds[] = {
82         "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
83 };
84
85
86 static char const * const tex_graphics[] = {
87         "default", "dvips", "dvitops", "emtex",
88         "ln", "oztex", "textures", "none", ""
89 };
90
91
92 namespace lyx {
93
94 // Local translators
95 namespace {
96
97 // Paragraph separation
98 typedef Translator<string, BufferParams::ParagraphSeparation> ParSepTranslator;
99
100
101 ParSepTranslator const init_parseptranslator()
102 {
103         ParSepTranslator translator
104                 (string_paragraph_separation[0], BufferParams::ParagraphIndentSeparation);
105         translator.addPair(string_paragraph_separation[1], BufferParams::ParagraphSkipSeparation);
106         return translator;
107 }
108
109
110 ParSepTranslator const & parseptranslator()
111 {
112         static ParSepTranslator translator = init_parseptranslator();
113         return translator;
114 }
115
116
117 // Quotes language
118 typedef Translator<string, InsetQuotes::QuoteLanguage> QuotesLangTranslator;
119
120
121 QuotesLangTranslator const init_quoteslangtranslator()
122 {
123         QuotesLangTranslator translator
124                 (string_quotes_language[0], InsetQuotes::EnglishQuotes);
125         translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQuotes);
126         translator.addPair(string_quotes_language[2], InsetQuotes::GermanQuotes);
127         translator.addPair(string_quotes_language[3], InsetQuotes::PolishQuotes);
128         translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQuotes);
129         translator.addPair(string_quotes_language[5], InsetQuotes::DanishQuotes);
130         return translator;
131 }
132
133
134 QuotesLangTranslator const & quoteslangtranslator()
135 {
136         static QuotesLangTranslator translator = init_quoteslangtranslator();
137         return translator;
138 }
139
140
141 // Paper size
142 typedef Translator<string, PAPER_SIZE> PaperSizeTranslator;
143
144
145 static PaperSizeTranslator initPaperSizeTranslator()
146 {
147         PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
148         translator.addPair(string_papersize[1], PAPER_CUSTOM);
149         translator.addPair(string_papersize[2], PAPER_USLETTER);
150         translator.addPair(string_papersize[3], PAPER_USLEGAL);
151         translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
152         translator.addPair(string_papersize[5], PAPER_A3);
153         translator.addPair(string_papersize[6], PAPER_A4);
154         translator.addPair(string_papersize[7], PAPER_A5);
155         translator.addPair(string_papersize[8], PAPER_B3);
156         translator.addPair(string_papersize[9], PAPER_B4);
157         translator.addPair(string_papersize[10], PAPER_B5);
158         return translator;
159 }
160
161
162 PaperSizeTranslator const & papersizetranslator()
163 {
164         static PaperSizeTranslator translator = initPaperSizeTranslator();
165         return translator;
166 }
167
168
169 // Paper orientation
170 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
171
172
173 PaperOrientationTranslator const init_paperorientationtranslator()
174 {
175         PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
176         translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
177         return translator;
178 }
179
180
181 PaperOrientationTranslator const & paperorientationtranslator()
182 {
183         static PaperOrientationTranslator translator = init_paperorientationtranslator();
184         return translator;
185 }
186
187
188 // Page sides
189 typedef Translator<int, PageSides> SidesTranslator;
190
191
192 SidesTranslator const init_sidestranslator()
193 {
194         SidesTranslator translator(1, OneSide);
195         translator.addPair(2, TwoSides);
196         return translator;
197 }
198
199
200 SidesTranslator const & sidestranslator()
201 {
202         static SidesTranslator translator = init_sidestranslator();
203         return translator;
204 }
205
206
207 // LaTeX packages
208 typedef Translator<int, BufferParams::Package> PackageTranslator;
209
210
211 PackageTranslator const init_packagetranslator()
212 {
213         PackageTranslator translator(0, BufferParams::package_off);
214         translator.addPair(1, BufferParams::package_auto);
215         translator.addPair(2, BufferParams::package_on);
216         return translator;
217 }
218
219
220 PackageTranslator const & packagetranslator()
221 {
222         static PackageTranslator translator = init_packagetranslator();
223         return translator;
224 }
225
226
227 // Cite engine
228 typedef Translator<string, CiteEngine> CiteEngineTranslator;
229
230
231 CiteEngineTranslator const init_citeenginetranslator()
232 {
233         CiteEngineTranslator translator("basic", ENGINE_BASIC);
234         translator.addPair("natbib_numerical", ENGINE_NATBIB_NUMERICAL);
235         translator.addPair("natbib_authoryear", ENGINE_NATBIB_AUTHORYEAR);
236         translator.addPair("jurabib", ENGINE_JURABIB);
237         return translator;
238 }
239
240
241 CiteEngineTranslator const & citeenginetranslator()
242 {
243         static CiteEngineTranslator translator = init_citeenginetranslator();
244         return translator;
245 }
246
247
248 // Spacing
249 typedef Translator<string, Spacing::Space> SpaceTranslator;
250
251
252 SpaceTranslator const init_spacetranslator()
253 {
254         SpaceTranslator translator("default", Spacing::Default);
255         translator.addPair("single", Spacing::Single);
256         translator.addPair("onehalf", Spacing::Onehalf);
257         translator.addPair("double", Spacing::Double);
258         translator.addPair("other", Spacing::Other);
259         return translator;
260 }
261
262
263 SpaceTranslator const & spacetranslator()
264 {
265         static SpaceTranslator translator = init_spacetranslator();
266         return translator;
267 }
268
269
270 } // anon namespace
271
272
273 class BufferParams::Impl
274 {
275 public:
276         Impl();
277
278         AuthorList authorlist;
279         BranchList branchlist;
280         Bullet temp_bullets[4];
281         Bullet user_defined_bullets[4];
282         Spacing spacing;
283         /** This is the amount of space used for paragraph_separation "skip",
284          * and for detached paragraphs in "indented" documents.
285          */
286         VSpace defskip;
287         PDFOptions pdfoptions;
288         LayoutFileIndex baseClass_;
289 };
290
291
292 BufferParams::Impl::Impl()
293         : defskip(VSpace::MEDSKIP), baseClass_(string(""))
294 {
295         // set initial author
296         // FIXME UNICODE
297         authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
298 }
299
300
301 BufferParams::Impl *
302 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
303 {
304         LASSERT(ptr, /**/);
305
306         return new BufferParams::Impl(*ptr);
307 }
308
309
310 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
311 {
312         delete ptr;
313 }
314
315
316 BufferParams::BufferParams()
317         : pimpl_(new Impl)
318 {
319         setBaseClass(defaultBaseclass());
320         makeDocumentClass();
321         paragraph_separation = ParagraphIndentSeparation;
322         quotes_language = InsetQuotes::EnglishQuotes;
323         fontsize = "default";
324
325         /*  PaperLayout */
326         papersize = PAPER_DEFAULT;
327         orientation = ORIENTATION_PORTRAIT;
328         use_geometry = false;
329         use_amsmath = package_auto;
330         use_esint = package_auto;
331         cite_engine_ = ENGINE_BASIC;
332         use_bibtopic = false;
333         trackChanges = false;
334         outputChanges = false;
335         secnumdepth = 3;
336         tocdepth = 3;
337         language = default_language;
338         fontsRoman = "default";
339         fontsSans = "default";
340         fontsTypewriter = "default";
341         fontsDefaultFamily = "default";
342         fontsSC = false;
343         fontsOSF = false;
344         fontsSansScale = 100;
345         fontsTypewriterScale = 100;
346         inputenc = "auto";
347         graphicsDriver = "default";
348         sides = OneSide;
349         columns = 1;
350         listings_params = string();
351         pagestyle = "default";
352         compressed = false;
353         for (int iter = 0; iter < 4; ++iter) {
354                 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
355                 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
356         }
357 }
358
359
360 docstring BufferParams::B_(string const & l10n) const
361 {
362         LASSERT(language, /**/);
363         return getMessages(language->code()).get(l10n);
364 }
365
366
367 AuthorList & BufferParams::authors()
368 {
369         return pimpl_->authorlist;
370 }
371
372
373 AuthorList const & BufferParams::authors() const
374 {
375         return pimpl_->authorlist;
376 }
377
378
379 BranchList & BufferParams::branchlist()
380 {
381         return pimpl_->branchlist;
382 }
383
384
385 BranchList const & BufferParams::branchlist() const
386 {
387         return pimpl_->branchlist;
388 }
389
390
391 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
392 {
393         LASSERT(index < 4, /**/);
394         return pimpl_->temp_bullets[index];
395 }
396
397
398 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
399 {
400         LASSERT(index < 4, /**/);
401         return pimpl_->temp_bullets[index];
402 }
403
404
405 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
406 {
407         LASSERT(index < 4, /**/);
408         return pimpl_->user_defined_bullets[index];
409 }
410
411
412 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
413 {
414         LASSERT(index < 4, /**/);
415         return pimpl_->user_defined_bullets[index];
416 }
417
418
419 Spacing & BufferParams::spacing()
420 {
421         return pimpl_->spacing;
422 }
423
424
425 Spacing const & BufferParams::spacing() const
426 {
427         return pimpl_->spacing;
428 }
429
430
431 PDFOptions & BufferParams::pdfoptions()
432 {
433         return pimpl_->pdfoptions;
434 }
435
436
437 PDFOptions const & BufferParams::pdfoptions() const
438 {
439         return pimpl_->pdfoptions;
440 }
441
442
443 VSpace const & BufferParams::getDefSkip() const
444 {
445         return pimpl_->defskip;
446 }
447
448
449 void BufferParams::setDefSkip(VSpace const & vs)
450 {
451         pimpl_->defskip = vs;
452 }
453
454
455 string BufferParams::readToken(Lexer & lex, string const & token,
456         FileName const & filepath)
457 {
458         if (token == "\\textclass") {
459                 lex.next();
460                 string const classname = lex.getString();
461                 // if there exists a local layout file, ignore the system one
462                 // NOTE: in this case, the textclass (.cls file) is assumed to be available.
463                 string tcp;
464                 LayoutFileList & bcl = LayoutFileList::get();
465                 if (tcp.empty() && !filepath.empty())
466                         tcp = bcl.addLocalLayout(classname, filepath.absFilename());
467                 if (!tcp.empty())
468                         setBaseClass(tcp);
469                 else
470                         setBaseClass(classname);
471                 // We assume that a tex class exists for local or unknown layouts so this warning
472                 // will only be given for system layouts.
473                 if (!baseClass()->isTeXClassAvailable()) {
474                         docstring const msg =
475                                 bformat(_("The layout file requested by this document,\n"
476                                                  "%1$s.layout,\n"
477                                                  "is not usable. This is probably because a LaTeX\n"
478                                                  "class or style file required by it is not\n"
479                                                  "available. See the Customization documentation\n"
480                                                  "for more information.\n"), from_utf8(classname));
481                         frontend::Alert::warning(_("Document class not available"),
482                                        msg + _("LyX will not be able to produce output."));
483                 } 
484         } else if (token == "\\begin_preamble") {
485                 readPreamble(lex);
486         } else if (token == "\\begin_local_layout") {
487                 readLocalLayout(lex);
488         } else if (token == "\\begin_modules") {
489                 readModules(lex);
490         } else if (token == "\\begin_removed_modules") {
491                 readRemovedModules(lex);
492         } else if (token == "\\options") {
493                 lex.eatLine();
494                 options = lex.getString();
495         } else if (token == "\\master") {
496                 lex.eatLine();
497                 master = lex.getString();
498         } else if (token == "\\language") {
499                 readLanguage(lex);
500         } else if (token == "\\inputencoding") {
501                 lex >> inputenc;
502         } else if (token == "\\graphics") {
503                 readGraphicsDriver(lex);
504         } else if (token == "\\font_roman") {
505                 lex >> fontsRoman;
506         } else if (token == "\\font_sans") {
507                 lex >> fontsSans;
508         } else if (token == "\\font_typewriter") {
509                 lex >> fontsTypewriter;
510         } else if (token == "\\font_default_family") {
511                 lex >> fontsDefaultFamily;
512         } else if (token == "\\font_sc") {
513                 lex >> fontsSC;
514         } else if (token == "\\font_osf") {
515                 lex >> fontsOSF;
516         } else if (token == "\\font_sf_scale") {
517                 lex >> fontsSansScale;
518         } else if (token == "\\font_tt_scale") {
519                 lex >> fontsTypewriterScale;
520         } else if (token == "\\font_cjk") {
521                 lex >> fontsCJK;
522         } else if (token == "\\paragraph_separation") {
523                 string parsep;
524                 lex >> parsep;
525                 paragraph_separation = parseptranslator().find(parsep);
526         } else if (token == "\\defskip") {
527                 lex.next();
528                 string defskip = lex.getString();
529                 if (defskip == "defskip")
530                         // this is invalid
531                         defskip = "medskip";
532                 pimpl_->defskip = VSpace(defskip);
533         } else if (token == "\\quotes_language") {
534                 string quotes_lang;
535                 lex >> quotes_lang;
536                 quotes_language = quoteslangtranslator().find(quotes_lang);
537         } else if (token == "\\papersize") {
538                 string ppsize;
539                 lex >> ppsize;
540                 papersize = papersizetranslator().find(ppsize);
541         } else if (token == "\\use_geometry") {
542                 lex >> use_geometry;
543         } else if (token == "\\use_amsmath") {
544                 int use_ams;
545                 lex >> use_ams;
546                 use_amsmath = packagetranslator().find(use_ams);
547         } else if (token == "\\use_esint") {
548                 int useesint;
549                 lex >> useesint;
550                 use_esint = packagetranslator().find(useesint);
551         } else if (token == "\\cite_engine") {
552                 string engine;
553                 lex >> engine;
554                 cite_engine_ = citeenginetranslator().find(engine);
555         } else if (token == "\\use_bibtopic") {
556                 lex >> use_bibtopic;
557         } else if (token == "\\tracking_changes") {
558                 lex >> trackChanges;
559         } else if (token == "\\output_changes") {
560                 lex >> outputChanges;
561         } else if (token == "\\branch") {
562                 lex.next();
563                 docstring branch = lex.getDocString();
564                 branchlist().add(branch);
565                 while (true) {
566                         lex.next();
567                         string const tok = lex.getString();
568                         if (tok == "\\end_branch")
569                                 break;
570                         Branch * branch_ptr = branchlist().find(branch);
571                         if (tok == "\\selected") {
572                                 lex.next();
573                                 if (branch_ptr)
574                                         branch_ptr->setSelected(lex.getInteger());
575                         }
576                         // not yet operational
577                         if (tok == "\\color") {
578                                 lex.eatLine();
579                                 string color = lex.getString();
580                                 if (branch_ptr)
581                                         branch_ptr->setColor(color);
582                                 // Update also the Color table:
583                                 if (color == "none")
584                                         color = lcolor.getX11Name(Color_background);
585                                 // FIXME UNICODE
586                                 lcolor.setColor(to_utf8(branch), color);
587
588                         }
589                 }
590         } else if (token == "\\author") {
591                 lex.eatLine();
592                 istringstream ss(lex.getString());
593                 Author a;
594                 ss >> a;
595                 author_map.push_back(pimpl_->authorlist.record(a));
596         } else if (token == "\\paperorientation") {
597                 string orient;
598                 lex >> orient;
599                 orientation = paperorientationtranslator().find(orient);
600         } else if (token == "\\paperwidth") {
601                 lex >> paperwidth;
602         } else if (token == "\\paperheight") {
603                 lex >> paperheight;
604         } else if (token == "\\leftmargin") {
605                 lex >> leftmargin;
606         } else if (token == "\\topmargin") {
607                 lex >> topmargin;
608         } else if (token == "\\rightmargin") {
609                 lex >> rightmargin;
610         } else if (token == "\\bottommargin") {
611                 lex >> bottommargin;
612         } else if (token == "\\headheight") {
613                 lex >> headheight;
614         } else if (token == "\\headsep") {
615                 lex >> headsep;
616         } else if (token == "\\footskip") {
617                 lex >> footskip;
618         } else if (token == "\\columnsep") {
619                 lex >> columnsep;
620         } else if (token == "\\paperfontsize") {
621                 lex >> fontsize;
622         } else if (token == "\\papercolumns") {
623                 lex >> columns;
624         } else if (token == "\\listings_params") {
625                 string par;
626                 lex >> par;
627                 listings_params = InsetListingsParams(par).params();
628         } else if (token == "\\papersides") {
629                 int psides;
630                 lex >> psides;
631                 sides = sidestranslator().find(psides);
632         } else if (token == "\\paperpagestyle") {
633                 lex >> pagestyle;
634         } else if (token == "\\bullet") {
635                 readBullets(lex);
636         } else if (token == "\\bulletLaTeX") {
637                 readBulletsLaTeX(lex);
638         } else if (token == "\\secnumdepth") {
639                 lex >> secnumdepth;
640         } else if (token == "\\tocdepth") {
641                 lex >> tocdepth;
642         } else if (token == "\\spacing") {
643                 string nspacing;
644                 lex >> nspacing;
645                 string tmp_val;
646                 if (nspacing == "other") {
647                         lex >> tmp_val;
648                 }
649                 spacing().set(spacetranslator().find(nspacing), tmp_val);
650         } else if (token == "\\float_placement") {
651                 lex >> float_placement;
652
653         } else if (prefixIs(token, "\\pdf_") || token == "\\use_hyperref") {
654                 string toktmp = pdfoptions().readToken(lex, token);
655                 if (!toktmp.empty()) {
656                         lyxerr << "PDFOptions::readToken(): Unknown token: " <<
657                                 toktmp << endl;
658                         return toktmp;
659                 }
660         } else {
661                 lyxerr << "BufferParams::readToken(): Unknown token: " << 
662                         token << endl;
663                 return token;
664         }
665
666         return string();
667 }
668
669
670 void BufferParams::writeFile(ostream & os) const
671 {
672         // The top of the file is written by the buffer.
673         // Prints out the buffer info into the .lyx file given by file
674
675         // the textclass
676         os << "\\textclass " << baseClass()->name() << '\n';
677
678         // then the preamble
679         if (!preamble.empty()) {
680                 // remove '\n' from the end of preamble
681                 string const tmppreamble = rtrim(preamble, "\n");
682                 os << "\\begin_preamble\n"
683                    << tmppreamble
684                    << "\n\\end_preamble\n";
685         }
686
687         // the options
688         if (!options.empty()) {
689                 os << "\\options " << options << '\n';
690         }
691
692         // the master document
693         if (!master.empty()) {
694                 os << "\\master " << master << '\n';
695         }
696         
697         // removed modules
698         if (!removedModules_.empty()) {
699                 os << "\\begin_removed_modules" << '\n';
700                 set<string>::const_iterator it = removedModules_.begin();
701                 set<string>::const_iterator en = removedModules_.end();
702                 for (; it != en; it++)
703                         os << *it << '\n';
704                 os << "\\end_removed_modules" << '\n';
705         }
706
707         // the modules
708         if (!layoutModules_.empty()) {
709                 os << "\\begin_modules" << '\n';
710                 LayoutModuleList::const_iterator it = layoutModules_.begin();
711                 LayoutModuleList::const_iterator en = layoutModules_.end();
712                 for (; it != en; it++)
713                         os << *it << '\n';
714                 os << "\\end_modules" << '\n';
715         }
716         
717         // local layout information
718         if (!local_layout.empty()) {
719                 // remove '\n' from the end 
720                 string const tmplocal = rtrim(local_layout, "\n");
721                 os << "\\begin_local_layout\n"
722                    << tmplocal
723                    << "\n\\end_local_layout\n";
724         }
725
726         // then the text parameters
727         if (language != ignore_language)
728                 os << "\\language " << language->lang() << '\n';
729         os << "\\inputencoding " << inputenc
730            << "\n\\font_roman " << fontsRoman
731            << "\n\\font_sans " << fontsSans
732            << "\n\\font_typewriter " << fontsTypewriter
733            << "\n\\font_default_family " << fontsDefaultFamily
734            << "\n\\font_sc " << convert<string>(fontsSC)
735            << "\n\\font_osf " << convert<string>(fontsOSF)
736            << "\n\\font_sf_scale " << fontsSansScale
737            << "\n\\font_tt_scale " << fontsTypewriterScale
738            << '\n';
739         if (!fontsCJK.empty()) {
740                 os << "\\font_cjk " << fontsCJK << '\n';
741         }
742         os << "\n\\graphics " << graphicsDriver << '\n';
743
744         if (!float_placement.empty()) {
745                 os << "\\float_placement " << float_placement << '\n';
746         }
747         os << "\\paperfontsize " << fontsize << '\n';
748
749         spacing().writeFile(os);
750         pdfoptions().writeFile(os);
751
752         os << "\\papersize " << string_papersize[papersize]
753            << "\n\\use_geometry " << convert<string>(use_geometry)
754            << "\n\\use_amsmath " << use_amsmath
755            << "\n\\use_esint " << use_esint
756            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
757            << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
758            << "\n\\paperorientation " << string_orientation[orientation]
759            << '\n';
760
761         BranchList::const_iterator it = branchlist().begin();
762         BranchList::const_iterator end = branchlist().end();
763         for (; it != end; ++it) {
764                 os << "\\branch " << to_utf8(it->branch())
765                    << "\n\\selected " << it->isSelected()
766                    << "\n\\color " << lyx::X11hexname(it->color())
767                    << "\n\\end_branch"
768                    << "\n";
769         }
770
771         if (!paperwidth.empty())
772                 os << "\\paperwidth "
773                    << VSpace(paperwidth).asLyXCommand() << '\n';
774         if (!paperheight.empty())
775                 os << "\\paperheight "
776                    << VSpace(paperheight).asLyXCommand() << '\n';
777         if (!leftmargin.empty())
778                 os << "\\leftmargin "
779                    << VSpace(leftmargin).asLyXCommand() << '\n';
780         if (!topmargin.empty())
781                 os << "\\topmargin "
782                    << VSpace(topmargin).asLyXCommand() << '\n';
783         if (!rightmargin.empty())
784                 os << "\\rightmargin "
785                    << VSpace(rightmargin).asLyXCommand() << '\n';
786         if (!bottommargin.empty())
787                 os << "\\bottommargin "
788                    << VSpace(bottommargin).asLyXCommand() << '\n';
789         if (!headheight.empty())
790                 os << "\\headheight "
791                    << VSpace(headheight).asLyXCommand() << '\n';
792         if (!headsep.empty())
793                 os << "\\headsep "
794                    << VSpace(headsep).asLyXCommand() << '\n';
795         if (!footskip.empty())
796                 os << "\\footskip "
797                    << VSpace(footskip).asLyXCommand() << '\n';
798         if (!columnsep.empty())
799                 os << "\\columnsep " 
800                          << VSpace(columnsep).asLyXCommand() << '\n';
801         os << "\\secnumdepth " << secnumdepth
802            << "\n\\tocdepth " << tocdepth
803            << "\n\\paragraph_separation "
804            << string_paragraph_separation[paragraph_separation]
805            << "\n\\defskip " << getDefSkip().asLyXCommand()
806            << "\n\\quotes_language "
807            << string_quotes_language[quotes_language]
808            << "\n\\papercolumns " << columns
809            << "\n\\papersides " << sides
810            << "\n\\paperpagestyle " << pagestyle << '\n';
811         if (!listings_params.empty())
812                 os << "\\listings_params \"" <<
813                         InsetListingsParams(listings_params).encodedString() << "\"\n";
814         for (int i = 0; i < 4; ++i) {
815                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
816                         if (user_defined_bullet(i).getFont() != -1) {
817                                 os << "\\bullet " << i << " "
818                                    << user_defined_bullet(i).getFont() << " "
819                                    << user_defined_bullet(i).getCharacter() << " "
820                                    << user_defined_bullet(i).getSize() << "\n";
821                         }
822                         else {
823                                 // FIXME UNICODE
824                                 os << "\\bulletLaTeX " << i << " \""
825                                    << lyx::to_ascii(user_defined_bullet(i).getText())
826                                    << "\"\n";
827                         }
828                 }
829         }
830
831         os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
832         os << "\\output_changes " << convert<string>(outputChanges) << "\n";
833
834         AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
835         AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
836         for (; a_it != a_end; ++a_it) {
837                 if (a_it->second.used())
838                         os << "\\author " << a_it->second << "\n";
839                 else
840                         os << "\\author " << Author() << "\n";
841         }
842 }
843
844
845 void BufferParams::validate(LaTeXFeatures & features) const
846 {
847         features.require(documentClass().requires());
848
849         if (outputChanges) {
850                 bool dvipost    = LaTeXFeatures::isAvailable("dvipost");
851                 bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
852                                   LaTeXFeatures::isAvailable("xcolor");
853
854                 switch (features.runparams().flavor) {
855                 case OutputParams::LATEX:
856                         if (dvipost) {
857                                 features.require("ct-dvipost");
858                                 features.require("dvipost");
859                         } else if (xcolorsoul) {
860                                 features.require("ct-xcolor-soul");
861                                 features.require("soul");
862                                 features.require("xcolor");
863                         } else {
864                                 features.require("ct-none");
865                         }
866                         break;
867                 case OutputParams::PDFLATEX:
868                         if (xcolorsoul) {
869                                 features.require("ct-xcolor-soul");
870                                 features.require("soul");
871                                 features.require("xcolor");
872                                 // improves color handling in PDF output
873                                 features.require("pdfcolmk"); 
874                         } else {
875                                 features.require("ct-none");
876                         }
877                         break;
878                 default:
879                         break;
880                 }
881         }
882
883         // Floats with 'Here definitely' as default setting.
884         if (float_placement.find('H') != string::npos)
885                 features.require("float");
886
887         // AMS Style is at document level
888         if (use_amsmath == package_on
889             || documentClass().provides("amsmath"))
890                 features.require("amsmath");
891         if (use_esint == package_on)
892                 features.require("esint");
893
894         // Document-level line spacing
895         if (spacing().getSpace() != Spacing::Single && !spacing().isDefault())
896                 features.require("setspace");
897
898         // the bullet shapes are buffer level not paragraph level
899         // so they are tested here
900         for (int i = 0; i < 4; ++i) {
901                 if (user_defined_bullet(i) == ITEMIZE_DEFAULTS[i]) 
902                         continue;
903                 int const font = user_defined_bullet(i).getFont();
904                 if (font == 0) {
905                         int const c = user_defined_bullet(i).getCharacter();
906                         if (c == 16
907                             || c == 17
908                             || c == 25
909                             || c == 26
910                             || c == 31) {
911                                 features.require("latexsym");
912                         }
913                 } else if (font == 1) {
914                         features.require("amssymb");
915                 } else if (font >= 2 && font <= 5) {
916                         features.require("pifont");
917                 }
918         }
919
920         if (pdfoptions().use_hyperref) {
921                 features.require("hyperref");
922                 // due to interferences with babel and hyperref, the color package has to
923                 // be loaded after hyperref when hyperref is used with the colorlinks
924                 // option, see http://bugzilla.lyx.org/show_bug.cgi?id=5291
925                 if (pdfoptions().colorlinks)
926                         features.require("color");
927         }
928
929         if (language->lang() == "vietnamese")
930                 features.require("vietnamese");
931         else if (language->lang() == "japanese")
932                 features.require("japanese");
933 }
934
935
936 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
937                               TexRow & texrow) const
938 {
939         os << "\\documentclass";
940
941         DocumentClass const & tclass = documentClass();
942
943         ostringstream clsoptions; // the document class options.
944
945         if (tokenPos(tclass.opt_fontsize(),
946                      '|', fontsize) >= 0) {
947                 // only write if existing in list (and not default)
948                 clsoptions << fontsize << "pt,";
949         }
950
951         // custom, A3, B3 and B4 paper sizes need geometry
952         bool nonstandard_papersize = papersize == PAPER_B3
953                 || papersize == PAPER_B4
954                 || papersize == PAPER_A3
955                 || papersize == PAPER_CUSTOM;
956
957         if (!use_geometry) {
958                 switch (papersize) {
959                 case PAPER_A4:
960                         clsoptions << "a4paper,";
961                         break;
962                 case PAPER_USLETTER:
963                         clsoptions << "letterpaper,";
964                         break;
965                 case PAPER_A5:
966                         clsoptions << "a5paper,";
967                         break;
968                 case PAPER_B5:
969                         clsoptions << "b5paper,";
970                         break;
971                 case PAPER_USEXECUTIVE:
972                         clsoptions << "executivepaper,";
973                         break;
974                 case PAPER_USLEGAL:
975                         clsoptions << "legalpaper,";
976                         break;
977                 case PAPER_DEFAULT:
978                 case PAPER_A3:
979                 case PAPER_B3:
980                 case PAPER_B4:
981                 case PAPER_CUSTOM:
982                         break;
983                 }
984         }
985
986         // if needed
987         if (sides != tclass.sides()) {
988                 switch (sides) {
989                 case OneSide:
990                         clsoptions << "oneside,";
991                         break;
992                 case TwoSides:
993                         clsoptions << "twoside,";
994                         break;
995                 }
996         }
997
998         // if needed
999         if (columns != tclass.columns()) {
1000                 if (columns == 2)
1001                         clsoptions << "twocolumn,";
1002                 else
1003                         clsoptions << "onecolumn,";
1004         }
1005
1006         if (!use_geometry
1007             && orientation == ORIENTATION_LANDSCAPE)
1008                 clsoptions << "landscape,";
1009
1010         // language should be a parameter to \documentclass
1011         if (language->babel() == "hebrew"
1012             && default_language->babel() != "hebrew")
1013                 // This seems necessary
1014                 features.useLanguage(default_language);
1015
1016         ostringstream language_options;
1017         bool const use_babel = features.useBabel();
1018         if (use_babel) {
1019                 language_options << features.getLanguages();
1020                 if (!language->babel().empty()) {
1021                         if (!language_options.str().empty())
1022                                 language_options << ',';
1023                         language_options << language->babel();
1024                 }
1025                 // if Vietnamese is used, babel must directly be loaded
1026                 // with language options, not in the class options, see
1027                 // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1028                 size_t viet = language_options.str().find("vietnam");
1029                 // viet = string::npos when not found
1030                 // if Japanese is used, babel must directly be loaded
1031                 // with language options, not in the class options, see
1032                 // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1033                 size_t japan = language_options.str().find("japanese");
1034                 // japan = string::npos when not found
1035                 if (lyxrc.language_global_options
1036                         && !language_options.str().empty()
1037                         && viet == string::npos && japan == string::npos)
1038                         clsoptions << language_options.str() << ',';
1039         }
1040
1041         // the user-defined options
1042         if (!options.empty()) {
1043                 clsoptions << options << ',';
1044         }
1045
1046         string strOptions(clsoptions.str());
1047         if (!strOptions.empty()) {
1048                 strOptions = rtrim(strOptions, ",");
1049                 // FIXME UNICODE
1050                 os << '[' << from_utf8(strOptions) << ']';
1051         }
1052
1053         os << '{' << from_ascii(tclass.latexname()) << "}\n";
1054         texrow.newline();
1055         // end of \documentclass defs
1056
1057         // font selection must be done before loading fontenc.sty
1058         string const fonts =
1059                 loadFonts(fontsRoman, fontsSans,
1060                           fontsTypewriter, fontsSC, fontsOSF,
1061                           fontsSansScale, fontsTypewriterScale);
1062         if (!fonts.empty()) {
1063                 os << from_ascii(fonts);
1064                 texrow.newline();
1065         }
1066         if (fontsDefaultFamily != "default")
1067                 os << "\\renewcommand{\\familydefault}{\\"
1068                    << from_ascii(fontsDefaultFamily) << "}\n";
1069
1070         // set font encoding
1071         // this one is not per buffer
1072         // for arabic_arabi and farsi we also need to load the LAE and
1073         // LFE encoding
1074         if (lyxrc.fontenc != "default" && language->lang() != "japanese") {
1075                 if (language->lang() == "arabic_arabi"
1076                     || language->lang() == "farsi") {
1077                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1078                            << ",LFE,LAE]{fontenc}\n";
1079                         texrow.newline();
1080                 } else {
1081                         os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
1082                            << "]{fontenc}\n";
1083                         texrow.newline();
1084                 }
1085         }
1086
1087         // handle inputenc etc.
1088         writeEncodingPreamble(os, features, texrow);
1089
1090         if (!listings_params.empty() || features.isRequired("listings")) {
1091                 os << "\\usepackage{listings}\n";
1092                 texrow.newline();
1093         }
1094         if (!listings_params.empty()) {
1095                 os << "\\lstset{";
1096                 // do not test validity because listings_params is 
1097                 // supposed to be valid
1098                 string par =
1099                         InsetListingsParams(listings_params).separatedParams(true);
1100                 // we can't support all packages, but we should load the color package
1101                 if (par.find("\\color", 0) != string::npos)
1102                         features.require("color");
1103                 os << from_utf8(par);
1104                 // count the number of newlines
1105                 for (size_t i = 0; i < par.size(); ++i)
1106                         if (par[i] == '\n')
1107                                 texrow.newline();
1108                 os << "}\n";
1109                 texrow.newline();
1110         }
1111         if (use_geometry || nonstandard_papersize) {
1112                 os << "\\usepackage{geometry}\n";
1113                 texrow.newline();
1114                 os << "\\geometry{verbose";
1115                 if (orientation == ORIENTATION_LANDSCAPE)
1116                         os << ",landscape";
1117                 switch (papersize) {
1118                 case PAPER_CUSTOM:
1119                         if (!paperwidth.empty())
1120                                 os << ",paperwidth="
1121                                    << from_ascii(paperwidth);
1122                         if (!paperheight.empty())
1123                                 os << ",paperheight="
1124                                    << from_ascii(paperheight);
1125                         break;
1126                 case PAPER_USLETTER:
1127                         os << ",letterpaper";
1128                         break;
1129                 case PAPER_USLEGAL:
1130                         os << ",legalpaper";
1131                         break;
1132                 case PAPER_USEXECUTIVE:
1133                         os << ",executivepaper";
1134                         break;
1135                 case PAPER_A3:
1136                         os << ",a3paper";
1137                         break;
1138                 case PAPER_A4:
1139                         os << ",a4paper";
1140                         break;
1141                 case PAPER_A5:
1142                         os << ",a5paper";
1143                         break;
1144                 case PAPER_B3:
1145                         os << ",b3paper";
1146                         break;
1147                 case PAPER_B4:
1148                         os << ",b4paper";
1149                         break;
1150                 case PAPER_B5:
1151                         os << ",b5paper";
1152                         break;
1153                 default:
1154                         // default papersize ie PAPER_DEFAULT
1155                         switch (lyxrc.default_papersize) {
1156                         case PAPER_DEFAULT: // keep compiler happy
1157                         case PAPER_USLETTER:
1158                                 os << ",letterpaper";
1159                                 break;
1160                         case PAPER_USLEGAL:
1161                                 os << ",legalpaper";
1162                                 break;
1163                         case PAPER_USEXECUTIVE:
1164                                 os << ",executivepaper";
1165                                 break;
1166                         case PAPER_A3:
1167                                 os << ",a3paper";
1168                                 break;
1169                         case PAPER_A4:
1170                                 os << ",a4paper";
1171                                 break;
1172                         case PAPER_A5:
1173                                 os << ",a5paper";
1174                                 break;
1175                         case PAPER_B5:
1176                                 os << ",b5paper";
1177                                 break;
1178                         case PAPER_B3:
1179                         case PAPER_B4:
1180                         case PAPER_CUSTOM:
1181                                 break;
1182                         }
1183                 }
1184                 if (!topmargin.empty())
1185                         os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1186                 if (!bottommargin.empty())
1187                         os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1188                 if (!leftmargin.empty())
1189                         os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1190                 if (!rightmargin.empty())
1191                         os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1192                 if (!headheight.empty())
1193                         os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1194                 if (!headsep.empty())
1195                         os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1196                 if (!footskip.empty())
1197                         os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1198                 if (!columnsep.empty())
1199                         os << ",columnsep=" << from_ascii(Length(columnsep).asLatexString());
1200                 os << "}\n";
1201                 texrow.newline();
1202         } else if (orientation == ORIENTATION_LANDSCAPE) {
1203                 features.require("papersize");
1204         }
1205
1206         if (tokenPos(tclass.opt_pagestyle(),
1207                      '|', pagestyle) >= 0) {
1208                 if (pagestyle == "fancy") {
1209                         os << "\\usepackage{fancyhdr}\n";
1210                         texrow.newline();
1211                 }
1212                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1213                 texrow.newline();
1214         }
1215
1216         // Only if class has a ToC hierarchy
1217         if (tclass.hasTocLevels()) {
1218                 if (secnumdepth != tclass.secnumdepth()) {
1219                         os << "\\setcounter{secnumdepth}{"
1220                            << secnumdepth
1221                            << "}\n";
1222                         texrow.newline();
1223                 }
1224                 if (tocdepth != tclass.tocdepth()) {
1225                         os << "\\setcounter{tocdepth}{"
1226                            << tocdepth
1227                            << "}\n";
1228                         texrow.newline();
1229                 }
1230         }
1231
1232         if (paragraph_separation) {
1233                 switch (getDefSkip().kind()) {
1234                 case VSpace::SMALLSKIP:
1235                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1236                         break;
1237                 case VSpace::MEDSKIP:
1238                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1239                         break;
1240                 case VSpace::BIGSKIP:
1241                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1242                         break;
1243                 case VSpace::LENGTH:
1244                         os << "\\setlength{\\parskip}{"
1245                            << from_utf8(getDefSkip().length().asLatexString())
1246                            << "}\n";
1247                         break;
1248                 default: // should never happen // Then delete it.
1249                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1250                         break;
1251                 }
1252                 texrow.newline();
1253
1254                 os << "\\setlength{\\parindent}{0pt}\n";
1255                 texrow.newline();
1256         }
1257
1258         // Now insert the LyX specific LaTeX commands...
1259         docstring lyxpreamble;
1260
1261         // due to interferences with babel and hyperref, the color package has to
1262         // be loaded (when it is not already loaded) before babel when hyperref
1263         // is used with the colorlinks option, see
1264         // http://bugzilla.lyx.org/show_bug.cgi?id=5291
1265         // we decided therefore to load color always before babel, see
1266         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg144349.html
1267         lyxpreamble += from_ascii(features.getColorOptions());
1268         
1269         // If we use hyperref, jurabib, japanese, or vietnamese, we have to call babel before them.
1270         if (use_babel
1271                 && (features.isRequired("jurabib")
1272                         || features.isRequired("hyperref")
1273                         || features.isRequired("vietnamese")
1274                         || features.isRequired("japanese") ) ) {
1275                                 // FIXME UNICODE
1276                                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1277                                 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1278         }
1279
1280         // The optional packages;
1281         lyxpreamble += from_ascii(features.getPackages());
1282
1283         // Line spacing
1284         lyxpreamble += from_utf8(spacing().writePreamble(tclass.provides("SetSpace")));
1285
1286         // PDF support.
1287         // * Hyperref manual: "Make sure it comes last of your loaded
1288         //   packages, to give it a fighting chance of not being over-written,
1289         //   since its job is to redefine many LATEX commands."
1290         // * Email from Heiko Oberdiek: "It is usually better to load babel
1291         //   before hyperref. Then hyperref has a chance to detect babel.
1292         // * Has to be loaded before the "LyX specific LaTeX commands" to
1293         //   avoid errors with algorithm floats.
1294         // use hyperref explicitely when it is required
1295         if (features.isRequired("hyperref")) {
1296                 odocstringstream oss;
1297                 pdfoptions().writeLaTeX(oss, documentClass().provides("hyperref"));
1298                 lyxpreamble += oss.str();
1299         }
1300         
1301         // Will be surrounded by \makeatletter and \makeatother when needed
1302         docstring atlyxpreamble;
1303
1304         // Some macros LyX will need
1305         docstring tmppreamble(from_ascii(features.getMacros()));
1306
1307         if (!tmppreamble.empty())
1308                 atlyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1309                         "LyX specific LaTeX commands.\n"
1310                         + tmppreamble + '\n';
1311
1312         // the text class specific preamble
1313         tmppreamble = features.getTClassPreamble();
1314         if (!tmppreamble.empty())
1315                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1316                         "Textclass specific LaTeX commands.\n"
1317                         + tmppreamble + '\n';
1318
1319         /* the user-defined preamble */
1320         if (!preamble.empty())
1321                 // FIXME UNICODE
1322                 atlyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1323                         "User specified LaTeX commands.\n"
1324                         + from_utf8(preamble) + '\n';
1325
1326         // subfig loads internally the LaTeX package "caption". As
1327         // caption is a very popular package, users will load it in
1328         // the preamble. Therefore we must load subfig behind the
1329         // user-defined preamble and check if the caption package was
1330         // loaded or not. For the case that caption is loaded before
1331         // subfig, there is the subfig option "caption=false". This
1332         // option also works when a koma-script class is used and
1333         // koma's own caption commands are used instead of caption. We
1334         // use \PassOptionsToPackage here because the user could have
1335         // already loaded subfig in the preamble.
1336         if (features.isRequired("subfig")) {
1337                 atlyxpreamble += "\\@ifundefined{showcaptionsetup}{}{%\n"
1338                         " \\PassOptionsToPackage{caption=false}{subfig}}\n"
1339                         "\\usepackage{subfig}\n";
1340         }
1341
1342         // Itemize bullet settings need to be last in case the user
1343         // defines their own bullets that use a package included
1344         // in the user-defined preamble -- ARRae
1345         // Actually it has to be done much later than that
1346         // since some packages like frenchb make modifications
1347         // at \begin{document} time -- JMarc
1348         docstring bullets_def;
1349         for (int i = 0; i < 4; ++i) {
1350                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1351                         if (bullets_def.empty())
1352                                 bullets_def += "\\AtBeginDocument{\n";
1353                         bullets_def += "  \\def\\labelitemi";
1354                         switch (i) {
1355                                 // `i' is one less than the item to modify
1356                         case 0:
1357                                 break;
1358                         case 1:
1359                                 bullets_def += 'i';
1360                                 break;
1361                         case 2:
1362                                 bullets_def += "ii";
1363                                 break;
1364                         case 3:
1365                                 bullets_def += 'v';
1366                                 break;
1367                         }
1368                         bullets_def += '{' +
1369                                 user_defined_bullet(i).getText()
1370                                 + "}\n";
1371                 }
1372         }
1373
1374         if (!bullets_def.empty())
1375                 atlyxpreamble += bullets_def + "}\n\n";
1376
1377         if (atlyxpreamble.find(from_ascii("@")) != docstring::npos)
1378                 lyxpreamble += "\n\\makeatletter\n"
1379                         + atlyxpreamble + "\\makeatother\n\n";
1380         else
1381                 lyxpreamble += '\n' + atlyxpreamble;
1382
1383         // We try to load babel late, in case it interferes with other packages.
1384         // Jurabib and Hyperref have to be called after babel, though.
1385         if (use_babel && !features.isRequired("jurabib")
1386             && !features.isRequired("hyperref")
1387             && !features.isRequired("vietnamese")
1388             && !features.isRequired("japanese")) {
1389                 // FIXME UNICODE
1390                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1391                 lyxpreamble += from_utf8(features.getBabelOptions()) + '\n';
1392         }
1393
1394         int const nlines =
1395                 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1396         for (int j = 0; j != nlines; ++j) {
1397                 texrow.newline();
1398         }
1399
1400         os << lyxpreamble;
1401         return use_babel;
1402 }
1403
1404
1405 void BufferParams::useClassDefaults()
1406 {
1407         DocumentClass const & tclass = documentClass();
1408
1409         sides = tclass.sides();
1410         columns = tclass.columns();
1411         pagestyle = tclass.pagestyle();
1412         options = tclass.options();
1413         // Only if class has a ToC hierarchy
1414         if (tclass.hasTocLevels()) {
1415                 secnumdepth = tclass.secnumdepth();
1416                 tocdepth = tclass.tocdepth();
1417         }
1418 }
1419
1420
1421 bool BufferParams::hasClassDefaults() const
1422 {
1423         DocumentClass const & tclass = documentClass();
1424
1425         return sides == tclass.sides()
1426                 && columns == tclass.columns()
1427                 && pagestyle == tclass.pagestyle()
1428                 && options == tclass.options()
1429                 && secnumdepth == tclass.secnumdepth()
1430                 && tocdepth == tclass.tocdepth();
1431 }
1432
1433
1434 DocumentClass const & BufferParams::documentClass() const
1435 {
1436         return *doc_class_;
1437 }
1438
1439
1440 DocumentClass const * BufferParams::documentClassPtr() const {
1441         return doc_class_;
1442 }
1443
1444
1445 void BufferParams::setDocumentClass(DocumentClass const * const tc) {
1446         // evil, but this function is evil
1447         doc_class_ = const_cast<DocumentClass *>(tc);
1448 }
1449
1450
1451 bool BufferParams::setBaseClass(string const & classname)
1452 {
1453         LYXERR(Debug::TCLASS, "setBaseClass: " << classname);
1454         LayoutFileList & bcl = LayoutFileList::get();
1455         if (!bcl.haveClass(classname)) {
1456                 docstring s = 
1457                         bformat(_("The document class %1$s could not be found. "
1458                                 "A default textclass with default layouts will be used. "
1459                                 "LyX might not be able to produce output unless a correct "
1460                                 "textclass is selected from the document settings dialog."),
1461                         from_utf8(classname));
1462                 frontend::Alert::error(_("Document class not found"), s);
1463                 bcl.addEmptyClass(classname);
1464         }
1465
1466         bool const success = bcl[classname].load();
1467         if (!success) { 
1468                 docstring s = 
1469                         bformat(_("The document class %1$s could not be loaded."),
1470                         from_utf8(classname));
1471                 frontend::Alert::error(_("Could not load class"), s);
1472                 return false;
1473         }
1474
1475         pimpl_->baseClass_ = classname;
1476
1477         // add any required modules not already in use
1478         set<string> const & mods = baseClass()->defaultModules();
1479         set<string>::const_iterator mit = mods.begin();
1480         set<string>::const_iterator men = mods.end();
1481         for (; mit != men; mit++) {
1482                 string const & modName = *mit;
1483                 // see if we're already in use
1484                 if (find(layoutModules_.begin(), layoutModules_.end(), modName) != 
1485                     layoutModules_.end()) {
1486                         LYXERR(Debug::TCLASS, "Default module `" << modName << 
1487                                         "' not added because already used.");
1488                         continue;
1489                 }
1490                 // make sure the user hasn't removed it
1491                 if (find(removedModules_.begin(), removedModules_.end(), modName) != 
1492                     removedModules_.end()) {
1493                         LYXERR(Debug::TCLASS, "Default module `" << modName << 
1494                                         "' not added because removed by user.");
1495                         continue;
1496                 }
1497                 // Now we want to check the list of selected modules to see if any of them
1498                 // exclude this one.
1499                 bool foundit = false;
1500                 // so iterate over the selected modules...
1501                 LayoutModuleList::const_iterator lit = layoutModules_.begin();
1502                 LayoutModuleList::const_iterator len = layoutModules_.end();
1503                 for (; lit != len; lit++) {
1504                         LyXModule * lm = moduleList[*lit];
1505                         if (!lm)
1506                                 continue;
1507                         vector<string> const & exc = lm->getExcludedModules();
1508                         // ...and see if this one excludes us.
1509                         if (find(exc.begin(), exc.end(), modName) != exc.end()) {
1510                                 foundit = true;
1511                                 LYXERR(Debug::TCLASS, "Default module `" << modName << 
1512                                                 "' not added because excluded by loaded module `" << 
1513                                                 *lit << "'.");
1514                                 break;
1515                         }
1516                 }
1517                 if (!foundit) {
1518                         LYXERR(Debug::TCLASS, "Default module `" << modName << "' added.");
1519                         layoutModules_.push_back(modName);
1520                 }
1521         }
1522         return true;
1523 }
1524
1525
1526 LayoutFile const * BufferParams::baseClass() const
1527 {
1528         if (LayoutFileList::get().haveClass(pimpl_->baseClass_))
1529                 return &(LayoutFileList::get()[pimpl_->baseClass_]);
1530         else 
1531                 return 0;
1532 }
1533
1534
1535 LayoutFileIndex const & BufferParams::baseClassID() const
1536 {
1537         return pimpl_->baseClass_;
1538 }
1539
1540
1541 void BufferParams::makeDocumentClass()
1542 {
1543         if (!baseClass())
1544                 return;
1545
1546         doc_class_ = &(DocumentClassBundle::get().newClass(*baseClass()));
1547
1548         // FIXME It might be worth loading the children's modules here,
1549         // just as we load their bibliographies and such, instead of just 
1550         // doing a check in InsetInclude.
1551         LayoutModuleList::const_iterator it = layoutModules_.begin();
1552         for (; it != layoutModules_.end(); it++) {
1553                 string const modName = *it;
1554                 LyXModule * lm = moduleList[modName];
1555                 if (!lm) {
1556                         docstring const msg =
1557                                 bformat(_("The module %1$s has been requested by\n"
1558                                         "this document but has not been found in the list of\n"
1559                                         "available modules. If you recently installed it, you\n"
1560                                         "probably need to reconfigure LyX.\n"), from_utf8(modName));
1561                         frontend::Alert::warning(_("Module not available"),
1562                                         msg + _("Some layouts may not be available."));
1563                         LYXERR0("BufferParams::makeDocumentClass(): Module " <<
1564                                         modName << " requested but not found in module list.");
1565                         continue;
1566                 }
1567                 if (!lm->isAvailable()) {
1568                         docstring const msg =
1569                                                 bformat(_("The module %1$s requires a package that is\n"
1570                                                 "not available in your LaTeX installation. LaTeX output\n"
1571                                                 "may not be possible.\n"), from_utf8(modName));
1572                         frontend::Alert::warning(_("Package not available"), msg);
1573                 }
1574                 FileName layout_file = libFileSearch("layouts", lm->getFilename());
1575                 if (!doc_class_->read(layout_file, TextClass::MODULE)) {
1576                         docstring const msg =
1577                                 bformat(_("Error reading module %1$s\n"), from_utf8(modName));
1578                         frontend::Alert::warning(_("Read Error"), msg);
1579                 }
1580         }
1581         if (!local_layout.empty()) {
1582                 if (!doc_class_->read(local_layout, TextClass::MODULE)) {
1583                         docstring const msg = _("Error reading internal layout information");
1584                         frontend::Alert::warning(_("Read Error"), msg);
1585                 }
1586         }
1587 }
1588
1589
1590 bool BufferParams::addLayoutModule(string const & modName) 
1591 {
1592         LayoutModuleList::const_iterator it = layoutModules_.begin();
1593         LayoutModuleList::const_iterator end = layoutModules_.end();
1594         for (; it != end; it++)
1595                 if (*it == modName) 
1596                         return false;
1597         layoutModules_.push_back(modName);
1598         return true;
1599 }
1600
1601
1602 Font const BufferParams::getFont() const
1603 {
1604         FontInfo f = documentClass().defaultfont();
1605         if (fontsDefaultFamily == "rmdefault")
1606                 f.setFamily(ROMAN_FAMILY);
1607         else if (fontsDefaultFamily == "sfdefault")
1608                 f.setFamily(SANS_FAMILY);
1609         else if (fontsDefaultFamily == "ttdefault")
1610                 f.setFamily(TYPEWRITER_FAMILY);
1611         return Font(f, language);
1612 }
1613
1614
1615 void BufferParams::readPreamble(Lexer & lex)
1616 {
1617         if (lex.getString() != "\\begin_preamble")
1618                 lyxerr << "Error (BufferParams::readPreamble):"
1619                         "consistency check failed." << endl;
1620
1621         preamble = lex.getLongString("\\end_preamble");
1622 }
1623
1624
1625 void BufferParams::readLocalLayout(Lexer & lex)
1626 {
1627         if (lex.getString() != "\\begin_local_layout")
1628                 lyxerr << "Error (BufferParams::readLocalLayout):"
1629                         "consistency check failed." << endl;
1630
1631         local_layout = lex.getLongString("\\end_local_layout");
1632 }
1633
1634
1635 void BufferParams::readLanguage(Lexer & lex)
1636 {
1637         if (!lex.next()) return;
1638
1639         string const tmptok = lex.getString();
1640
1641         // check if tmptok is part of tex_babel in tex-defs.h
1642         language = languages.getLanguage(tmptok);
1643         if (!language) {
1644                 // Language tmptok was not found
1645                 language = default_language;
1646                 lyxerr << "Warning: Setting language `"
1647                        << tmptok << "' to `" << language->lang()
1648                        << "'." << endl;
1649         }
1650 }
1651
1652
1653 void BufferParams::readGraphicsDriver(Lexer & lex)
1654 {
1655         if (!lex.next()) 
1656                 return;
1657
1658         string const tmptok = lex.getString();
1659         // check if tmptok is part of tex_graphics in tex_defs.h
1660         int n = 0;
1661         while (true) {
1662                 string const test = tex_graphics[n++];
1663
1664                 if (test == tmptok) {
1665                         graphicsDriver = tmptok;
1666                         break;
1667                 }
1668                 if (test.empty()) {
1669                         lex.printError(
1670                                 "Warning: graphics driver `$$Token' not recognized!\n"
1671                                 "         Setting graphics driver to `default'.\n");
1672                         graphicsDriver = "default";
1673                         break;
1674                 }
1675         }
1676 }
1677
1678
1679 void BufferParams::readBullets(Lexer & lex)
1680 {
1681         if (!lex.next()) 
1682                 return;
1683
1684         int const index = lex.getInteger();
1685         lex.next();
1686         int temp_int = lex.getInteger();
1687         user_defined_bullet(index).setFont(temp_int);
1688         temp_bullet(index).setFont(temp_int);
1689         lex >> temp_int;
1690         user_defined_bullet(index).setCharacter(temp_int);
1691         temp_bullet(index).setCharacter(temp_int);
1692         lex >> temp_int;
1693         user_defined_bullet(index).setSize(temp_int);
1694         temp_bullet(index).setSize(temp_int);
1695 }
1696
1697
1698 void BufferParams::readBulletsLaTeX(Lexer & lex)
1699 {
1700         // The bullet class should be able to read this.
1701         if (!lex.next()) 
1702                 return;
1703         int const index = lex.getInteger();
1704         lex.next(true);
1705         docstring const temp_str = lex.getDocString();
1706
1707         user_defined_bullet(index).setText(temp_str);
1708         temp_bullet(index).setText(temp_str);
1709 }
1710
1711
1712 void BufferParams::readModules(Lexer & lex)
1713 {
1714         if (!lex.eatLine()) {
1715                 lyxerr << "Error (BufferParams::readModules):"
1716                                 "Unexpected end of input." << endl;
1717                 return;
1718         }
1719         while (true) {
1720                 string mod = lex.getString();
1721                 if (mod == "\\end_modules")
1722                         break;
1723                 addLayoutModule(mod);
1724                 lex.eatLine();
1725         }
1726 }
1727
1728
1729 void BufferParams::readRemovedModules(Lexer & lex)
1730 {
1731         if (!lex.eatLine()) {
1732                 lyxerr << "Error (BufferParams::readRemovedModules):"
1733                                 "Unexpected end of input." << endl;
1734                 return;
1735         }
1736         while (true) {
1737                 string mod = lex.getString();
1738                 if (mod == "\\end_removed_modules")
1739                         break;
1740                 removedModules_.insert(mod);
1741                 lex.eatLine();
1742         }
1743         // now we want to remove any removed modules that were previously 
1744         // added. normally, that will be because default modules were added in 
1745         // setBaseClass(), which gets called when \textclass is read at the 
1746         // start of the read.
1747         set<string>::const_iterator rit = removedModules_.begin();
1748         set<string>::const_iterator const ren = removedModules_.end();
1749         for (; rit != ren; rit++) {
1750                 LayoutModuleList::iterator const mit = layoutModules_.begin();
1751                 LayoutModuleList::iterator const men = layoutModules_.end();
1752                 LayoutModuleList::iterator found = find(mit, men, *rit);
1753                 if (found == men)
1754                         continue;
1755                 layoutModules_.erase(found);
1756         }
1757 }
1758
1759
1760 string BufferParams::paperSizeName(PapersizePurpose purpose) const
1761 {
1762         char real_papersize = papersize;
1763         if (real_papersize == PAPER_DEFAULT)
1764                 real_papersize = lyxrc.default_papersize;
1765
1766         switch (real_papersize) {
1767         case PAPER_DEFAULT:
1768                 // could be anything, so don't guess
1769                 return string();
1770         case PAPER_CUSTOM: {
1771                 if (purpose == XDVI && !paperwidth.empty() &&
1772                     !paperheight.empty()) {
1773                         // heightxwidth<unit>
1774                         string first = paperwidth;
1775                         string second = paperheight;
1776                         if (orientation == ORIENTATION_LANDSCAPE)
1777                                 first.swap(second);
1778                         // cut off unit.
1779                         return first.erase(first.length() - 2)
1780                                 + "x" + second;
1781                 }
1782                 return string();
1783         }
1784         case PAPER_A3:
1785                 return "a3";
1786         case PAPER_A4:
1787                 return "a4";
1788         case PAPER_A5:
1789                 return "a5";
1790         case PAPER_B3:
1791                 // dvips and dvipdfm do not know this
1792                 if (purpose == DVIPS || purpose == DVIPDFM)
1793                         return string();
1794                 return "b3";
1795         case PAPER_B4:
1796                 // dvipdfm does not know this
1797                 if (purpose == DVIPDFM)
1798                         return string();
1799                 return "b4";
1800         case PAPER_B5:
1801                 // dvipdfm does not know this
1802                 if (purpose == DVIPDFM)
1803                         return string();
1804                 return "b5";
1805         case PAPER_USEXECUTIVE:
1806                 // dvipdfm does not know this
1807                 if (purpose == DVIPDFM)
1808                         return string();
1809                 return "foolscap";
1810         case PAPER_USLEGAL:
1811                 return "legal";
1812         case PAPER_USLETTER:
1813         default:
1814                 if (purpose == XDVI)
1815                         return "us";
1816                 return "letter";
1817         }
1818 }
1819
1820
1821 string const BufferParams::dvips_options() const
1822 {
1823         string result;
1824
1825         if (use_geometry
1826             && papersize == PAPER_CUSTOM
1827             && !lyxrc.print_paper_dimension_flag.empty()
1828             && !paperwidth.empty()
1829             && !paperheight.empty()) {
1830                 // using a custom papersize
1831                 result = lyxrc.print_paper_dimension_flag;
1832                 result += ' ' + paperwidth;
1833                 result += ',' + paperheight;
1834         } else {
1835                 string const paper_option = paperSizeName(DVIPS);
1836                 if (!paper_option.empty() && (paper_option != "letter" ||
1837                     orientation != ORIENTATION_LANDSCAPE)) {
1838                         // dvips won't accept -t letter -t landscape.
1839                         // In all other cases, include the paper size
1840                         // explicitly.
1841                         result = lyxrc.print_paper_flag;
1842                         result += ' ' + paper_option;
1843                 }
1844         }
1845         if (orientation == ORIENTATION_LANDSCAPE &&
1846             papersize != PAPER_CUSTOM)
1847                 result += ' ' + lyxrc.print_landscape_flag;
1848         return result;
1849 }
1850
1851
1852 string BufferParams::babelCall(string const & lang_opts) const
1853 {
1854         string lang_pack = lyxrc.language_package;
1855         if (lang_pack != "\\usepackage{babel}")
1856                 return lang_pack;
1857         // suppress the babel call when there is no babel language defined
1858         // for the document language in the lib/languages file and if no
1859         // other languages are used (lang_opts is then empty)
1860         if (lang_opts.empty())
1861                 return string();
1862         // If Vietnamese is used, babel must directly be loaded with the
1863         // language options, see
1864         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129417.html
1865         size_t viet = lang_opts.find("vietnam");
1866         // viet = string::npos when not found
1867         // If Japanese is used, babel must directly be loaded with the
1868         // language options, see
1869         // http://bugzilla.lyx.org/show_bug.cgi?id=4597#c4
1870         size_t japan = lang_opts.find("japanese");
1871         // japan = string::npos when not found
1872         if (!lyxrc.language_global_options || viet != string::npos || japan != string::npos)
1873                 return "\\usepackage[" + lang_opts + "]{babel}";
1874         return lang_pack;
1875 }
1876
1877
1878 void BufferParams::writeEncodingPreamble(odocstream & os,
1879                 LaTeXFeatures & features, TexRow & texrow) const
1880 {
1881         if (inputenc == "auto") {
1882                 string const doc_encoding =
1883                         language->encoding()->latexName();
1884                 Encoding::Package const package =
1885                         language->encoding()->package();
1886
1887                 // Create a list with all the input encodings used
1888                 // in the document
1889                 set<string> encodings =
1890                         features.getEncodingSet(doc_encoding);
1891
1892                 // If the "japanese" package (i.e. pLaTeX) is used,
1893                 // inputenc must be omitted.
1894                 // see http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg129680.html
1895                 if (package == Encoding::japanese)
1896                      features.require("japanese");
1897
1898                 if ((!encodings.empty() || package == Encoding::inputenc)
1899                     && !features.isRequired("japanese")) {
1900                         os << "\\usepackage[";
1901                         set<string>::const_iterator it = encodings.begin();
1902                         set<string>::const_iterator const end = encodings.end();
1903                         if (it != end) {
1904                                 os << from_ascii(*it);
1905                                 ++it;
1906                         }
1907                         for (; it != end; ++it)
1908                                 os << ',' << from_ascii(*it);
1909                         if (package == Encoding::inputenc) {
1910                                 if (!encodings.empty())
1911                                         os << ',';
1912                                 os << from_ascii(doc_encoding);
1913                         }
1914                         os << "]{inputenc}\n";
1915                         texrow.newline();
1916                 }
1917                 if (package == Encoding::CJK || features.mustProvide("CJK")) {
1918                         os << "\\usepackage{CJK}\n";
1919                         texrow.newline();
1920                 }
1921         } else if (inputenc != "default") {
1922                 switch (encoding().package()) {
1923                 case Encoding::none:
1924                 case Encoding::japanese:
1925                         break;
1926                 case Encoding::inputenc:
1927                         // do not load inputenc if japanese is used
1928                         if (features.isRequired("japanese"))
1929                                 break;
1930                         os << "\\usepackage[" << from_ascii(inputenc)
1931                            << "]{inputenc}\n";
1932                         texrow.newline();
1933                         break;
1934                 case Encoding::CJK:
1935                         os << "\\usepackage{CJK}\n";
1936                         texrow.newline();
1937                         break;
1938                 }
1939         }
1940
1941         // The encoding "armscii8" (for Armenian) is only available when
1942         // the package "armtex" is loaded.
1943         if (language->encoding()->latexName() == "armscii8"
1944             || inputenc == "armscii8") {
1945                 os << "\\usepackage{armtex}\n";
1946                 texrow.newline();
1947         }
1948 }
1949
1950
1951 string const BufferParams::loadFonts(string const & rm,
1952                                      string const & sf, string const & tt,
1953                                      bool const & sc, bool const & osf,
1954                                      int const & sfscale, int const & ttscale) const
1955 {
1956         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1957            several packages have been replaced by others, that might not
1958            be installed on every system. We have to take care for that
1959            (see psnfss.pdf). We try to support all psnfss fonts as well
1960            as the fonts that have become de facto standard in the LaTeX
1961            world (e.g. Latin Modern). We do not support obsolete fonts
1962            (like PSLatex). In general, it should be possible to mix any
1963            rm font with any sf or tt font, respectively. (JSpitzm)
1964            TODO:
1965                 -- separate math fonts.
1966         */
1967
1968         if (rm == "default" && sf == "default" && tt == "default")
1969                 //nothing to do
1970                 return string();
1971
1972         ostringstream os;
1973
1974         // ROMAN FONTS
1975         // Computer Modern (must be explicitely selectable -- there might be classes
1976         // that define a different default font!
1977         if (rm == "cmr") {
1978                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1979                 // osf for Computer Modern needs eco.sty
1980                 if (osf)
1981                         os << "\\usepackage{eco}\n";
1982         }
1983         // Latin Modern Roman
1984         else if (rm == "lmodern")
1985                 os << "\\usepackage{lmodern}\n";
1986         // AE
1987         else if (rm == "ae") {
1988                 // not needed when using OT1 font encoding.
1989                 if (lyxrc.fontenc != "default")
1990                         os << "\\usepackage{ae,aecompl}\n";
1991         }
1992         // Times
1993         else if (rm == "times") {
1994                 // try to load the best available package
1995                 if (LaTeXFeatures::isAvailable("mathptmx"))
1996                         os << "\\usepackage{mathptmx}\n";
1997                 else if (LaTeXFeatures::isAvailable("mathptm"))
1998                         os << "\\usepackage{mathptm}\n";
1999                 else
2000                         os << "\\usepackage{times}\n";
2001         }
2002         // Palatino
2003         else if (rm == "palatino") {
2004                 // try to load the best available package
2005                 if (LaTeXFeatures::isAvailable("mathpazo")) {
2006                         os << "\\usepackage";
2007                         if (osf || sc) {
2008                                 os << '[';
2009                                 if (!osf)
2010                                         os << "sc";
2011                                 else
2012                                         // "osf" includes "sc"!
2013                                         os << "osf";
2014                                 os << ']';
2015                         }
2016                         os << "{mathpazo}\n";
2017                 }
2018                 else if (LaTeXFeatures::isAvailable("mathpple"))
2019                         os << "\\usepackage{mathpple}\n";
2020                 else
2021                         os << "\\usepackage{palatino}\n";
2022         }
2023         // Utopia
2024         else if (rm == "utopia") {
2025                 // fourier supersedes utopia.sty, but does
2026                 // not work with OT1 encoding.
2027                 if (LaTeXFeatures::isAvailable("fourier")
2028                     && lyxrc.fontenc != "default") {
2029                         os << "\\usepackage";
2030                         if (osf || sc) {
2031                                 os << '[';
2032                                 if (sc)
2033                                         os << "expert";
2034                                 if (osf && sc)
2035                                         os << ',';
2036                                 if (osf)
2037                                         os << "oldstyle";
2038                                 os << ']';
2039                         }
2040                         os << "{fourier}\n";
2041                 }
2042                 else
2043                         os << "\\usepackage{utopia}\n";
2044         }
2045         // Bera (complete fontset)
2046         else if (rm == "bera" && sf == "default" && tt == "default")
2047                 os << "\\usepackage{bera}\n";
2048         // everything else
2049         else if (rm != "default")
2050                 os << "\\usepackage" << "{" << rm << "}\n";
2051
2052         // SANS SERIF
2053         // Helvetica, Bera Sans
2054         if (sf == "helvet" || sf == "berasans") {
2055                 if (sfscale != 100)
2056                         os << "\\usepackage[scaled=" << float(sfscale) / 100
2057                            << "]{" << sf << "}\n";
2058                 else
2059                         os << "\\usepackage{" << sf << "}\n";
2060         }
2061         // Avant Garde
2062         else if (sf == "avant")
2063                 os << "\\usepackage{" << sf << "}\n";
2064         // Computer Modern, Latin Modern, CM Bright
2065         else if (sf != "default")
2066                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
2067
2068         // monospaced/typewriter
2069         // Courier, LuxiMono
2070         if (tt == "luximono" || tt == "beramono") {
2071                 if (ttscale != 100)
2072                         os << "\\usepackage[scaled=" << float(ttscale) / 100
2073                            << "]{" << tt << "}\n";
2074                 else
2075                         os << "\\usepackage{" << tt << "}\n";
2076         }
2077         // Courier
2078         else if (tt == "courier" )
2079                 os << "\\usepackage{" << tt << "}\n";
2080         // Computer Modern, Latin Modern, CM Bright
2081         else if (tt != "default")
2082                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
2083
2084         return os.str();
2085 }
2086
2087
2088 Encoding const & BufferParams::encoding() const
2089 {
2090         if (inputenc == "auto" || inputenc == "default")
2091                 return *language->encoding();
2092         Encoding const * const enc = encodings.fromLaTeXName(inputenc);
2093         if (enc)
2094                 return *enc;
2095         LYXERR0("Unknown inputenc value `" << inputenc
2096                << "'. Using `auto' instead.");
2097         return *language->encoding();
2098 }
2099
2100
2101 CiteEngine BufferParams::citeEngine() const
2102 {
2103         // FIXME the class should provide the numerical/
2104         // authoryear choice
2105         if (documentClass().provides("natbib")
2106             && cite_engine_ != ENGINE_NATBIB_NUMERICAL)
2107                 return ENGINE_NATBIB_AUTHORYEAR;
2108         return cite_engine_;
2109 }
2110
2111
2112 void BufferParams::setCiteEngine(CiteEngine cite_engine)
2113 {
2114         cite_engine_ = cite_engine;
2115 }
2116
2117 } // namespace lyx