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