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