]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
resolve makefile problem step 2
[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         } else if (inputenc != "default" && inputenc != "tis620-0" &&
920                    inputenc != "ascii") {
921                 os << "\\usepackage[" << from_ascii(inputenc)
922                    << "]{inputenc}\n";
923                 texrow.newline();
924         }
925
926         // The encoding "armscii8" is only available when the package "armtex" is loaded.
927         // armscii8 is used for Armenian.
928         if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
929                 os << "\\usepackage{armtex}\n";
930                 texrow.newline();
931         }
932
933         if (use_geometry || nonstandard_papersize) {
934                 os << "\\usepackage{geometry}\n";
935                 texrow.newline();
936                 os << "\\geometry{verbose";
937                 if (orientation == ORIENTATION_LANDSCAPE)
938                         os << ",landscape";
939                 switch (papersize) {
940                 case PAPER_CUSTOM:
941                         if (!paperwidth.empty())
942                                 os << ",paperwidth="
943                                    << from_ascii(paperwidth);
944                         if (!paperheight.empty())
945                                 os << ",paperheight="
946                                    << from_ascii(paperheight);
947                         break;
948                 case PAPER_USLETTER:
949                         os << ",letterpaper";
950                         break;
951                 case PAPER_USLEGAL:
952                         os << ",legalpaper";
953                         break;
954                 case PAPER_USEXECUTIVE:
955                         os << ",executivepaper";
956                         break;
957                 case PAPER_A3:
958                         os << ",a3paper";
959                         break;
960                 case PAPER_A4:
961                         os << ",a4paper";
962                         break;
963                 case PAPER_A5:
964                         os << ",a5paper";
965                         break;
966                 case PAPER_B3:
967                         os << ",b3paper";
968                         break;
969                 case PAPER_B4:
970                         os << ",b4paper";
971                         break;
972                 case PAPER_B5:
973                         os << ",b5paper";
974                         break;
975                 default:
976                         // default papersize ie PAPER_DEFAULT
977                         switch (lyxrc.default_papersize) {
978                         case PAPER_DEFAULT: // keep compiler happy
979                         case PAPER_USLETTER:
980                                 os << ",letterpaper";
981                                 break;
982                         case PAPER_USLEGAL:
983                                 os << ",legalpaper";
984                                 break;
985                         case PAPER_USEXECUTIVE:
986                                 os << ",executivepaper";
987                                 break;
988                         case PAPER_A3:
989                                 os << ",a3paper";
990                                 break;
991                         case PAPER_A4:
992                                 os << ",a4paper";
993                                 break;
994                         case PAPER_A5:
995                                 os << ",a5paper";
996                                 break;
997                         case PAPER_B5:
998                                 os << ",b5paper";
999                                 break;
1000                         case PAPER_B3:
1001                         case PAPER_B4:
1002                         case PAPER_CUSTOM:
1003                                 break;
1004                         }
1005                 }
1006                 if (!topmargin.empty())
1007                         os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1008                 if (!bottommargin.empty())
1009                         os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1010                 if (!leftmargin.empty())
1011                         os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1012                 if (!rightmargin.empty())
1013                         os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1014                 if (!headheight.empty())
1015                         os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1016                 if (!headsep.empty())
1017                         os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1018                 if (!footskip.empty())
1019                         os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1020                 os << "}\n";
1021                 texrow.newline();
1022         }
1023
1024         if (tokenPos(tclass.opt_pagestyle(),
1025                      '|', pagestyle) >= 0) {
1026                 if (pagestyle == "fancy") {
1027                         os << "\\usepackage{fancyhdr}\n";
1028                         texrow.newline();
1029                 }
1030                 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1031                 texrow.newline();
1032         }
1033
1034         // Only if class has a ToC hierarchy
1035         if (tclass.hasTocLevels()) {
1036                 if (secnumdepth != tclass.secnumdepth()) {
1037                         os << "\\setcounter{secnumdepth}{"
1038                            << secnumdepth
1039                            << "}\n";
1040                         texrow.newline();
1041                 }
1042                 if (tocdepth != tclass.tocdepth()) {
1043                         os << "\\setcounter{tocdepth}{"
1044                            << tocdepth
1045                            << "}\n";
1046                         texrow.newline();
1047                 }
1048         }
1049
1050         if (paragraph_separation) {
1051                 switch (getDefSkip().kind()) {
1052                 case VSpace::SMALLSKIP:
1053                         os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1054                         break;
1055                 case VSpace::MEDSKIP:
1056                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1057                         break;
1058                 case VSpace::BIGSKIP:
1059                         os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1060                         break;
1061                 case VSpace::LENGTH:
1062                         os << "\\setlength{\\parskip}{"
1063                            << from_utf8(getDefSkip().length().asLatexString())
1064                            << "}\n";
1065                         break;
1066                 default: // should never happen // Then delete it.
1067                         os << "\\setlength{\\parskip}{\\medskipamount}\n";
1068                         break;
1069                 }
1070                 texrow.newline();
1071
1072                 os << "\\setlength{\\parindent}{0pt}\n";
1073                 texrow.newline();
1074         }
1075
1076         // If we use jurabib, we have to call babel here.
1077         if (use_babel && features.isRequired("jurabib")) {
1078                 os << from_ascii(babelCall(language_options.str()))
1079                    << '\n'
1080                    << from_ascii(features.getBabelOptions());
1081                 texrow.newline();
1082         }
1083
1084         // Now insert the LyX specific LaTeX commands...
1085
1086         // The optional packages;
1087         docstring lyxpreamble(from_ascii(features.getPackages()));
1088
1089         // this might be useful...
1090         lyxpreamble += "\n\\makeatletter\n";
1091
1092         // Some macros LyX will need
1093         docstring tmppreamble(from_ascii(features.getMacros()));
1094
1095         if (!tmppreamble.empty()) {
1096                 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1097                         "LyX specific LaTeX commands.\n"
1098                         + tmppreamble + '\n';
1099         }
1100
1101         // the text class specific preamble
1102         tmppreamble = features.getTClassPreamble();
1103         if (!tmppreamble.empty()) {
1104                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1105                         "Textclass specific LaTeX commands.\n"
1106                         + tmppreamble + '\n';
1107         }
1108
1109         /* the user-defined preamble */
1110         if (!preamble.empty()) {
1111                 // FIXME UNICODE
1112                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1113                         "User specified LaTeX commands.\n"
1114                         + from_utf8(preamble) + '\n';
1115         }
1116
1117         // Itemize bullet settings need to be last in case the user
1118         // defines their own bullets that use a package included
1119         // in the user-defined preamble -- ARRae
1120         // Actually it has to be done much later than that
1121         // since some packages like frenchb make modifications
1122         // at \begin{document} time -- JMarc
1123         docstring bullets_def;
1124         for (int i = 0; i < 4; ++i) {
1125                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1126                         if (bullets_def.empty())
1127                                 bullets_def += "\\AtBeginDocument{\n";
1128                         bullets_def += "  \\def\\labelitemi";
1129                         switch (i) {
1130                                 // `i' is one less than the item to modify
1131                         case 0:
1132                                 break;
1133                         case 1:
1134                                 bullets_def += 'i';
1135                                 break;
1136                         case 2:
1137                                 bullets_def += "ii";
1138                                 break;
1139                         case 3:
1140                                 bullets_def += 'v';
1141                                 break;
1142                         }
1143                         bullets_def += '{' +
1144                                 user_defined_bullet(i).getText()
1145                                 + "}\n";
1146                 }
1147         }
1148
1149         if (!bullets_def.empty())
1150                 lyxpreamble += bullets_def + "}\n\n";
1151
1152         // We try to load babel late, in case it interferes
1153         // with other packages.
1154         // Jurabib has to be called after babel, though.
1155         if (use_babel && !features.isRequired("jurabib")) {
1156                 // FIXME UNICODE
1157                 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1158                 lyxpreamble += from_utf8(features.getBabelOptions());
1159         }
1160
1161         lyxpreamble += "\\makeatother\n";
1162
1163         // dvipost settings come after everything else
1164         if (features.isAvailable("dvipost") && outputChanges) {
1165                 lyxpreamble +=
1166                         "\\dvipostlayout\n"
1167                         "\\dvipost{osstart color push Red}\n"
1168                         "\\dvipost{osend color pop}\n"
1169                         "\\dvipost{cbstart color push Blue}\n"
1170                         "\\dvipost{cbend color pop}\n";
1171         }
1172
1173         int const nlines =
1174                 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1175         for (int j = 0; j != nlines; ++j) {
1176                 texrow.newline();
1177         }
1178
1179         os << lyxpreamble;
1180         return use_babel;
1181 }
1182
1183
1184 void BufferParams::useClassDefaults()
1185 {
1186         TextClass const & tclass = textclasslist[textclass];
1187
1188         sides = tclass.sides();
1189         columns = tclass.columns();
1190         pagestyle = tclass.pagestyle();
1191         options = tclass.options();
1192         // Only if class has a ToC hierarchy
1193         if (tclass.hasTocLevels()) {
1194                 secnumdepth = tclass.secnumdepth();
1195                 tocdepth = tclass.tocdepth();
1196         }
1197 }
1198
1199
1200 bool BufferParams::hasClassDefaults() const
1201 {
1202         TextClass const & tclass = textclasslist[textclass];
1203
1204         return (sides == tclass.sides()
1205                 && columns == tclass.columns()
1206                 && pagestyle == tclass.pagestyle()
1207                 && options == tclass.options()
1208                 && secnumdepth == tclass.secnumdepth()
1209                 && tocdepth == tclass.tocdepth());
1210 }
1211
1212
1213 TextClass const & BufferParams::getTextClass() const
1214 {
1215         return textclasslist[textclass];
1216 }
1217
1218
1219 Font const BufferParams::getFont() const
1220 {
1221         Font f = getTextClass().defaultfont();
1222         f.setLanguage(language);
1223         if (fontsDefaultFamily == "rmdefault")
1224                 f.setFamily(Font::ROMAN_FAMILY);
1225         else if (fontsDefaultFamily == "sfdefault")
1226                 f.setFamily(Font::SANS_FAMILY);
1227         else if (fontsDefaultFamily == "ttdefault")
1228                 f.setFamily(Font::TYPEWRITER_FAMILY);
1229         return f;
1230 }
1231
1232
1233 void BufferParams::readPreamble(Lexer & lex)
1234 {
1235         if (lex.getString() != "\\begin_preamble")
1236                 lyxerr << "Error (BufferParams::readPreamble):"
1237                         "consistency check failed." << endl;
1238
1239         preamble = lex.getLongString("\\end_preamble");
1240 }
1241
1242
1243 void BufferParams::readLanguage(Lexer & lex)
1244 {
1245         if (!lex.next()) return;
1246
1247         string const tmptok = lex.getString();
1248
1249         // check if tmptok is part of tex_babel in tex-defs.h
1250         language = languages.getLanguage(tmptok);
1251         if (!language) {
1252                 // Language tmptok was not found
1253                 language = default_language;
1254                 lyxerr << "Warning: Setting language `"
1255                        << tmptok << "' to `" << language->lang()
1256                        << "'." << endl;
1257         }
1258 }
1259
1260
1261 void BufferParams::readGraphicsDriver(Lexer & lex)
1262 {
1263         if (!lex.next()) return;
1264
1265         string const tmptok = lex.getString();
1266         // check if tmptok is part of tex_graphics in tex_defs.h
1267         int n = 0;
1268         while (true) {
1269                 string const test = tex_graphics[n++];
1270
1271                 if (test == tmptok) {
1272                         graphicsDriver = tmptok;
1273                         break;
1274                 } else if (test == "") {
1275                         lex.printError(
1276                                 "Warning: graphics driver `$$Token' not recognized!\n"
1277                                 "         Setting graphics driver to `default'.\n");
1278                         graphicsDriver = "default";
1279                         break;
1280                 }
1281         }
1282 }
1283
1284
1285 void BufferParams::readBullets(Lexer & lex)
1286 {
1287         if (!lex.next()) return;
1288
1289         int const index = lex.getInteger();
1290         lex.next();
1291         int temp_int = lex.getInteger();
1292         user_defined_bullet(index).setFont(temp_int);
1293         temp_bullet(index).setFont(temp_int);
1294         lex >> temp_int;
1295         user_defined_bullet(index).setCharacter(temp_int);
1296         temp_bullet(index).setCharacter(temp_int);
1297         lex >> temp_int;
1298         user_defined_bullet(index).setSize(temp_int);
1299         temp_bullet(index).setSize(temp_int);
1300 }
1301
1302
1303 void BufferParams::readBulletsLaTeX(Lexer & lex)
1304 {
1305         // The bullet class should be able to read this.
1306         if (!lex.next()) return;
1307         int const index = lex.getInteger();
1308         lex.next(true);
1309         docstring const temp_str = lex.getDocString();
1310
1311         user_defined_bullet(index).setText(temp_str);
1312         temp_bullet(index).setText(temp_str);
1313 }
1314
1315
1316 string const BufferParams::paperSizeName() const
1317 {
1318         char real_papersize = papersize;
1319         if (real_papersize == PAPER_DEFAULT)
1320                 real_papersize = lyxrc.default_papersize;
1321
1322         switch (real_papersize) {
1323         case PAPER_A3:
1324                 return "a3";
1325         case PAPER_A4:
1326                 return "a4";
1327         case PAPER_A5:
1328                 return "a5";
1329         case PAPER_B5:
1330                 return "b5";
1331         case PAPER_USEXECUTIVE:
1332                 return "foolscap";
1333         case PAPER_USLEGAL:
1334                 return "legal";
1335         case PAPER_USLETTER:
1336         default:
1337                 return "letter";
1338         }
1339 }
1340
1341
1342 string const BufferParams::dvips_options() const
1343 {
1344         string result;
1345
1346         if (use_geometry
1347             && papersize == PAPER_CUSTOM
1348             && !lyxrc.print_paper_dimension_flag.empty()
1349             && !paperwidth.empty()
1350             && !paperheight.empty()) {
1351                 // using a custom papersize
1352                 result = lyxrc.print_paper_dimension_flag;
1353                 result += ' ' + paperwidth;
1354                 result += ',' + paperheight;
1355         } else {
1356                 string const paper_option = paperSizeName();
1357                 if (paper_option != "letter" ||
1358                     orientation != ORIENTATION_LANDSCAPE) {
1359                         // dvips won't accept -t letter -t landscape.
1360                         // In all other cases, include the paper size
1361                         // explicitly.
1362                         result = lyxrc.print_paper_flag;
1363                         result += ' ' + paper_option;
1364                 }
1365         }
1366         if (orientation == ORIENTATION_LANDSCAPE &&
1367             papersize != PAPER_CUSTOM)
1368                 result += ' ' + lyxrc.print_landscape_flag;
1369         return result;
1370 }
1371
1372
1373 string const BufferParams::babelCall(string const & lang_opts) const
1374 {
1375         string tmp = lyxrc.language_package;
1376         if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1377                 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1378         return tmp;
1379 }
1380
1381
1382 string const BufferParams::loadFonts(string const & rm,
1383                                      string const & sf, string const & tt,
1384                                      bool const & sc, bool const & osf,
1385                                      int const & sfscale, int const & ttscale) const
1386 {
1387         /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1388            several packages have been replaced by others, that might not
1389            be installed on every system. We have to take care for that
1390            (see psnfss.pdf). We try to support all psnfss fonts as well
1391            as the fonts that have become de facto standard in the LaTeX
1392            world (e.g. Latin Modern). We do not support obsolete fonts
1393            (like PSLatex). In general, it should be possible to mix any
1394            rm font with any sf or tt font, respectively. (JSpitzm)
1395            TODO:
1396                 -- separate math fonts.
1397         */
1398
1399         if (rm == "default" && sf == "default" && tt == "default")
1400                 //nothing to do
1401                 return string();
1402
1403         ostringstream os;
1404
1405         // ROMAN FONTS
1406         // Computer Modern (must be explicitely selectable -- there might be classes
1407         // that define a different default font!
1408         if (rm == "cmr") {
1409                 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1410                 // osf for Computer Modern needs eco.sty
1411                 if (osf)
1412                         os << "\\usepackage{eco}\n";
1413         }
1414         // Latin Modern Roman
1415         else if (rm == "lmodern")
1416                 os << "\\usepackage{lmodern}\n";
1417         // AE
1418         else if (rm == "ae") {
1419                 // not needed when using OT1 font encoding.
1420                 if (lyxrc.fontenc != "default")
1421                         os << "\\usepackage{ae,aecompl}\n";
1422         }
1423         // Times
1424         else if (rm == "times") {
1425                 // try to load the best available package
1426                 if (LaTeXFeatures::isAvailable("mathptmx"))
1427                         os << "\\usepackage{mathptmx}\n";
1428                 else if (LaTeXFeatures::isAvailable("mathptm"))
1429                         os << "\\usepackage{mathptm}\n";
1430                 else
1431                         os << "\\usepackage{times}\n";
1432         }
1433         // Palatino
1434         else if (rm == "palatino") {
1435                 // try to load the best available package
1436                 if (LaTeXFeatures::isAvailable("mathpazo")) {
1437                         os << "\\usepackage";
1438                         if (osf || sc) {
1439                                 os << '[';
1440                                 if (!osf)
1441                                         os << "sc";
1442                                 else
1443                                         // "osf" includes "sc"!
1444                                         os << "osf";
1445                                 os << ']';
1446                         }
1447                         os << "{mathpazo}\n";
1448                 }
1449                 else if (LaTeXFeatures::isAvailable("mathpple"))
1450                         os << "\\usepackage{mathpple}\n";
1451                 else
1452                         os << "\\usepackage{palatino}\n";
1453         }
1454         // Utopia
1455         else if (rm == "utopia") {
1456                 // fourier supersedes utopia.sty, but does
1457                 // not work with OT1 encoding.
1458                 if (LaTeXFeatures::isAvailable("fourier")
1459                     && lyxrc.fontenc != "default") {
1460                         os << "\\usepackage";
1461                         if (osf || sc) {
1462                                 os << '[';
1463                                 if (sc)
1464                                         os << "expert";
1465                                 if (osf && sc)
1466                                         os << ',';
1467                                 if (osf)
1468                                         os << "oldstyle";
1469                                 os << ']';
1470                         }
1471                         os << "{fourier}\n";
1472                 }
1473                 else
1474                         os << "\\usepackage{utopia}\n";
1475         }
1476         // Bera (complete fontset)
1477         else if (rm == "bera" && sf == "default" && tt == "default")
1478                 os << "\\usepackage{bera}\n";
1479         // everything else
1480         else if (rm != "default")
1481                 os << "\\usepackage" << "{" << rm << "}\n";
1482
1483         // SANS SERIF
1484         // Helvetica, Bera Sans
1485         if (sf == "helvet" || sf == "berasans") {
1486                 if (sfscale != 100)
1487                         os << "\\usepackage[scaled=" << float(sfscale) / 100
1488                            << "]{" << sf << "}\n";
1489                 else
1490                         os << "\\usepackage{" << sf << "}\n";
1491         }
1492         // Avant Garde
1493         else if (sf == "avant")
1494                 os << "\\usepackage{" << sf << "}\n";
1495         // Computer Modern, Latin Modern, CM Bright
1496         else if (sf != "default")
1497                 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1498
1499         // monospaced/typewriter
1500         // Courier, LuxiMono
1501         if (tt == "luximono" || tt == "beramono") {
1502                 if (ttscale != 100)
1503                         os << "\\usepackage[scaled=" << float(ttscale) / 100
1504                            << "]{" << tt << "}\n";
1505                 else
1506                         os << "\\usepackage{" << tt << "}\n";
1507         }
1508         // Courier
1509         else if (tt == "courier" )
1510                 os << "\\usepackage{" << tt << "}\n";
1511         // Computer Modern, Latin Modern, CM Bright
1512         else if  (tt != "default")
1513                 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1514
1515         return os.str();
1516 }
1517
1518
1519 Encoding const & BufferParams::encoding() const
1520 {
1521         if (inputenc == "auto" || inputenc == "default")
1522                 return *(language->encoding());
1523         Encoding const * const enc =
1524                 encodings.getFromLaTeXName(inputenc);
1525         if (enc)
1526                 return *enc;
1527         lyxerr << "Unknown inputenc value `" << inputenc
1528                << "'. Using `auto' instead." << endl;
1529         return *(language->encoding());
1530 }
1531
1532
1533 biblio::CiteEngine BufferParams::getEngine() const
1534 {
1535         // FIXME the class should provide the numerical/
1536         // authoryear choice
1537         if (getTextClass().provides("natbib")
1538             && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1539                 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1540         return cite_engine_;
1541 }
1542
1543
1544 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1545 {
1546         cite_engine_ = cite_engine;
1547 }
1548
1549 } // namespace lyx