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