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