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