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