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