]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
* do not ignore "requires" field in MathMacro
[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 "BranchList.h"
22 #include "Bullet.h"
23 #include "debug.h"
24 #include "Encoding.h"
25 #include "gettext.h"
26 #include "Language.h"
27 #include "LaTeXFeatures.h"
28 #include "Messages.h"
29 #include "Color.h"
30 #include "Font.h"
31 #include "Lexer.h"
32 #include "LyXRC.h"
33 #include "TextClassList.h"
34 #include "OutputParams.h"
35 #include "Spacing.h"
36 #include "TexRow.h"
37 #include "VSpace.h"
38
39 #include "frontends/alert.h"
40
41 #include "support/lyxalgo.h" // for lyx::count
42 #include "support/convert.h"
43 #include "support/Translator.h"
44
45 #include <boost/array.hpp>
46
47 #include <sstream>
48
49 using std::endl;
50 using std::string;
51 using std::istringstream;
52 using std::ostream;
53 using std::ostringstream;
54 using std::pair;
55
56 using lyx::support::bformat;
57 using lyx::support::rtrim;
58 using lyx::support::tokenPos;
59
60
61 static char const * const string_paragraph_separation[] = {
62         "indent", "skip", ""
63 };
64
65
66 static char const * const string_quotes_language[] = {
67         "english", "swedish", "german", "polish", "french", "danish", ""
68 };
69
70
71 static char const * const string_papersize[] = {
72         "default", "custom", "letterpaper", "executivepaper", "legalpaper",
73         "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
74 };
75
76
77 static char const * const string_orientation[] = {
78         "portrait", "landscape", ""
79 };
80
81
82 static char const * const string_footnotekinds[] = {
83         "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
84 };
85
86
87 static char const * const tex_graphics[] = {
88         "default", "dvips", "dvitops", "emtex",
89         "ln", "oztex", "textures", "none", ""
90 };
91
92
93 namespace lyx {
94
95 // Local translators
96 namespace {
97
98 // Paragraph separation
99 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
100
101
102 ParSepTranslator const init_parseptranslator()
103 {
104         ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
105         translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
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::quote_language> QuotesLangTranslator;
119
120
121 QuotesLangTranslator const init_quoteslangtranslator()
122 {
123         QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
124         translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
125         translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
126         translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
127         translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
128         translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
129         return translator;
130 }
131
132
133 QuotesLangTranslator const & quoteslangtranslator()
134 {
135         static QuotesLangTranslator translator = init_quoteslangtranslator();
136         return translator;
137 }
138
139
140 // Paper size
141 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
142
143
144 PaperSizeTranslator const init_papersizetranslator()
145 {
146         PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
147         translator.addPair(string_papersize[1], PAPER_CUSTOM);
148         translator.addPair(string_papersize[2], PAPER_USLETTER);
149         translator.addPair(string_papersize[3], PAPER_USLEGAL);
150         translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
151         translator.addPair(string_papersize[5], PAPER_A3);
152         translator.addPair(string_papersize[6], PAPER_A4);
153         translator.addPair(string_papersize[7], PAPER_A5);
154         translator.addPair(string_papersize[8], PAPER_B3);
155         translator.addPair(string_papersize[9], PAPER_B4);
156         translator.addPair(string_papersize[10], PAPER_B5);
157         return translator;
158 }
159
160
161 PaperSizeTranslator const & papersizetranslator()
162 {
163         static PaperSizeTranslator translator = init_papersizetranslator();
164         return translator;
165 }
166
167
168 // Paper orientation
169 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
170
171
172 PaperOrientationTranslator const init_paperorientationtranslator()
173 {
174         PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
175         translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
176         return translator;
177 }
178
179
180 PaperOrientationTranslator const & paperorientationtranslator()
181 {
182         static PaperOrientationTranslator translator = init_paperorientationtranslator();
183         return translator;
184 }
185
186
187 // Page sides
188 typedef Translator<int, TextClass::PageSides> SidesTranslator;
189
190
191 SidesTranslator const init_sidestranslator()
192 {
193         SidesTranslator translator(1, TextClass::OneSide);
194         translator.addPair(2, TextClass::TwoSides);
195         return translator;
196 }
197
198
199 SidesTranslator const & sidestranslator()
200 {
201         static SidesTranslator translator = init_sidestranslator();
202         return translator;
203 }
204
205
206 // LaTeX packages
207 typedef Translator<int, BufferParams::Package> PackageTranslator;
208
209
210 PackageTranslator const init_packagetranslator()
211 {
212         PackageTranslator translator(0, BufferParams::package_off);
213         translator.addPair(1, BufferParams::package_auto);
214         translator.addPair(2, BufferParams::package_on);
215         return translator;
216 }
217
218
219 PackageTranslator const & packagetranslator()
220 {
221         static PackageTranslator translator = init_packagetranslator();
222         return translator;
223 }
224
225
226 // Cite engine
227 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
228
229
230 CiteEngineTranslator const init_citeenginetranslator()
231 {
232         CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
233         translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
234         translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
235         translator.addPair("jurabib", biblio::ENGINE_JURABIB);
236         return translator;
237 }
238
239
240 CiteEngineTranslator const & citeenginetranslator()
241 {
242         static CiteEngineTranslator translator = init_citeenginetranslator();
243         return translator;
244 }
245
246
247 // Spacing
248 typedef Translator<string, Spacing::Space> SpaceTranslator;
249
250
251 SpaceTranslator const init_spacetranslator()
252 {
253         SpaceTranslator translator("default", Spacing::Default);
254         translator.addPair("single", Spacing::Single);
255         translator.addPair("onehalf", Spacing::Onehalf);
256         translator.addPair("double", Spacing::Double);
257         translator.addPair("other", Spacing::Other);
258         return translator;
259 }
260
261
262 SpaceTranslator const & spacetranslator()
263 {
264         static SpaceTranslator translator = init_spacetranslator();
265         return translator;
266 }
267
268
269 textclass_type defaultTextclass()
270 {
271         // Initialize textclass to point to article. if `first' is
272         // true in the returned pair, then `second' is the textclass
273         // number; if it is false, second is 0. In both cases, second
274         // is what we want.
275         return textclasslist.numberOfClass("article").second;
276 }
277
278 } // anon namespace
279
280
281 class BufferParams::Impl
282 {
283 public:
284         Impl();
285
286         AuthorList authorlist;
287         BranchList branchlist;
288         boost::array<Bullet, 4> temp_bullets;
289         boost::array<Bullet, 4> user_defined_bullets;
290         Spacing spacing;
291         /** This is the amount of space used for paragraph_separation "skip",
292          * and for detached paragraphs in "indented" documents.
293          */
294         VSpace defskip;
295 };
296
297
298 BufferParams::Impl::Impl()
299         : defskip(VSpace::MEDSKIP)
300 {
301         // set initial author
302         // FIXME UNICODE
303         authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
304 }
305
306
307 BufferParams::Impl *
308 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
309 {
310         BOOST_ASSERT(ptr);
311
312         return new BufferParams::Impl(*ptr);
313 }
314
315
316 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
317 {
318         delete ptr;
319 }
320
321
322 BufferParams::BufferParams()
323         : textclass(defaultTextclass()), pimpl_(new Impl)
324 {
325         paragraph_separation = PARSEP_INDENT;
326         quotes_language = InsetQuotes::EnglishQ;
327         fontsize = "default";
328
329         /*  PaperLayout */
330         papersize = PAPER_DEFAULT;
331         orientation = ORIENTATION_PORTRAIT;
332         use_geometry = false;
333         use_amsmath = package_auto;
334         use_esint = package_auto;
335         cite_engine_ = biblio::ENGINE_BASIC;
336         use_bibtopic = false;
337         trackChanges = false;
338         outputChanges = false;
339         secnumdepth = 3;
340         tocdepth = 3;
341         language = default_language;
342         fontsRoman = "default";
343         fontsSans = "default";
344         fontsTypewriter = "default";
345         fontsDefaultFamily = "default";
346         fontsSC = false;
347         fontsOSF = false;
348         fontsSansScale = 100;
349         fontsTypewriterScale = 100;
350         inputenc = "auto";
351         graphicsDriver = "default";
352         sides = TextClass::OneSide;
353         columns = 1;
354         pagestyle = "default";
355         compressed = false;
356         for (int iter = 0; iter < 4; ++iter) {
357                 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
358                 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
359         }
360 }
361
362
363 BufferParams::~BufferParams()
364 {}
365
366
367 docstring const BufferParams::B_(string const & l10n) const
368 {
369         BOOST_ASSERT(language);
370         return getMessages(language->code()).get(l10n);
371 }
372
373
374 AuthorList & BufferParams::authors()
375 {
376         return pimpl_->authorlist;
377 }
378
379
380 AuthorList const & BufferParams::authors() const
381 {
382         return pimpl_->authorlist;
383 }
384
385
386 BranchList & BufferParams::branchlist()
387 {
388         return pimpl_->branchlist;
389 }
390
391
392 BranchList const & BufferParams::branchlist() const
393 {
394         return pimpl_->branchlist;
395 }
396
397
398 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
399 {
400         BOOST_ASSERT(index < 4);
401         return pimpl_->temp_bullets[index];
402 }
403
404
405 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
406 {
407         BOOST_ASSERT(index < 4);
408         return pimpl_->temp_bullets[index];
409 }
410
411
412 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
413 {
414         BOOST_ASSERT(index < 4);
415         return pimpl_->user_defined_bullets[index];
416 }
417
418
419 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
420 {
421         BOOST_ASSERT(index < 4);
422         return pimpl_->user_defined_bullets[index];
423 }
424
425
426 Spacing & BufferParams::spacing()
427 {
428         return pimpl_->spacing;
429 }
430
431
432 Spacing const & BufferParams::spacing() const
433 {
434         return pimpl_->spacing;
435 }
436
437
438 VSpace const & BufferParams::getDefSkip() const
439 {
440         return pimpl_->defskip;
441 }
442
443
444 void BufferParams::setDefSkip(VSpace const & vs)
445 {
446         pimpl_->defskip = vs;
447 }
448
449
450 string const BufferParams::readToken(Lexer & lex, string const & token)
451 {
452         if (token == "\\textclass") {
453                 lex.next();
454                 string const classname = lex.getString();
455                 pair<bool, lyx::textclass_type> pp =
456                         textclasslist.numberOfClass(classname);
457                 if (pp.first) {
458                         textclass = pp.second;
459                 } else {
460                         // if text class does not exist, try to load it from filepath
461                         pp = textclasslist.addTextClass(classname, filepath);
462                         if (pp.first) {
463                                 textclass = pp.second;
464                         } else {
465                                 textclass = defaultTextclass();
466                                 return classname;
467                         }
468                 }
469                 // FIXME: isTeXClassAvailable will try to load the layout file, but will
470                 // fail because of the lack of path info. Warnings will be given although
471                 // the layout file will be correctly loaded later.
472                 if (!getTextClass().isTeXClassAvailable()) {
473                         docstring const msg =
474                                 bformat(_("The layout file requested by this document,\n"
475                                                  "%1$s.layout,\n"
476                                                  "is not usable. This is probably because a LaTeX\n"
477                                                  "class or style file required by it is not\n"
478                                                  "available. See the Customization documentation\n"
479                                                  "for more information.\n"), from_utf8(classname));
480                         frontend::Alert::warning(_("Document class not available"),
481                                        msg + _("LyX will not be able to produce output."));
482                 }
483         } else if (token == "\\begin_preamble") {
484                 readPreamble(lex);
485         } else if (token == "\\options") {
486                 lex.eatLine();
487                 options = lex.getString();
488         } else if (token == "\\language") {
489                 readLanguage(lex);
490         } else if (token == "\\inputencoding") {
491                 lex >> inputenc;
492         } else if (token == "\\graphics") {
493                 readGraphicsDriver(lex);
494         } else if (token == "\\font_roman") {
495                 lex >> fontsRoman;
496         } else if (token == "\\font_sans") {
497                 lex >> fontsSans;
498         } else if (token == "\\font_typewriter") {
499                 lex >> fontsTypewriter;
500         } else if (token == "\\font_default_family") {
501                 lex >> fontsDefaultFamily;
502         } else if (token == "\\font_sc") {
503                 lex >> fontsSC;
504         } else if (token == "\\font_osf") {
505                 lex >> fontsOSF;
506         } else if (token == "\\font_sf_scale") {
507                 lex >> fontsSansScale;
508         } else if (token == "\\font_tt_scale") {
509                 lex >> fontsTypewriterScale;
510         } else if (token == "\\paragraph_separation") {
511                 string parsep;
512                 lex >> parsep;
513                 paragraph_separation = parseptranslator().find(parsep);
514         } else if (token == "\\defskip") {
515                 lex.next();
516                 pimpl_->defskip = VSpace(lex.getString());
517         } else if (token == "\\quotes_language") {
518                 string quotes_lang;
519                 lex >> quotes_lang;
520                 quotes_language = quoteslangtranslator().find(quotes_lang);
521         } else if (token == "\\papersize") {
522                 string ppsize;
523                 lex >> ppsize;
524                 papersize = papersizetranslator().find(ppsize);
525         } else if (token == "\\use_geometry") {
526                 lex >> use_geometry;
527         } else if (token == "\\use_amsmath") {
528                 int use_ams;
529                 lex >> use_ams;
530                 use_amsmath = packagetranslator().find(use_ams);
531         } else if (token == "\\use_esint") {
532                 int useesint;
533                 lex >> useesint;
534                 use_esint = packagetranslator().find(useesint);
535         } else if (token == "\\cite_engine") {
536                 string engine;
537                 lex >> engine;
538                 cite_engine_ = citeenginetranslator().find(engine);
539         } else if (token == "\\use_bibtopic") {
540                 lex >> use_bibtopic;
541         } else if (token == "\\tracking_changes") {
542                 lex >> trackChanges;
543         } else if (token == "\\output_changes") {
544                 lex >> outputChanges;
545         } else if (token == "\\branch") {
546                 lex.next();
547                 docstring branch = lex.getDocString();
548                 branchlist().add(branch);
549                 while (true) {
550                         lex.next();
551                         string const tok = lex.getString();
552                         if (tok == "\\end_branch")
553                                 break;
554                         Branch * branch_ptr = branchlist().find(branch);
555                         if (tok == "\\selected") {
556                                 lex.next();
557                                 if (branch_ptr)
558                                         branch_ptr->setSelected(lex.getInteger());
559                         }
560                         // not yet operational
561                         if (tok == "\\color") {
562                                 lex.eatLine();
563                                 string color = lex.getString();
564                                 if (branch_ptr)
565                                         branch_ptr->setColor(color);
566                                 // Update also the Color table:
567                                 if (color == "none")
568                                         color = lcolor.getX11Name(Color::background);
569                                 // FIXME UNICODE
570                                 lcolor.setColor(to_utf8(branch), color);
571
572                         }
573                 }
574         } else if (token == "\\author") {
575                 lex.eatLine();
576                 istringstream ss(lex.getString());
577                 Author a;
578                 ss >> a;
579                 author_map.push_back(pimpl_->authorlist.record(a));
580         } else if (token == "\\paperorientation") {
581                 string orient;
582                 lex >> orient;
583                 orientation = paperorientationtranslator().find(orient);
584         } else if (token == "\\paperwidth") {
585                 lex >> paperwidth;
586         } else if (token == "\\paperheight") {
587                 lex >> paperheight;
588         } else if (token == "\\leftmargin") {
589                 lex >> leftmargin;
590         } else if (token == "\\topmargin") {
591                 lex >> topmargin;
592         } else if (token == "\\rightmargin") {
593                 lex >> rightmargin;
594         } else if (token == "\\bottommargin") {
595                 lex >> bottommargin;
596         } else if (token == "\\headheight") {
597                 lex >> headheight;
598         } else if (token == "\\headsep") {
599                 lex >> headsep;
600         } else if (token == "\\footskip") {
601                 lex >> footskip;
602         } else if (token == "\\paperfontsize") {
603                 lex >> fontsize;
604         } else if (token == "\\papercolumns") {
605                 lex >> columns;
606         } else if (token == "\\papersides") {
607                 int psides;
608                 lex >> psides;
609                 sides = sidestranslator().find(psides);
610         } else if (token == "\\paperpagestyle") {
611                 lex >> pagestyle;
612         } else if (token == "\\bullet") {
613                 readBullets(lex);
614         } else if (token == "\\bulletLaTeX") {
615                 readBulletsLaTeX(lex);
616         } else if (token == "\\secnumdepth") {
617                 lex >> secnumdepth;
618         } else if (token == "\\tocdepth") {
619                 lex >> tocdepth;
620         } else if (token == "\\spacing") {
621                 string nspacing;
622                 lex >> nspacing;
623                 string tmp_val;
624                 if (nspacing == "other") {
625                         lex >> tmp_val;
626                 }
627                 spacing().set(spacetranslator().find(nspacing), tmp_val);
628         } else if (token == "\\float_placement") {
629                 lex >> float_placement;
630         } else {
631                 return token;
632         }
633
634         return string();
635 }
636
637
638 void BufferParams::writeFile(ostream & os) const
639 {
640         // The top of the file is written by the buffer.
641         // Prints out the buffer info into the .lyx file given by file
642
643         // the textclass
644         os << "\\textclass " << textclasslist[textclass].name() << '\n';
645
646         // then the preamble
647         if (!preamble.empty()) {
648                 // remove '\n' from the end of preamble
649                 string const tmppreamble = rtrim(preamble, "\n");
650                 os << "\\begin_preamble\n"
651                    << tmppreamble
652                    << "\n\\end_preamble\n";
653         }
654
655         // the options
656         if (!options.empty()) {
657                 os << "\\options " << options << '\n';
658         }
659
660         // then the text parameters
661         if (language != ignore_language)
662                 os << "\\language " << language->lang() << '\n';
663         os << "\\inputencoding " << inputenc
664            << "\n\\font_roman " << fontsRoman
665            << "\n\\font_sans " << fontsSans
666            << "\n\\font_typewriter " << fontsTypewriter
667            << "\n\\font_default_family " << fontsDefaultFamily
668            << "\n\\font_sc " << convert<string>(fontsSC)
669            << "\n\\font_osf " << convert<string>(fontsOSF)
670            << "\n\\font_sf_scale " << fontsSansScale
671            << "\n\\font_tt_scale " << fontsTypewriterScale
672            << "\n\\graphics " << graphicsDriver << '\n';
673
674         if (!float_placement.empty()) {
675                 os << "\\float_placement " << float_placement << '\n';
676         }
677         os << "\\paperfontsize " << fontsize << '\n';
678
679         spacing().writeFile(os);
680
681         os << "\\papersize " << string_papersize[papersize]
682            << "\n\\use_geometry " << convert<string>(use_geometry)
683            << "\n\\use_amsmath " << use_amsmath
684            << "\n\\use_esint " << use_esint
685            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
686            << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
687            << "\n\\paperorientation " << string_orientation[orientation]
688            << '\n';
689
690         BranchList::const_iterator it = branchlist().begin();
691         BranchList::const_iterator end = branchlist().end();
692         for (; it != end; ++it) {
693                 os << "\\branch " << to_utf8(it->getBranch())
694                    << "\n\\selected " << it->getSelected()
695                    << "\n\\color " << lyx::X11hexname(it->getColor())
696                    << "\n\\end_branch"
697                    << "\n";
698         }
699
700         if (!paperwidth.empty())
701                 os << "\\paperwidth "
702                    << VSpace(paperwidth).asLyXCommand() << '\n';
703         if (!paperheight.empty())
704                 os << "\\paperheight "
705                    << VSpace(paperheight).asLyXCommand() << '\n';
706         if (!leftmargin.empty())
707                 os << "\\leftmargin "
708                    << VSpace(leftmargin).asLyXCommand() << '\n';
709         if (!topmargin.empty())
710                 os << "\\topmargin "
711                    << VSpace(topmargin).asLyXCommand() << '\n';
712         if (!rightmargin.empty())
713                 os << "\\rightmargin "
714                    << VSpace(rightmargin).asLyXCommand() << '\n';
715         if (!bottommargin.empty())
716                 os << "\\bottommargin "
717                    << VSpace(bottommargin).asLyXCommand() << '\n';
718         if (!headheight.empty())
719                 os << "\\headheight "
720                    << VSpace(headheight).asLyXCommand() << '\n';
721         if (!headsep.empty())
722                 os << "\\headsep "
723                    << VSpace(headsep).asLyXCommand() << '\n';
724         if (!footskip.empty())
725                 os << "\\footskip "
726                    << VSpace(footskip).asLyXCommand() << '\n';
727         os << "\\secnumdepth " << secnumdepth
728            << "\n\\tocdepth " << tocdepth
729            << "\n\\paragraph_separation "
730            << string_paragraph_separation[paragraph_separation]
731            << "\n\\defskip " << getDefSkip().asLyXCommand()
732            << "\n\\quotes_language "
733            << string_quotes_language[quotes_language]
734            << "\n\\papercolumns " << columns
735            << "\n\\papersides " << sides
736            << "\n\\paperpagestyle " << pagestyle << '\n';
737         for (int i = 0; i < 4; ++i) {
738                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
739                         if (user_defined_bullet(i).getFont() != -1) {
740                                 os << "\\bullet " << i << " "
741                                    << user_defined_bullet(i).getFont() << " "
742                                    << user_defined_bullet(i).getCharacter() << " "
743                                    << user_defined_bullet(i).getSize() << "\n";
744                         }
745                         else {
746                                 // FIXME UNICODE
747                                 os << "\\bulletLaTeX " << i << " \""
748                                    << lyx::to_ascii(user_defined_bullet(i).getText())
749                                    << "\"\n";
750                         }
751                 }
752         }
753
754         os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
755         os << "\\output_changes " << convert<string>(outputChanges) << "\n";
756
757         AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
758         AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
759         for (; a_it != a_end; ++a_it) {
760                 os << "\\author " << a_it->second << "\n";
761         }
762 }
763
764
765 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
766                               TexRow & texrow) const
767 {
768         os << "\\documentclass";
769
770         TextClass const & tclass = getTextClass();
771
772         ostringstream clsoptions; // the document class options.
773
774         if (tokenPos(tclass.opt_fontsize(),
775                      '|', fontsize) >= 0) {
776                 // only write if existing in list (and not default)
777                 clsoptions << fontsize << "pt,";
778         }
779
780         // custom, A3, B3 and B4 paper sizes need geometry
781         bool nonstandard_papersize = papersize == PAPER_B3 
782                 || papersize == PAPER_B4
783                 || papersize == PAPER_A3
784                 || papersize == PAPER_CUSTOM;
785
786         if (!use_geometry) {
787                 switch (papersize) {
788                 case PAPER_A4:
789                         clsoptions << "a4paper,";
790                         break;
791                 case PAPER_USLETTER:
792                         clsoptions << "letterpaper,";
793                         break;
794                 case PAPER_A5:
795                         clsoptions << "a5paper,";
796                         break;
797                 case PAPER_B5:
798                         clsoptions << "b5paper,";
799                         break;
800                 case PAPER_USEXECUTIVE:
801                         clsoptions << "executivepaper,";
802                         break;
803                 case PAPER_USLEGAL:
804                         clsoptions << "legalpaper,";
805                         break;
806                 case PAPER_DEFAULT:
807                 case PAPER_A3:
808                 case PAPER_B3:
809                 case PAPER_B4:
810                 case PAPER_CUSTOM:
811                         break;
812                 }
813         }
814
815         // if needed
816         if (sides != tclass.sides()) {
817                 switch (sides) {
818                 case TextClass::OneSide:
819                         clsoptions << "oneside,";
820                         break;
821                 case TextClass::TwoSides:
822                         clsoptions << "twoside,";
823                         break;
824                 }
825         }
826
827         // if needed
828         if (columns != tclass.columns()) {
829                 if (columns == 2)
830                         clsoptions << "twocolumn,";
831                 else
832                         clsoptions << "onecolumn,";
833         }
834
835         if (!use_geometry
836             && orientation == ORIENTATION_LANDSCAPE)
837                 clsoptions << "landscape,";
838
839         // language should be a parameter to \documentclass
840         if (language->babel() == "hebrew"
841             && default_language->babel() != "hebrew")
842                 // This seems necessary
843                 features.useLanguage(default_language);
844
845         ostringstream language_options;
846         bool const use_babel = features.useBabel();
847         if (use_babel) {
848                 language_options << features.getLanguages();
849                 language_options << language->babel();
850                 if (lyxrc.language_global_options)
851                         clsoptions << language_options.str() << ',';
852         }
853
854         // the user-defined options
855         if (!options.empty()) {
856                 clsoptions << options << ',';
857         }
858
859         string strOptions(clsoptions.str());
860         if (!strOptions.empty()) {
861                 strOptions = rtrim(strOptions, ",");
862                 // FIXME UNICODE
863                 os << '[' << from_utf8(strOptions) << ']';
864         }
865
866         os << '{' << from_ascii(tclass.latexname()) << "}\n";
867         texrow.newline();
868         // end of \documentclass defs
869
870         // font selection must be done before loading fontenc.sty
871         string const fonts =
872                 loadFonts(fontsRoman, fontsSans,
873                           fontsTypewriter, fontsSC, fontsOSF,
874                           fontsSansScale, fontsTypewriterScale);
875         if (!fonts.empty()) {
876                 os << from_ascii(fonts);
877                 texrow.newline();
878         }
879         if (fontsDefaultFamily != "default")
880                 os << "\\renewcommand{\\familydefault}{\\"
881                    << from_ascii(fontsDefaultFamily) << "}\n";
882         // this one is not per buffer
883         if (lyxrc.fontenc != "default") {
884                 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
885                    << "]{fontenc}\n";
886                 texrow.newline();
887         }
888
889         if (inputenc == "auto") {
890                 string const doc_encoding =
891                         language->encoding()->latexName();
892
893                 // Create a list with all the input encodings used
894                 // in the document
895                 std::set<string> encodings =
896                         features.getEncodingSet(doc_encoding);
897
898                 // thailatex does not use the inputenc package, but sets up
899                 // babel directly for tis620-0 encoding, therefore we must
900                 // not request inputenc for tis620-0 encoding
901                 if (!encodings.empty() && doc_encoding != "tis620-0") {
902                         os << "\\usepackage[";
903                         std::set<string>::const_iterator it = encodings.begin();
904                         std::set<string>::const_iterator const end = encodings.end();
905                         if (it != end) {
906                                 os << from_ascii(*it);
907                                 ++it;
908                         }
909                         for (; it != end; ++it)
910                                 os << ',' << from_ascii(*it);
911                         if (doc_encoding != "tis620-0") {
912                                 if (!encodings.empty())
913                                         os << ',';
914                                 os << from_ascii(doc_encoding);
915                         }
916                         os << "]{inputenc}\n";
917                         texrow.newline();
918                 }
919         // utf8-plain is for XeTeX users (inputenc not desired)
920         } else if (inputenc != "default" && inputenc != "tis620-0" &&
921                    inputenc != "ascii" &&  inputenc != "utf8-plain") {
922                 os << "\\usepackage[" << from_ascii(inputenc)
923                    << "]{inputenc}\n";
924                 texrow.newline();
925         }
926
927         // The encoding "armscii8" is only available when the package "armtex" is loaded.
928         // armscii8 is used for Armenian.
929         if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
930                 os << "\\usepackage{armtex}\n";
931                 texrow.newline();
932         }
933
934         if (use_geometry || nonstandard_papersize) {
935                 os << "\\usepackage{geometry}\n";
936                 texrow.newline();
937                 os << "\\geometry{verbose";
938                 if (orientation == ORIENTATION_LANDSCAPE)
939                         os << ",landscape";
940                 switch (papersize) {
941                 case PAPER_CUSTOM:
942                         if (!paperwidth.empty())
943                                 os << ",paperwidth="
944                                    << from_ascii(paperwidth);
945                         if (!paperheight.empty())
946                                 os << ",paperheight="
947                                    << from_ascii(paperheight);
948                         break;
949                 case PAPER_USLETTER:
950                         os << ",letterpaper";
951                         break;
952                 case PAPER_USLEGAL:
953                         os << ",legalpaper";
954                         break;
955                 case PAPER_USEXECUTIVE:
956                         os << ",executivepaper";
957                         break;
958                 case PAPER_A3:
959                         os << ",a3paper";
960                         break;
961                 case PAPER_A4:
962                         os << ",a4paper";
963                         break;
964                 case PAPER_A5:
965                         os << ",a5paper";
966                         break;
967                 case PAPER_B3:
968                         os << ",b3paper";
969                         break;
970                 case PAPER_B4:
971                         os << ",b4paper";
972                         break;
973                 case PAPER_B5:
974                         os << ",b5paper";
975                         break;
976                 default:
977                         // default papersize ie PAPER_DEFAULT
978                         switch (lyxrc.default_papersize) {
979                         case PAPER_DEFAULT: // keep compiler happy
980                         case PAPER_USLETTER:
981                                 os << ",letterpaper";
982                                 break;
983                         case PAPER_USLEGAL:
984                                 os << ",legalpaper";
985                                 break;
986                         case PAPER_USEXECUTIVE:
987                                 os << ",executivepaper";
988                                 break;
989                         case PAPER_A3:
990                                 os << ",a3paper";
991                                 break;
992                         case PAPER_A4:
993                                 os << ",a4paper";
994                                 break;
995                         case PAPER_A5:
996                                 os << ",a5paper";
997                                 break;
998                         case PAPER_B5:
999                                 os << ",b5paper";
1000                                 break;
1001                         case PAPER_B3:
1002                         case PAPER_B4:
1003                         case PAPER_CUSTOM:
1004                                 break;
1005                         }
1006                 }
1007                 if (!topmargin.empty())
1008                         os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1009                 if (!bottommargin.empty())
1010                         os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1011                 if (!leftmargin.empty())
1012                         os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1013                 if (!rightmargin.empty())
1014                         os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1015                 if (!headheight.empty())
1016                         os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1017                 if (!headsep.empty())
1018                         os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1019                 if (!footskip.empty())
1020                         os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1021                 os << "}\n";
1022                 texrow.newline();
1023         }
1024
1025         if (tokenPos(tclass.opt_pagestyle(),
1026                      '|', pagestyle) >= 0) {
1027                 if (pagestyle == "fancy") {
1028                         os << "\\usepackage{fancyhdr}\n";
1029                         texrow.newline();
1030                 }
1031                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1032                 texrow.newline();
1033         }
1034
1035         // Only if class has a ToC hierarchy
1036         if (tclass.hasTocLevels()) {
1037                 if (secnumdepth != tclass.secnumdepth()) {
1038                         os << "\\setcounter{secnumdepth}{"
1039                            << secnumdepth
1040                            << "}\n";
1041                         texrow.newline();
1042                 }
1043                 if (tocdepth != tclass.tocdepth()) {
1044                         os << "\\setcounter{tocdepth}{"
1045                            << tocdepth
1046                            << "}\n";
1047                         texrow.newline();
1048                 }
1049         }
1050
1051         if (paragraph_separation) {
1052                 switch (getDefSkip().kind()) {
1053                 case VSpace::SMALLSKIP:
1054                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1055                         break;
1056                 case VSpace::MEDSKIP:
1057                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1058                         break;
1059                 case VSpace::BIGSKIP:
1060                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1061                         break;
1062                 case VSpace::LENGTH:
1063                         os << "\\setlength{\\parskip}{"
1064                            << from_utf8(getDefSkip().length().asLatexString())
1065                            << "}\n";
1066                         break;
1067                 default: // should never happen // Then delete it.
1068                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1069                         break;
1070                 }
1071                 texrow.newline();
1072
1073                 os << "\\setlength{\\parindent}{0pt}\n";
1074                 texrow.newline();
1075         }
1076
1077         // If we use jurabib, we have to call babel here.
1078         if (use_babel && features.isRequired("jurabib")) {
1079                 os << from_ascii(babelCall(language_options.str()))
1080                    << '\n'
1081                    << from_ascii(features.getBabelOptions());
1082                 texrow.newline();
1083         }
1084
1085         // Now insert the LyX specific LaTeX commands...
1086
1087         // The optional packages;
1088         docstring lyxpreamble(from_ascii(features.getPackages()));
1089
1090         // this might be useful...
1091         lyxpreamble += "\n\\makeatletter\n";
1092
1093         // Some macros LyX will need
1094         docstring tmppreamble(from_ascii(features.getMacros()));
1095
1096         if (!tmppreamble.empty()) {
1097                 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1098                         "LyX specific LaTeX commands.\n"
1099                         + tmppreamble + '\n';
1100         }
1101
1102         // the text class specific preamble
1103         tmppreamble = features.getTClassPreamble();
1104         if (!tmppreamble.empty()) {
1105                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1106                         "Textclass specific LaTeX commands.\n"
1107                         + tmppreamble + '\n';
1108         }
1109
1110         /* the user-defined preamble */
1111         if (!preamble.empty()) {
1112                 // FIXME UNICODE
1113                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1114                         "User specified LaTeX commands.\n"
1115                         + from_utf8(preamble) + '\n';
1116         }
1117
1118         // Itemize bullet settings need to be last in case the user
1119         // defines their own bullets that use a package included
1120         // in the user-defined preamble -- ARRae
1121         // Actually it has to be done much later than that
1122         // since some packages like frenchb make modifications
1123         // at \begin{document} time -- JMarc
1124         docstring bullets_def;
1125         for (int i = 0; i < 4; ++i) {
1126                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1127                         if (bullets_def.empty())
1128                                 bullets_def += "\\AtBeginDocument{\n";
1129                         bullets_def += "  \\def\\labelitemi";
1130                         switch (i) {
1131                                 // `i' is one less than the item to modify
1132                         case 0:
1133                                 break;
1134                         case 1:
1135                                 bullets_def += 'i';
1136                                 break;
1137                         case 2:
1138                                 bullets_def += "ii";
1139                                 break;
1140                         case 3:
1141                                 bullets_def += 'v';
1142                                 break;
1143                         }
1144                         bullets_def += '{' +
1145                                 user_defined_bullet(i).getText()
1146                                 + "}\n";
1147                 }
1148         }
1149
1150         if (!bullets_def.empty())
1151                 lyxpreamble += bullets_def + "}\n\n";
1152
1153         // We try to load babel late, in case it interferes
1154         // with other packages.
1155         // Jurabib has to be called after babel, though.
1156         if (use_babel && !features.isRequired("jurabib")) {
1157                 // FIXME UNICODE
1158                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1159                 lyxpreamble += from_utf8(features.getBabelOptions());
1160         }
1161
1162         lyxpreamble += "\\makeatother\n";
1163
1164         // dvipost settings come after everything else
1165         if (features.isAvailable("dvipost") && outputChanges) {
1166                 lyxpreamble +=
1167                         "\\dvipostlayout\n"
1168                         "\\dvipost{osstart color push Red}\n"
1169                         "\\dvipost{osend color pop}\n"
1170                         "\\dvipost{cbstart color push Blue}\n"
1171                         "\\dvipost{cbend color pop}\n";
1172         }
1173
1174         int const nlines =
1175                 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1176         for (int j = 0; j != nlines; ++j) {
1177                 texrow.newline();
1178         }
1179
1180         os << lyxpreamble;
1181         return use_babel;
1182 }
1183
1184
1185 void BufferParams::useClassDefaults()
1186 {
1187         TextClass const & tclass = textclasslist[textclass];
1188
1189         sides = tclass.sides();
1190         columns = tclass.columns();
1191         pagestyle = tclass.pagestyle();
1192         options = tclass.options();
1193         // Only if class has a ToC hierarchy
1194         if (tclass.hasTocLevels()) {
1195                 secnumdepth = tclass.secnumdepth();
1196                 tocdepth = tclass.tocdepth();
1197         }
1198 }
1199
1200
1201 bool BufferParams::hasClassDefaults() const
1202 {
1203         TextClass const & tclass = textclasslist[textclass];
1204
1205         return (sides == tclass.sides()
1206                 && columns == tclass.columns()
1207                 && pagestyle == tclass.pagestyle()
1208                 && options == tclass.options()
1209                 && secnumdepth == tclass.secnumdepth()
1210                 && tocdepth == tclass.tocdepth());
1211 }
1212
1213
1214 TextClass const & BufferParams::getTextClass() const
1215 {
1216         return textclasslist[textclass];
1217 }
1218
1219
1220 Font const BufferParams::getFont() const
1221 {
1222         Font f = getTextClass().defaultfont();
1223         f.setLanguage(language);
1224         if (fontsDefaultFamily == "rmdefault")
1225                 f.setFamily(Font::ROMAN_FAMILY);
1226         else if (fontsDefaultFamily == "sfdefault")
1227                 f.setFamily(Font::SANS_FAMILY);
1228         else if (fontsDefaultFamily == "ttdefault")
1229                 f.setFamily(Font::TYPEWRITER_FAMILY);
1230         return f;
1231 }
1232
1233
1234 void BufferParams::readPreamble(Lexer & lex)
1235 {
1236         if (lex.getString() != "\\begin_preamble")
1237                 lyxerr << "Error (BufferParams::readPreamble):"
1238                         "consistency check failed." << endl;
1239
1240         preamble = lex.getLongString("\\end_preamble");
1241 }
1242
1243
1244 void BufferParams::readLanguage(Lexer & lex)
1245 {
1246         if (!lex.next()) return;
1247
1248         string const tmptok = lex.getString();
1249
1250         // check if tmptok is part of tex_babel in tex-defs.h
1251         language = languages.getLanguage(tmptok);
1252         if (!language) {
1253                 // Language tmptok was not found
1254                 language = default_language;
1255                 lyxerr << "Warning: Setting language `"
1256                        << tmptok << "' to `" << language->lang()
1257                        << "'." << endl;
1258         }
1259 }
1260
1261
1262 void BufferParams::readGraphicsDriver(Lexer & lex)
1263 {
1264         if (!lex.next()) return;
1265
1266         string const tmptok = lex.getString();
1267         // check if tmptok is part of tex_graphics in tex_defs.h
1268         int n = 0;
1269         while (true) {
1270                 string const test = tex_graphics[n++];
1271
1272                 if (test == tmptok) {
1273                         graphicsDriver = tmptok;
1274                         break;
1275                 } else if (test == "") {
1276                         lex.printError(
1277                                 "Warning: graphics driver `$$Token' not recognized!\n"
1278                                 "         Setting graphics driver to `default'.\n");
1279                         graphicsDriver = "default";
1280                         break;
1281                 }
1282         }
1283 }
1284
1285
1286 void BufferParams::readBullets(Lexer & lex)
1287 {
1288         if (!lex.next()) return;
1289
1290         int const index = lex.getInteger();
1291         lex.next();
1292         int temp_int = lex.getInteger();
1293         user_defined_bullet(index).setFont(temp_int);
1294         temp_bullet(index).setFont(temp_int);
1295         lex >> temp_int;
1296         user_defined_bullet(index).setCharacter(temp_int);
1297         temp_bullet(index).setCharacter(temp_int);
1298         lex >> temp_int;
1299         user_defined_bullet(index).setSize(temp_int);
1300         temp_bullet(index).setSize(temp_int);
1301 }
1302
1303
1304 void BufferParams::readBulletsLaTeX(Lexer & lex)
1305 {
1306         // The bullet class should be able to read this.
1307         if (!lex.next()) return;
1308         int const index = lex.getInteger();
1309         lex.next(true);
1310         docstring const temp_str = lex.getDocString();
1311
1312         user_defined_bullet(index).setText(temp_str);
1313         temp_bullet(index).setText(temp_str);
1314 }
1315
1316
1317 string const BufferParams::paperSizeName() const
1318 {
1319         char real_papersize = papersize;
1320         if (real_papersize == PAPER_DEFAULT)
1321                 real_papersize = lyxrc.default_papersize;
1322
1323         switch (real_papersize) {
1324         case PAPER_A3:
1325                 return "a3";
1326         case PAPER_A4:
1327                 return "a4";
1328         case PAPER_A5:
1329                 return "a5";
1330         case PAPER_B5:
1331                 return "b5";
1332         case PAPER_USEXECUTIVE:
1333                 return "foolscap";
1334         case PAPER_USLEGAL:
1335                 return "legal";
1336         case PAPER_USLETTER:
1337         default:
1338                 return "letter";
1339         }
1340 }
1341
1342
1343 string const BufferParams::dvips_options() const
1344 {
1345         string result;
1346
1347         if (use_geometry
1348             && papersize == PAPER_CUSTOM
1349             && !lyxrc.print_paper_dimension_flag.empty()
1350             && !paperwidth.empty()
1351             && !paperheight.empty()) {
1352                 // using a custom papersize
1353                 result = lyxrc.print_paper_dimension_flag;
1354                 result += ' ' + paperwidth;
1355                 result += ',' + paperheight;
1356         } else {
1357                 string const paper_option = paperSizeName();
1358                 if (paper_option != "letter" ||
1359                     orientation != ORIENTATION_LANDSCAPE) {
1360                         // dvips won't accept -t letter -t landscape.
1361                         // In all other cases, include the paper size
1362                         // explicitly.
1363                         result = lyxrc.print_paper_flag;
1364                         result += ' ' + paper_option;
1365                 }
1366         }
1367         if (orientation == ORIENTATION_LANDSCAPE &&
1368             papersize != PAPER_CUSTOM)
1369                 result += ' ' + lyxrc.print_landscape_flag;
1370         return result;
1371 }
1372
1373
1374 string const BufferParams::babelCall(string const & lang_opts) const
1375 {
1376         string tmp = lyxrc.language_package;
1377         if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1378                 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1379         return tmp;
1380 }
1381
1382
1383 string const BufferParams::loadFonts(string const & rm,
1384                                      string const & sf, string const & tt,
1385                                      bool const & sc, bool const & osf,
1386                                      int const & sfscale, int const & ttscale) const
1387 {
1388         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1389            several packages have been replaced by others, that might not
1390            be installed on every system. We have to take care for that
1391            (see psnfss.pdf). We try to support all psnfss fonts as well
1392            as the fonts that have become de facto standard in the LaTeX
1393            world (e.g. Latin Modern). We do not support obsolete fonts
1394            (like PSLatex). In general, it should be possible to mix any
1395            rm font with any sf or tt font, respectively. (JSpitzm)
1396            TODO:
1397                 -- separate math fonts.
1398         */
1399
1400         if (rm == "default" && sf == "default" && tt == "default")
1401                 //nothing to do
1402                 return string();
1403
1404         ostringstream os;
1405
1406         // ROMAN FONTS
1407         // Computer Modern (must be explicitely selectable -- there might be classes
1408         // that define a different default font!
1409         if (rm == "cmr") {
1410                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1411                 // osf for Computer Modern needs eco.sty
1412                 if (osf)
1413                         os << "\\usepackage{eco}\n";
1414         }
1415         // Latin Modern Roman
1416         else if (rm == "lmodern")
1417                 os << "\\usepackage{lmodern}\n";
1418         // AE
1419         else if (rm == "ae") {
1420                 // not needed when using OT1 font encoding.
1421                 if (lyxrc.fontenc != "default")
1422                         os << "\\usepackage{ae,aecompl}\n";
1423         }
1424         // Times
1425         else if (rm == "times") {
1426                 // try to load the best available package
1427                 if (LaTeXFeatures::isAvailable("mathptmx"))
1428                         os << "\\usepackage{mathptmx}\n";
1429                 else if (LaTeXFeatures::isAvailable("mathptm"))
1430                         os << "\\usepackage{mathptm}\n";
1431                 else
1432                         os << "\\usepackage{times}\n";
1433         }
1434         // Palatino
1435         else if (rm == "palatino") {
1436                 // try to load the best available package
1437                 if (LaTeXFeatures::isAvailable("mathpazo")) {
1438                         os << "\\usepackage";
1439                         if (osf || sc) {
1440                                 os << '[';
1441                                 if (!osf)
1442                                         os << "sc";
1443                                 else
1444                                         // "osf" includes "sc"!
1445                                         os << "osf";
1446                                 os << ']';
1447                         }
1448                         os << "{mathpazo}\n";
1449                 }
1450                 else if (LaTeXFeatures::isAvailable("mathpple"))
1451                         os << "\\usepackage{mathpple}\n";
1452                 else
1453                         os << "\\usepackage{palatino}\n";
1454         }
1455         // Utopia
1456         else if (rm == "utopia") {
1457                 // fourier supersedes utopia.sty, but does
1458                 // not work with OT1 encoding.
1459                 if (LaTeXFeatures::isAvailable("fourier")
1460                     && lyxrc.fontenc != "default") {
1461                         os << "\\usepackage";
1462                         if (osf || sc) {
1463                                 os << '[';
1464                                 if (sc)
1465                                         os << "expert";
1466                                 if (osf && sc)
1467                                         os << ',';
1468                                 if (osf)
1469                                         os << "oldstyle";
1470                                 os << ']';
1471                         }
1472                         os << "{fourier}\n";
1473                 }
1474                 else
1475                         os << "\\usepackage{utopia}\n";
1476         }
1477         // Bera (complete fontset)
1478         else if (rm == "bera" && sf == "default" && tt == "default")
1479                 os << "\\usepackage{bera}\n";
1480         // everything else
1481         else if (rm != "default")
1482                 os << "\\usepackage" << "{" << rm << "}\n";
1483
1484         // SANS SERIF
1485         // Helvetica, Bera Sans
1486         if (sf == "helvet" || sf == "berasans") {
1487                 if (sfscale != 100)
1488                         os << "\\usepackage[scaled=" << float(sfscale) / 100
1489                            << "]{" << sf << "}\n";
1490                 else
1491                         os << "\\usepackage{" << sf << "}\n";
1492         }
1493         // Avant Garde
1494         else if (sf == "avant")
1495                 os << "\\usepackage{" << sf << "}\n";
1496         // Computer Modern, Latin Modern, CM Bright
1497         else if (sf != "default")
1498                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1499
1500         // monospaced/typewriter
1501         // Courier, LuxiMono
1502         if (tt == "luximono" || tt == "beramono") {
1503                 if (ttscale != 100)
1504                         os << "\\usepackage[scaled=" << float(ttscale) / 100
1505                            << "]{" << tt << "}\n";
1506                 else
1507                         os << "\\usepackage{" << tt << "}\n";
1508         }
1509         // Courier
1510         else if (tt == "courier" )
1511                 os << "\\usepackage{" << tt << "}\n";
1512         // Computer Modern, Latin Modern, CM Bright
1513         else if  (tt != "default")
1514                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1515
1516         return os.str();
1517 }
1518
1519
1520 Encoding const & BufferParams::encoding() const
1521 {
1522         if (inputenc == "auto" || inputenc == "default")
1523                 return *(language->encoding());
1524         Encoding const * const enc =
1525                 encodings.getFromLaTeXName(inputenc);
1526         if (enc)
1527                 return *enc;
1528         lyxerr << "Unknown inputenc value `" << inputenc
1529                << "'. Using `auto' instead." << endl;
1530         return *(language->encoding());
1531 }
1532
1533
1534 biblio::CiteEngine BufferParams::getEngine() const
1535 {
1536         // FIXME the class should provide the numerical/
1537         // authoryear choice
1538         if (getTextClass().provides("natbib")
1539             && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1540                 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1541         return cite_engine_;
1542 }
1543
1544
1545 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1546 {
1547         cite_engine_ = cite_engine;
1548 }
1549
1550 } // namespace lyx