]> git.lyx.org Git - lyx.git/blob - src/BufferParams.cpp
* Only enter inset which return true on isActive(). This is the behavior in the curso...
[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                 // validate par and produce a valid listings parameter string
612                 try {
613                         listings_params = InsetListingsParams(par).params();
614                 } catch (invalidParam & e) {
615                         lyxerr << "Invalid parameter string " << par << endl;
616                         lyxerr << e.what() << endl;
617                         listings_params = string();
618                 }
619         } else if (token == "\\papersides") {
620                 int psides;
621                 lex >> psides;
622                 sides = sidestranslator().find(psides);
623         } else if (token == "\\paperpagestyle") {
624                 lex >> pagestyle;
625         } else if (token == "\\bullet") {
626                 readBullets(lex);
627         } else if (token == "\\bulletLaTeX") {
628                 readBulletsLaTeX(lex);
629         } else if (token == "\\secnumdepth") {
630                 lex >> secnumdepth;
631         } else if (token == "\\tocdepth") {
632                 lex >> tocdepth;
633         } else if (token == "\\spacing") {
634                 string nspacing;
635                 lex >> nspacing;
636                 string tmp_val;
637                 if (nspacing == "other") {
638                         lex >> tmp_val;
639                 }
640                 spacing().set(spacetranslator().find(nspacing), tmp_val);
641         } else if (token == "\\float_placement") {
642                 lex >> float_placement;
643         } else {
644                 return token;
645         }
646
647         return string();
648 }
649
650
651 void BufferParams::writeFile(ostream & os) const
652 {
653         // The top of the file is written by the buffer.
654         // Prints out the buffer info into the .lyx file given by file
655
656         // the textclass
657         os << "\\textclass " << textclasslist[textclass].name() << '\n';
658
659         // then the preamble
660         if (!preamble.empty()) {
661                 // remove '\n' from the end of preamble
662                 string const tmppreamble = rtrim(preamble, "\n");
663                 os << "\\begin_preamble\n"
664                    << tmppreamble
665                    << "\n\\end_preamble\n";
666         }
667
668         // the options
669         if (!options.empty()) {
670                 os << "\\options " << options << '\n';
671         }
672
673         // then the text parameters
674         if (language != ignore_language)
675                 os << "\\language " << language->lang() << '\n';
676         os << "\\inputencoding " << inputenc
677            << "\n\\font_roman " << fontsRoman
678            << "\n\\font_sans " << fontsSans
679            << "\n\\font_typewriter " << fontsTypewriter
680            << "\n\\font_default_family " << fontsDefaultFamily
681            << "\n\\font_sc " << convert<string>(fontsSC)
682            << "\n\\font_osf " << convert<string>(fontsOSF)
683            << "\n\\font_sf_scale " << fontsSansScale
684            << "\n\\font_tt_scale " << fontsTypewriterScale
685            << "\n\\graphics " << graphicsDriver << '\n';
686
687         if (!float_placement.empty()) {
688                 os << "\\float_placement " << float_placement << '\n';
689         }
690         os << "\\paperfontsize " << fontsize << '\n';
691
692         spacing().writeFile(os);
693
694         os << "\\papersize " << string_papersize[papersize]
695            << "\n\\use_geometry " << convert<string>(use_geometry)
696            << "\n\\use_amsmath " << use_amsmath
697            << "\n\\use_esint " << use_esint
698            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
699            << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
700            << "\n\\paperorientation " << string_orientation[orientation]
701            << '\n';
702
703         BranchList::const_iterator it = branchlist().begin();
704         BranchList::const_iterator end = branchlist().end();
705         for (; it != end; ++it) {
706                 os << "\\branch " << to_utf8(it->getBranch())
707                    << "\n\\selected " << it->getSelected()
708                    << "\n\\color " << lyx::X11hexname(it->getColor())
709                    << "\n\\end_branch"
710                    << "\n";
711         }
712
713         if (!paperwidth.empty())
714                 os << "\\paperwidth "
715                    << VSpace(paperwidth).asLyXCommand() << '\n';
716         if (!paperheight.empty())
717                 os << "\\paperheight "
718                    << VSpace(paperheight).asLyXCommand() << '\n';
719         if (!leftmargin.empty())
720                 os << "\\leftmargin "
721                    << VSpace(leftmargin).asLyXCommand() << '\n';
722         if (!topmargin.empty())
723                 os << "\\topmargin "
724                    << VSpace(topmargin).asLyXCommand() << '\n';
725         if (!rightmargin.empty())
726                 os << "\\rightmargin "
727                    << VSpace(rightmargin).asLyXCommand() << '\n';
728         if (!bottommargin.empty())
729                 os << "\\bottommargin "
730                    << VSpace(bottommargin).asLyXCommand() << '\n';
731         if (!headheight.empty())
732                 os << "\\headheight "
733                    << VSpace(headheight).asLyXCommand() << '\n';
734         if (!headsep.empty())
735                 os << "\\headsep "
736                    << VSpace(headsep).asLyXCommand() << '\n';
737         if (!footskip.empty())
738                 os << "\\footskip "
739                    << VSpace(footskip).asLyXCommand() << '\n';
740         os << "\\secnumdepth " << secnumdepth
741            << "\n\\tocdepth " << tocdepth
742            << "\n\\paragraph_separation "
743            << string_paragraph_separation[paragraph_separation]
744            << "\n\\defskip " << getDefSkip().asLyXCommand()
745            << "\n\\quotes_language "
746            << string_quotes_language[quotes_language]
747            << "\n\\papercolumns " << columns
748            << "\n\\papersides " << sides
749            << "\n\\paperpagestyle " << pagestyle << '\n';
750         if (!listings_params.empty())
751                 os << "\\listings_params \"" <<
752                         InsetListingsParams(listings_params).encodedString() << "\"\n";
753         for (int i = 0; i < 4; ++i) {
754                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
755                         if (user_defined_bullet(i).getFont() != -1) {
756                                 os << "\\bullet " << i << " "
757                                    << user_defined_bullet(i).getFont() << " "
758                                    << user_defined_bullet(i).getCharacter() << " "
759                                    << user_defined_bullet(i).getSize() << "\n";
760                         }
761                         else {
762                                 // FIXME UNICODE
763                                 os << "\\bulletLaTeX " << i << " \""
764                                    << lyx::to_ascii(user_defined_bullet(i).getText())
765                                    << "\"\n";
766                         }
767                 }
768         }
769
770         os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
771         os << "\\output_changes " << convert<string>(outputChanges) << "\n";
772
773         AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
774         AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
775         for (; a_it != a_end; ++a_it) {
776                 os << "\\author " << a_it->second << "\n";
777         }
778 }
779
780
781 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
782                               TexRow & texrow) const
783 {
784         os << "\\documentclass";
785
786         TextClass const & tclass = getTextClass();
787
788         ostringstream clsoptions; // the document class options.
789
790         if (tokenPos(tclass.opt_fontsize(),
791                      '|', fontsize) >= 0) {
792                 // only write if existing in list (and not default)
793                 clsoptions << fontsize << "pt,";
794         }
795
796         // custom, A3, B3 and B4 paper sizes need geometry
797         bool nonstandard_papersize = papersize == PAPER_B3
798                 || papersize == PAPER_B4
799                 || papersize == PAPER_A3
800                 || papersize == PAPER_CUSTOM;
801
802         if (!use_geometry) {
803                 switch (papersize) {
804                 case PAPER_A4:
805                         clsoptions << "a4paper,";
806                         break;
807                 case PAPER_USLETTER:
808                         clsoptions << "letterpaper,";
809                         break;
810                 case PAPER_A5:
811                         clsoptions << "a5paper,";
812                         break;
813                 case PAPER_B5:
814                         clsoptions << "b5paper,";
815                         break;
816                 case PAPER_USEXECUTIVE:
817                         clsoptions << "executivepaper,";
818                         break;
819                 case PAPER_USLEGAL:
820                         clsoptions << "legalpaper,";
821                         break;
822                 case PAPER_DEFAULT:
823                 case PAPER_A3:
824                 case PAPER_B3:
825                 case PAPER_B4:
826                 case PAPER_CUSTOM:
827                         break;
828                 }
829         }
830
831         // if needed
832         if (sides != tclass.sides()) {
833                 switch (sides) {
834                 case TextClass::OneSide:
835                         clsoptions << "oneside,";
836                         break;
837                 case TextClass::TwoSides:
838                         clsoptions << "twoside,";
839                         break;
840                 }
841         }
842
843         // if needed
844         if (columns != tclass.columns()) {
845                 if (columns == 2)
846                         clsoptions << "twocolumn,";
847                 else
848                         clsoptions << "onecolumn,";
849         }
850
851         if (!use_geometry
852             && orientation == ORIENTATION_LANDSCAPE)
853                 clsoptions << "landscape,";
854
855         // language should be a parameter to \documentclass
856         if (language->babel() == "hebrew"
857             && default_language->babel() != "hebrew")
858                 // This seems necessary
859                 features.useLanguage(default_language);
860
861         ostringstream language_options;
862         bool const use_babel = features.useBabel();
863         if (use_babel) {
864                 language_options << features.getLanguages();
865                 if (!language->babel().empty()) {
866                         if (!language_options.str().empty())
867                                 language_options << ',';
868                         language_options << language->babel();
869                 }
870                 if (lyxrc.language_global_options && !language_options.str().empty())
871                         clsoptions << language_options.str() << ',';
872         }
873
874         // the user-defined options
875         if (!options.empty()) {
876                 clsoptions << options << ',';
877         }
878
879         string strOptions(clsoptions.str());
880         if (!strOptions.empty()) {
881                 strOptions = rtrim(strOptions, ",");
882                 // FIXME UNICODE
883                 os << '[' << from_utf8(strOptions) << ']';
884         }
885
886         os << '{' << from_ascii(tclass.latexname()) << "}\n";
887         texrow.newline();
888         // end of \documentclass defs
889
890         // font selection must be done before loading fontenc.sty
891         string const fonts =
892                 loadFonts(fontsRoman, fontsSans,
893                           fontsTypewriter, fontsSC, fontsOSF,
894                           fontsSansScale, fontsTypewriterScale);
895         if (!fonts.empty()) {
896                 os << from_ascii(fonts);
897                 texrow.newline();
898         }
899         if (fontsDefaultFamily != "default")
900                 os << "\\renewcommand{\\familydefault}{\\"
901                    << from_ascii(fontsDefaultFamily) << "}\n";
902         // this one is not per buffer
903         if (lyxrc.fontenc != "default") {
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";
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