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