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