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