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