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