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