replace most &dquot;...&dquot; by <...>
[lyx.git] / src / bufferparams.C
blob2b5b05455f49f3da5ac2a036dd8a49a300048a59
1 /**
2  * \file bufferparams.C
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  */
16 #include <config.h>
18 #include "bufferparams.h"
20 #include "author.h"
21 #include "BranchList.h"
22 #include "Bullet.h"
23 #include "debug.h"
24 #include "encoding.h"
25 #include "gettext.h"
26 #include "language.h"
27 #include "LaTeXFeatures.h"
28 #include "LColor.h"
29 #include "lyxlex.h"
30 #include "lyxrc.h"
31 #include "lyxtextclasslist.h"
32 #include "outputparams.h"
33 #include "tex-strings.h"
34 #include "Spacing.h"
35 #include "texrow.h"
36 #include "vspace.h"
38 #include "frontends/Alert.h"
40 #include "support/lyxalgo.h" // for lyx::count
41 #include "support/tostr.h"
42 #include "support/translator.h"
44 #include <boost/array.hpp>
46 #include <sstream>
48 namespace support = lyx::support;
49 using lyx::support::bformat;
50 using lyx::support::rtrim;
51 using lyx::support::tokenPos;
53 using std::endl;
54 using std::string;
55 using std::istringstream;
56 using std::ostream;
57 using std::ostringstream;
58 using std::pair;
60 namespace biblio = lyx::biblio;
63 // Local translators
64 namespace {
66 // Paragraph separation
67 typedef Translator<std::string, BufferParams::PARSEP> ParSepTranslator;
70 ParSepTranslator const init_parseptranslator() {
71         ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
72         translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
73         return translator;
77 ParSepTranslator const & parseptranslator() {
78         static ParSepTranslator translator = init_parseptranslator();
79         return translator;
82 // Quotes language
83 typedef Translator<std::string, InsetQuotes::quote_language> QuotesLangTranslator;
86 QuotesLangTranslator const init_quoteslangtranslator() {
87         QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
88         translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
89         translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
90         translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
91         translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
92         translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
93         return translator;
97 QuotesLangTranslator const & quoteslangtranslator() {
98         static QuotesLangTranslator translator = init_quoteslangtranslator();
99         return translator;
102 // Quote times
103 typedef Translator<int, InsetQuotes::quote_times> QuotesTimesTranslator;
106 QuotesTimesTranslator const init_quotestimestranslator() {
107         QuotesTimesTranslator translator(1, InsetQuotes::SingleQ);
108         translator.addPair(2, InsetQuotes::DoubleQ);
109         return translator;
113 QuotesTimesTranslator const & quotestimestranslator() {
114         static QuotesTimesTranslator translator = init_quotestimestranslator();
115         return translator;
118 // Paper size
119 typedef Translator<std::string, VMARGIN_PAPER_TYPE> PaperSizeTranslator;
122 PaperSizeTranslator const init_papersizetranslator() {
123         PaperSizeTranslator translator(string_papersize[0], VM_PAPER_DEFAULT);
124         translator.addPair(string_papersize[1], VM_PAPER_CUSTOM);
125         translator.addPair(string_papersize[2], VM_PAPER_USLETTER);
126         translator.addPair(string_papersize[3], VM_PAPER_USLEGAL);
127         translator.addPair(string_papersize[4], VM_PAPER_USEXECUTIVE);
128         translator.addPair(string_papersize[5], VM_PAPER_A3);
129         translator.addPair(string_papersize[6], VM_PAPER_A4);
130         translator.addPair(string_papersize[7], VM_PAPER_A5);
131         translator.addPair(string_papersize[8], VM_PAPER_B3);
132         translator.addPair(string_papersize[9], VM_PAPER_B4);
133         translator.addPair(string_papersize[10], VM_PAPER_B5);
134         return translator;
138 PaperSizeTranslator const & papersizetranslator() {
139         static PaperSizeTranslator translator = init_papersizetranslator();
140         return translator;
143 // Paper packages
144 typedef Translator<std::string, PAPER_PACKAGES> PaperPackagesTranslator;
147 PaperPackagesTranslator const init_paperpackagestranslator() {
148         PaperPackagesTranslator translator(string_paperpackages[0], PACKAGE_NONE);
149         translator.addPair(string_paperpackages[1], PACKAGE_A4);
150         translator.addPair(string_paperpackages[2], PACKAGE_A4WIDE);
151         translator.addPair(string_paperpackages[3], PACKAGE_WIDEMARGINSA4);
152         return translator;
156 PaperPackagesTranslator const & paperpackagestranslator() {
157         static PaperPackagesTranslator translator = init_paperpackagestranslator();
158         return translator;
162 // Paper orientation
163 typedef Translator<std::string, PAPER_ORIENTATION> PaperOrientationTranslator;
166 PaperOrientationTranslator const init_paperorientationtranslator() {
167         PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
168         translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
169         return translator;
173 PaperOrientationTranslator const & paperorientationtranslator() {
174         static PaperOrientationTranslator translator = init_paperorientationtranslator();
175         return translator;
179 // Page sides
180 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
183 SidesTranslator const init_sidestranslator() {
184         SidesTranslator translator(1, LyXTextClass::OneSide);
185         translator.addPair(2, LyXTextClass::TwoSides);
186         return translator;
190 SidesTranslator const & sidestranslator() {
191         static SidesTranslator translator = init_sidestranslator();
192         return translator;
197 // AMS
198 typedef Translator<int, BufferParams::AMS> AMSTranslator;
201 AMSTranslator const init_amstranslator() {
202         AMSTranslator translator(0, BufferParams::AMS_OFF);
203         translator.addPair(1, BufferParams::AMS_AUTO);
204         translator.addPair(2, BufferParams::AMS_ON);
205         return translator;
209 AMSTranslator const & amstranslator() {
210         static AMSTranslator translator = init_amstranslator();
211         return translator;
216 // Cite engine
217 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
220 CiteEngineTranslator const init_citeenginetranslator() {
221         CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
222         translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
223         translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
224         translator.addPair("jurabib", biblio::ENGINE_JURABIB);
225         return translator;
229 CiteEngineTranslator const & citeenginetranslator() {
230         static CiteEngineTranslator translator = init_citeenginetranslator();
231         return translator;
235 // Spacing
236 typedef Translator<string, Spacing::Space> SpaceTranslator;
239 SpaceTranslator const init_spacetranslator() {
240         SpaceTranslator translator("default", Spacing::Default);
241         translator.addPair("single", Spacing::Single);
242         translator.addPair("onehalf", Spacing::Onehalf);
243         translator.addPair("double", Spacing::Double);
244         return translator;
248 SpaceTranslator const & spacetranslator() {
249         static SpaceTranslator translator = init_spacetranslator();
250         return translator;
253 // ends annonym namespace
257 struct BufferParams::Impl
259         Impl();
261         AuthorList authorlist;
262         BranchList branchlist;
263         boost::array<Bullet, 4> temp_bullets;
264         boost::array<Bullet, 4> user_defined_bullets;
265         Spacing spacing;
266         /** This is the amount of space used for paragraph_separation "skip",
267          * and for detached paragraphs in "indented" documents.
268          */
269         VSpace defskip;
273 BufferParams::Impl::Impl()
274         : defskip(VSpace::MEDSKIP)
276         // set initial author
277         authorlist.record(Author(lyxrc.user_name, lyxrc.user_email));
281 BufferParams::Impl *
282 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
284         return new BufferParams::Impl(*ptr);
288 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
290         delete ptr;
294 BufferParams::BufferParams()
295         : // Initialize textclass to point to article. if `first' is
296           // true in the returned pair, then `second' is the textclass
297           // number; if it is false, second is 0. In both cases, second
298           // is what we want.
299         textclass(textclasslist.NumberOfClass("article").second),
300         pimpl_(new Impl)
302         paragraph_separation = PARSEP_INDENT;
303         quotes_language = InsetQuotes::EnglishQ;
304         quotes_times = InsetQuotes::DoubleQ;
305         fontsize = "default";
307         /*  PaperLayout */
308         papersize = PAPER_DEFAULT;
309         papersize2 = VM_PAPER_DEFAULT; /* DEFAULT */
310         paperpackage = PACKAGE_NONE;
311         orientation = ORIENTATION_PORTRAIT;
312         use_geometry = false;
313         use_amsmath = AMS_AUTO;
314         cite_engine = biblio::ENGINE_BASIC;
315         use_bibtopic = false;
316         tracking_changes = false;
317         secnumdepth = 3;
318         tocdepth = 3;
319         language = default_language;
320         fonts = "default";
321         inputenc = "auto";
322         graphicsDriver = "default";
323         sides = LyXTextClass::OneSide;
324         columns = 1;
325         pagestyle = "default";
326         compressed = false;
327         for (int iter = 0; iter < 4; ++iter) {
328                 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
329                 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
330         }
334 BufferParams::~BufferParams()
338 AuthorList & BufferParams::authors()
340         return pimpl_->authorlist;
344 AuthorList const & BufferParams::authors() const
346         return pimpl_->authorlist;
350 BranchList & BufferParams::branchlist()
352         return pimpl_->branchlist;
356 BranchList const & BufferParams::branchlist() const
358         return pimpl_->branchlist;
362 Bullet & BufferParams::temp_bullet(lyx::size_type index)
364         BOOST_ASSERT(index < 4);
365         return pimpl_->temp_bullets[index];
369 Bullet const & BufferParams::temp_bullet(lyx::size_type index) const
371         BOOST_ASSERT(index < 4);
372         return pimpl_->temp_bullets[index];
376 Bullet & BufferParams::user_defined_bullet(lyx::size_type index)
378         BOOST_ASSERT(index < 4);
379         return pimpl_->user_defined_bullets[index];
383 Bullet const & BufferParams::user_defined_bullet(lyx::size_type index) const
385         BOOST_ASSERT(index < 4);
386         return pimpl_->user_defined_bullets[index];
390 Spacing & BufferParams::spacing()
392         return pimpl_->spacing;
396 Spacing const & BufferParams::spacing() const
398         return pimpl_->spacing;
402 VSpace const & BufferParams::getDefSkip() const
404         return pimpl_->defskip;
408 void BufferParams::setDefSkip(VSpace const & vs)
410         pimpl_->defskip = vs;
414 string const BufferParams::readToken(LyXLex & lex, string const & token)
416         if (token == "\\textclass") {
417                 lex.next();
418                 string const classname = lex.getString();
419                 pair<bool, lyx::textclass_type> pp =
420                         textclasslist.NumberOfClass(classname);
421                 if (pp.first) {
422                         textclass = pp.second;
423                 } else {
424                         textclass = 0;
425                         return classname;
426                 }
427                 if (!getLyXTextClass().isTeXClassAvailable()) {
428                         string msg = bformat(_("The document uses a missing "
429                                 "TeX class \"%1$s\".\n"), classname);
430                         Alert::warning(_("Document class not available"),
431                                        msg + _("LyX will not be able to produce output."));
432                 }
433         } else if (token == "\\begin_preamble") {
434                 readPreamble(lex);
435         } else if (token == "\\options") {
436                 lex.eatLine();
437                 options = lex.getString();
438         } else if (token == "\\language") {
439                 readLanguage(lex);
440         } else if (token == "\\inputencoding") {
441                 lex >> inputenc;
442         } else if (token == "\\graphics") {
443                 readGraphicsDriver(lex);
444         } else if (token == "\\fontscheme") {
445                 lex >> fonts;
446         } else if (token == "\\paragraph_separation") {
447                 string parsep;
448                 lex >> parsep;
449                 paragraph_separation = parseptranslator().find(parsep);
450         } else if (token == "\\defskip") {
451                 lex.next();
452                 pimpl_->defskip = VSpace(lex.getString());
453         } else if (token == "\\quotes_language") {
454                 string quotes_lang;
455                 lex >> quotes_lang;
456                 quotes_language = quoteslangtranslator().find(quotes_lang);
457         } else if (token == "\\quotes_times") {
458                 int qtimes;
459                 lex >> qtimes;
460                 quotes_times = quotestimestranslator().find(qtimes);
461         } else if (token == "\\papersize") {
462                 string ppsize;
463                 lex >> ppsize;
464                 papersize2 = papersizetranslator().find(ppsize);
465         } else if (token == "\\paperpackage") {
466                 string ppackage;
467                 lex >> ppackage;
468                 paperpackage = paperpackagestranslator().find(ppackage);
469         } else if (token == "\\use_geometry") {
470                 lex >> use_geometry;
471         } else if (token == "\\use_amsmath") {
472                 int use_ams;
473                 lex >> use_ams;
474                 use_amsmath = amstranslator().find(use_ams);
475         } else if (token == "\\cite_engine") {
476                 string engine;
477                 lex >> engine;
478                 cite_engine = citeenginetranslator().find(engine);
479         } else if (token == "\\use_bibtopic") {
480                 lex >> use_bibtopic;
481         } else if (token == "\\tracking_changes") {
482                 lex >> tracking_changes;
483         } else if (token == "\\branch") {
484                 lex.next();
485                 string branch = lex.getString();
486                 branchlist().add(branch);
487                 while (true) {
488                         lex.next();
489                         string const tok = lex.getString();
490                         if (tok == "\\end_branch")
491                                 break;
492                         Branch * branch_ptr = branchlist().find(branch);
493                         if (tok == "\\selected") {
494                                 lex.next();
495                                 if (branch_ptr)
496                                         branch_ptr->setSelected(lex.getInteger());
497                         }
498                         // not yet operational
499                         if (tok == "\\color") {
500                                 lex.eatLine();
501                                 string color = lex.getString();
502                                 if (branch_ptr)
503                                         branch_ptr->setColor(color);
504                                 // Update also the LColor table:
505                                 if (color == "none")
506                                         color = lcolor.getX11Name(LColor::background);
507                                 lcolor.setColor(branch, color);
509                         }
510                 }
511         } else if (token == "\\author") {
512                 lex.eatLine();
513                 istringstream ss(lex.getString());
514                 Author a;
515                 ss >> a;
516                 author_map.push_back(pimpl_->authorlist.record(a));
517         } else if (token == "\\paperorientation") {
518                 string orient;
519                 lex >> orient;
520                 orientation = paperorientationtranslator().find(orient);
521         } else if (token == "\\paperwidth") {
522                 lex >> paperwidth;
523         } else if (token == "\\paperheight") {
524                 lex >> paperheight;
525         } else if (token == "\\leftmargin") {
526                 lex >> leftmargin;
527         } else if (token == "\\topmargin") {
528                 lex >> topmargin;
529         } else if (token == "\\rightmargin") {
530                 lex >> rightmargin;
531         } else if (token == "\\bottommargin") {
532                 lex >> bottommargin;
533         } else if (token == "\\headheight") {
534                 lex >> headheight;
535         } else if (token == "\\headsep") {
536                 lex >> headsep;
537         } else if (token == "\\footskip") {
538                 lex >> footskip;
539         } else if (token == "\\paperfontsize") {
540                 lex >> fontsize;
541         } else if (token == "\\papercolumns") {
542                 lex >> columns;
543         } else if (token == "\\papersides") {
544                 int psides;
545                 lex >> psides;
546                 sides = sidestranslator().find(psides);
547         } else if (token == "\\paperpagestyle") {
548                 lex >> pagestyle;
549         } else if (token == "\\bullet") {
550                 readBullets(lex);
551         } else if (token == "\\bulletLaTeX") {
552                 readBulletsLaTeX(lex);
553         } else if (token == "\\secnumdepth") {
554                 lex >> secnumdepth;
555         } else if (token == "\\tocdepth") {
556                 lex >> tocdepth;
557         } else if (token == "\\spacing") {
558                 string nspacing;
559                 lex >> nspacing;
560                 float tmp_val = 0.0;
561                 if (nspacing == "other") {
562                         lex >> tmp_val;
563                 }
564                 spacing().set(spacetranslator().find(nspacing), tmp_val);
565         } else if (token == "\\float_placement") {
566                 lex >> float_placement;
567         } else {
568                 return token;
569         }
571         return string();
575 void BufferParams::writeFile(ostream & os) const
577         // The top of the file is written by the buffer.
578         // Prints out the buffer info into the .lyx file given by file
580         // the textclass
581         os << "\\textclass " << textclasslist[textclass].name() << '\n';
583         // then the the preamble
584         if (!preamble.empty()) {
585                 // remove '\n' from the end of preamble
586                 string const tmppreamble = rtrim(preamble, "\n");
587                 os << "\\begin_preamble\n"
588                    << tmppreamble
589                    << "\n\\end_preamble\n";
590         }
592         /* the options */
593         if (!options.empty()) {
594                 os << "\\options " << options << '\n';
595         }
597         /* then the text parameters */
598         if (language != ignore_language)
599                 os << "\\language " << language->lang() << '\n';
600         os << "\\inputencoding " << inputenc
601            << "\n\\fontscheme " << fonts
602            << "\n\\graphics " << graphicsDriver << '\n';
604         if (!float_placement.empty()) {
605                 os << "\\float_placement " << float_placement << '\n';
606         }
607         os << "\\paperfontsize " << fontsize << '\n';
609         spacing().writeFile(os);
611         os << "\\papersize " << string_papersize[papersize2]
612            << "\n\\paperpackage " << string_paperpackages[paperpackage]
613            << "\n\\use_geometry " << tostr(use_geometry)
614            << "\n\\use_amsmath " << use_amsmath
615            << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
616            << "\n\\use_bibtopic " << tostr(use_bibtopic)
617            << "\n\\paperorientation " << string_orientation[orientation]
618            << '\n';
620         std::list<Branch>::const_iterator it = branchlist().begin();
621         std::list<Branch>::const_iterator end = branchlist().end();
622         for (; it != end; ++it) {
623                 os << "\\branch " << it->getBranch()
624                    << "\n\\selected " << it->getSelected()
625                    << "\n\\color " << it->getColor()
626                    << "\n\\end_branch"
627                    << "\n";
628         }
630         if (!paperwidth.empty())
631                 os << "\\paperwidth "
632                    << VSpace(paperwidth).asLyXCommand() << '\n';
633         if (!paperheight.empty())
634                 os << "\\paperheight "
635                    << VSpace(paperheight).asLyXCommand() << '\n';
636         if (!leftmargin.empty())
637                 os << "\\leftmargin "
638                    << VSpace(leftmargin).asLyXCommand() << '\n';
639         if (!topmargin.empty())
640                 os << "\\topmargin "
641                    << VSpace(topmargin).asLyXCommand() << '\n';
642         if (!rightmargin.empty())
643                 os << "\\rightmargin "
644                    << VSpace(rightmargin).asLyXCommand() << '\n';
645         if (!bottommargin.empty())
646                 os << "\\bottommargin "
647                    << VSpace(bottommargin).asLyXCommand() << '\n';
648         if (!headheight.empty())
649                 os << "\\headheight "
650                    << VSpace(headheight).asLyXCommand() << '\n';
651         if (!headsep.empty())
652                 os << "\\headsep "
653                    << VSpace(headsep).asLyXCommand() << '\n';
654         if (!footskip.empty())
655                 os << "\\footskip "
656                    << VSpace(footskip).asLyXCommand() << '\n';
657         os << "\\secnumdepth " << secnumdepth
658            << "\n\\tocdepth " << tocdepth
659            << "\n\\paragraph_separation "
660            << string_paragraph_separation[paragraph_separation]
661            << "\n\\defskip " << getDefSkip().asLyXCommand()
662            << "\n\\quotes_language "
663            << string_quotes_language[quotes_language] << '\n'
664            << "\\quotes_times "
665            << quotestimestranslator().find(quotes_times)
666            << "\n\\papercolumns " << columns
667            << "\n\\papersides " << sides
668            << "\n\\paperpagestyle " << pagestyle << '\n';
669         for (int i = 0; i < 4; ++i) {
670                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
671                         if (user_defined_bullet(i).getFont() != -1) {
672                                 os << "\\bullet " << i << " "
673                                    << user_defined_bullet(i).getFont() << " "
674                                    << user_defined_bullet(i).getCharacter() << " "
675                                    << user_defined_bullet(i).getSize() << "\n";
676                         }
677                         else {
678                                 os << "\\bulletLaTeX " << i << " \""
679                                    << user_defined_bullet(i).getText()
680                                    << "\"\n";
681                         }
682                 }
683         }
685         os << "\\tracking_changes " << tostr(tracking_changes) << "\n";
687         if (tracking_changes) {
688                 AuthorList::Authors::const_iterator it = pimpl_->authorlist.begin();
689                 AuthorList::Authors::const_iterator end = pimpl_->authorlist.end();
690                 for (; it != end; ++it) {
691                         os << "\\author " << it->second << "\n";
692                 }
693         }
697 bool BufferParams::writeLaTeX(ostream & os, LaTeXFeatures & features,
698                               TexRow & texrow) const
700         os << "\\documentclass";
702         LyXTextClass const & tclass = getLyXTextClass();
704         ostringstream clsoptions; // the document class options.
706         if (tokenPos(tclass.opt_fontsize(),
707                      '|', fontsize) >= 0) {
708                 // only write if existing in list (and not default)
709                 clsoptions << fontsize << "pt,";
710         }
713         if (!use_geometry &&
714             (paperpackage == PACKAGE_NONE)) {
715                 switch (papersize) {
716                 case PAPER_A3PAPER:
717                         clsoptions << "a3paper,";
718                         break;
719                 case PAPER_A4PAPER:
720                         clsoptions << "a4paper,";
721                         break;
722                 case PAPER_USLETTER:
723                         clsoptions << "letterpaper,";
724                         break;
725                 case PAPER_A5PAPER:
726                         clsoptions << "a5paper,";
727                         break;
728                 case PAPER_B5PAPER:
729                         clsoptions << "b5paper,";
730                         break;
731                 case PAPER_EXECUTIVEPAPER:
732                         clsoptions << "executivepaper,";
733                         break;
734                 case PAPER_LEGALPAPER:
735                         clsoptions << "legalpaper,";
736                         break;
737                 case PAPER_DEFAULT:
738                         break;
739                 }
740         }
742         // if needed
743         if (sides != tclass.sides()) {
744                 switch (sides) {
745                 case LyXTextClass::OneSide:
746                         clsoptions << "oneside,";
747                         break;
748                 case LyXTextClass::TwoSides:
749                         clsoptions << "twoside,";
750                         break;
751                 }
752         }
754         // if needed
755         if (columns != tclass.columns()) {
756                 if (columns == 2)
757                         clsoptions << "twocolumn,";
758                 else
759                         clsoptions << "onecolumn,";
760         }
762         if (!use_geometry
763             && orientation == ORIENTATION_LANDSCAPE)
764                 clsoptions << "landscape,";
766         // language should be a parameter to \documentclass
767         if (language->babel() == "hebrew"
768             && default_language->babel() != "hebrew")
769                 // This seems necessary
770                 features.useLanguage(default_language);
772         ostringstream language_options;
773         bool const use_babel = features.useBabel();
774         if (use_babel) {
775                 language_options << features.getLanguages();
776                 language_options << language->babel();
777                 if (lyxrc.language_global_options)
778                         clsoptions << language_options.str() << ',';
779         }
781         // the user-defined options
782         if (!options.empty()) {
783                 clsoptions << options << ',';
784         }
786         string strOptions(clsoptions.str());
787         if (!strOptions.empty()) {
788                 strOptions = rtrim(strOptions, ",");
789                 os << '[' << strOptions << ']';
790         }
792         os << '{' << tclass.latexname() << "}\n";
793         texrow.newline();
794         // end of \documentclass defs
796         // font selection must be done before loading fontenc.sty
797         // The ae package is not needed when using OT1 font encoding.
798         if (fonts != "default" &&
799             (fonts != "ae" || lyxrc.fontenc != "default")) {
800                 os << "\\usepackage{" << fonts << "}\n";
801                 texrow.newline();
802                 if (fonts == "ae") {
803                         os << "\\usepackage{aecompl}\n";
804                         texrow.newline();
805                 }
806         }
807         // this one is not per buffer
808         if (lyxrc.fontenc != "default") {
809                 os << "\\usepackage[" << lyxrc.fontenc
810                    << "]{fontenc}\n";
811                 texrow.newline();
812         }
814         if (inputenc == "auto") {
815                 string const doc_encoding =
816                         language->encoding()->LatexName();
818                 // Create a list with all the input encodings used
819                 // in the document
820                 std::set<string> encodings =
821                         features.getEncodingSet(doc_encoding);
823                 os << "\\usepackage[";
824                 std::copy(encodings.begin(), encodings.end(),
825                           std::ostream_iterator<string>(os, ","));
826                 os << doc_encoding << "]{inputenc}\n";
827                 texrow.newline();
828         } else if (inputenc != "default") {
829                 os << "\\usepackage[" << inputenc
830                    << "]{inputenc}\n";
831                 texrow.newline();
832         }
834         // At the very beginning the text parameters.
835         if (paperpackage != PACKAGE_NONE) {
836                 switch (paperpackage) {
837                 case PACKAGE_NONE:
838                         break;
839                 case PACKAGE_A4:
840                         os << "\\usepackage{a4}\n";
841                         texrow.newline();
842                         break;
843                 case PACKAGE_A4WIDE:
844                         os << "\\usepackage{a4wide}\n";
845                         texrow.newline();
846                         break;
847                 case PACKAGE_WIDEMARGINSA4:
848                         os << "\\usepackage[widemargins]{a4}\n";
849                         texrow.newline();
850                         break;
851                 }
852         }
853         if (use_geometry) {
854                 os << "\\usepackage{geometry}\n";
855                 texrow.newline();
856                 os << "\\geometry{verbose";
857                 if (orientation == ORIENTATION_LANDSCAPE)
858                         os << ",landscape";
859                 switch (papersize2) {
860                 case VM_PAPER_CUSTOM:
861                         if (!paperwidth.empty())
862                                 os << ",paperwidth="
863                                    << paperwidth;
864                         if (!paperheight.empty())
865                                 os << ",paperheight="
866                                    << paperheight;
867                         break;
868                 case VM_PAPER_USLETTER:
869                         os << ",letterpaper";
870                         break;
871                 case VM_PAPER_USLEGAL:
872                         os << ",legalpaper";
873                         break;
874                 case VM_PAPER_USEXECUTIVE:
875                         os << ",executivepaper";
876                         break;
877                 case VM_PAPER_A3:
878                         os << ",a3paper";
879                         break;
880                 case VM_PAPER_A4:
881                         os << ",a4paper";
882                         break;
883                 case VM_PAPER_A5:
884                         os << ",a5paper";
885                         break;
886                 case VM_PAPER_B3:
887                         os << ",b3paper";
888                         break;
889                 case VM_PAPER_B4:
890                         os << ",b4paper";
891                         break;
892                 case VM_PAPER_B5:
893                         os << ",b5paper";
894                         break;
895                 default:
896                                 // default papersize ie VM_PAPER_DEFAULT
897                         switch (lyxrc.default_papersize) {
898                         case PAPER_DEFAULT: // keep compiler happy
899                         case PAPER_USLETTER:
900                                 os << ",letterpaper";
901                                 break;
902                         case PAPER_LEGALPAPER:
903                                 os << ",legalpaper";
904                                 break;
905                         case PAPER_EXECUTIVEPAPER:
906                                 os << ",executivepaper";
907                                 break;
908                         case PAPER_A3PAPER:
909                                 os << ",a3paper";
910                                 break;
911                         case PAPER_A4PAPER:
912                                 os << ",a4paper";
913                                 break;
914                         case PAPER_A5PAPER:
915                                 os << ",a5paper";
916                                 break;
917                         case PAPER_B5PAPER:
918                                 os << ",b5paper";
919                                 break;
920                         }
921                 }
922                 if (!topmargin.empty())
923                         os << ",tmargin=" << topmargin;
924                 if (!bottommargin.empty())
925                         os << ",bmargin=" << bottommargin;
926                 if (!leftmargin.empty())
927                         os << ",lmargin=" << leftmargin;
928                 if (!rightmargin.empty())
929                         os << ",rmargin=" << rightmargin;
930                 if (!headheight.empty())
931                         os << ",headheight=" << headheight;
932                 if (!headsep.empty())
933                         os << ",headsep=" << headsep;
934                 if (!footskip.empty())
935                         os << ",footskip=" << footskip;
936                 os << "}\n";
937                 texrow.newline();
938         }
940         if (tokenPos(tclass.opt_pagestyle(),
941                      '|', pagestyle) >= 0) {
942                 if (pagestyle == "fancy") {
943                         os << "\\usepackage{fancyhdr}\n";
944                         texrow.newline();
945                 }
946                 os << "\\pagestyle{" << pagestyle << "}\n";
947                 texrow.newline();
948         }
950         if (secnumdepth != tclass.secnumdepth()) {
951                 os << "\\setcounter{secnumdepth}{"
952                    << secnumdepth
953                    << "}\n";
954                 texrow.newline();
955         }
956         if (tocdepth != tclass.tocdepth()) {
957                 os << "\\setcounter{tocdepth}{"
958                    << tocdepth
959                    << "}\n";
960                 texrow.newline();
961         }
963         if (paragraph_separation) {
964                 switch (getDefSkip().kind()) {
965                 case VSpace::SMALLSKIP:
966                         os << "\\setlength\\parskip{\\smallskipamount}\n";
967                         break;
968                 case VSpace::MEDSKIP:
969                         os << "\\setlength\\parskip{\\medskipamount}\n";
970                         break;
971                 case VSpace::BIGSKIP:
972                         os << "\\setlength\\parskip{\\bigskipamount}\n";
973                         break;
974                 case VSpace::LENGTH:
975                         os << "\\setlength\\parskip{"
976                            << getDefSkip().length().asLatexString()
977                            << "}\n";
978                         break;
979                 default: // should never happen // Then delete it.
980                         os << "\\setlength\\parskip{\\medskipamount}\n";
981                         break;
982                 }
983                 texrow.newline();
985                 os << "\\setlength\\parindent{0pt}\n";
986                 texrow.newline();
987         }
989         // If we use jurabib, we have to call babel here.
990         if (use_babel && features.isRequired("jurabib")) {
991                 os << babelCall(language_options.str())
992                    << '\n'
993                    << features.getBabelOptions();
994                 texrow.newline();
995         }
997         // Now insert the LyX specific LaTeX commands...
999         // The optional packages;
1000         string lyxpreamble(features.getPackages());
1002         // this might be useful...
1003         lyxpreamble += "\n\\makeatletter\n";
1005         // Some macros LyX will need
1006         string tmppreamble(features.getMacros());
1008         if (!tmppreamble.empty()) {
1009                 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1010                         "LyX specific LaTeX commands.\n"
1011                         + tmppreamble + '\n';
1012         }
1014         // the text class specific preamble
1015         tmppreamble = features.getTClassPreamble();
1016         if (!tmppreamble.empty()) {
1017                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1018                         "Textclass specific LaTeX commands.\n"
1019                         + tmppreamble + '\n';
1020         }
1022         /* the user-defined preamble */
1023         if (!preamble.empty()) {
1024                 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1025                         "User specified LaTeX commands.\n"
1026                         + preamble + '\n';
1027         }
1029         // Itemize bullet settings need to be last in case the user
1030         // defines their own bullets that use a package included
1031         // in the user-defined preamble -- ARRae
1032         // Actually it has to be done much later than that
1033         // since some packages like frenchb make modifications
1034         // at \begin{document} time -- JMarc
1035         string bullets_def;
1036         for (int i = 0; i < 4; ++i) {
1037                 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1038                         if (bullets_def.empty())
1039                                 bullets_def="\\AtBeginDocument{\n";
1040                         bullets_def += "  \\renewcommand{\\labelitemi";
1041                         switch (i) {
1042                                 // `i' is one less than the item to modify
1043                         case 0:
1044                                 break;
1045                         case 1:
1046                                 bullets_def += 'i';
1047                                 break;
1048                         case 2:
1049                                 bullets_def += "ii";
1050                                 break;
1051                         case 3:
1052                                 bullets_def += 'v';
1053                                 break;
1054                         }
1055                         bullets_def += "}{" +
1056                                 user_defined_bullet(i).getText()
1057                                 + "}\n";
1058                 }
1059         }
1061         if (!bullets_def.empty())
1062                 lyxpreamble += bullets_def + "}\n\n";
1064         // We try to load babel late, in case it interferes
1065         // with other packages.
1066         // Jurabib has to be called after babel, though.
1067         if (use_babel && !features.isRequired("jurabib")) {
1068                 lyxpreamble += babelCall(language_options.str()) + '\n';
1069                 lyxpreamble += features.getBabelOptions();
1070         }
1072         lyxpreamble += "\\makeatother\n";
1074         // dvipost settings come after everything else
1075         if (tracking_changes) {
1076                 lyxpreamble +=
1077                         "\\dvipostlayout\n"
1078                         "\\dvipost{osstart color push Red}\n"
1079                         "\\dvipost{osend color pop}\n"
1080                         "\\dvipost{cbstart color push Blue}\n"
1081                         "\\dvipost{cbend color pop}\n";
1082         }
1084         int const nlines =
1085                 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1086         for (int j = 0; j != nlines; ++j) {
1087                 texrow.newline();
1088         }
1090         os << lyxpreamble;
1091         return use_babel;
1094 void BufferParams::setPaperStuff()
1096         papersize = PAPER_DEFAULT;
1097         char const c1 = paperpackage;
1098         if (c1 == PACKAGE_NONE) {
1099                 char const c2 = papersize2;
1100                 if (c2 == VM_PAPER_USLETTER)
1101                         papersize = PAPER_USLETTER;
1102                 else if (c2 == VM_PAPER_USLEGAL)
1103                         papersize = PAPER_LEGALPAPER;
1104                 else if (c2 == VM_PAPER_USEXECUTIVE)
1105                         papersize = PAPER_EXECUTIVEPAPER;
1106                 else if (c2 == VM_PAPER_A3)
1107                         papersize = PAPER_A3PAPER;
1108                 else if (c2 == VM_PAPER_A4)
1109                         papersize = PAPER_A4PAPER;
1110                 else if (c2 == VM_PAPER_A5)
1111                         papersize = PAPER_A5PAPER;
1112                 else if ((c2 == VM_PAPER_B3) || (c2 == VM_PAPER_B4) ||
1113                          (c2 == VM_PAPER_B5))
1114                         papersize = PAPER_B5PAPER;
1115         } else if ((c1 == PACKAGE_A4) || (c1 == PACKAGE_A4WIDE) ||
1116                    (c1 == PACKAGE_WIDEMARGINSA4))
1117                 papersize = PAPER_A4PAPER;
1121 void BufferParams::useClassDefaults()
1123         LyXTextClass const & tclass = textclasslist[textclass];
1125         sides = tclass.sides();
1126         columns = tclass.columns();
1127         pagestyle = tclass.pagestyle();
1128         options = tclass.options();
1129         secnumdepth = tclass.secnumdepth();
1130         tocdepth = tclass.tocdepth();
1134 bool BufferParams::hasClassDefaults() const
1136         LyXTextClass const & tclass = textclasslist[textclass];
1138         return (sides == tclass.sides()
1139                 && columns == tclass.columns()
1140                 && pagestyle == tclass.pagestyle()
1141                 && options == tclass.options()
1142                 && secnumdepth == tclass.secnumdepth()
1143                 && tocdepth == tclass.tocdepth());
1147 LyXTextClass const & BufferParams::getLyXTextClass() const
1149         return textclasslist[textclass];
1153 void BufferParams::readPreamble(LyXLex & lex)
1155         if (lex.getString() != "\\begin_preamble")
1156                 lyxerr << "Error (BufferParams::readPreamble):"
1157                         "consistency check failed." << endl;
1159         preamble = lex.getLongString("\\end_preamble");
1163 void BufferParams::readLanguage(LyXLex & lex)
1165         if (!lex.next()) return;
1167         string const tmptok = lex.getString();
1169         // check if tmptok is part of tex_babel in tex-defs.h
1170         language = languages.getLanguage(tmptok);
1171         if (!language) {
1172                 // Language tmptok was not found
1173                 language = default_language;
1174                 lyxerr << "Warning: Setting language `"
1175                        << tmptok << "' to `" << language->lang()
1176                        << "'." << endl;
1177         }
1181 void BufferParams::readGraphicsDriver(LyXLex & lex)
1183         if (!lex.next()) return;
1185         string const tmptok = lex.getString();
1186         // check if tmptok is part of tex_graphics in tex_defs.h
1187         int n = 0;
1188         while (true) {
1189                 string const test = tex_graphics[n++];
1191                 if (test == tmptok) {
1192                         graphicsDriver = tmptok;
1193                         break;
1194                 } else if (test == "last_item") {
1195                         lex.printError(
1196                                 "Warning: graphics driver `$$Token' not recognized!\n"
1197                                 "         Setting graphics driver to `default'.\n");
1198                         graphicsDriver = "default";
1199                         break;
1200                 }
1201         }
1205 void BufferParams::readBullets(LyXLex & lex)
1207         if (!lex.next()) return;
1209         int const index = lex.getInteger();
1210         lex.next();
1211         int temp_int = lex.getInteger();
1212         user_defined_bullet(index).setFont(temp_int);
1213         temp_bullet(index).setFont(temp_int);
1214         lex >> temp_int;
1215         user_defined_bullet(index).setCharacter(temp_int);
1216         temp_bullet(index).setCharacter(temp_int);
1217         lex >> temp_int;
1218         user_defined_bullet(index).setSize(temp_int);
1219         temp_bullet(index).setSize(temp_int);
1223 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1225         // The bullet class should be able to read this.
1226         if (!lex.next()) return;
1227         int const index = lex.getInteger();
1228         lex.next(true);
1229         string temp_str = lex.getString();
1231         user_defined_bullet(index).setText(temp_str);
1232         temp_bullet(index).setText(temp_str);
1236 string const BufferParams::paperSizeName() const
1238         char real_papersize = papersize;
1239         if (real_papersize == PAPER_DEFAULT)
1240                 real_papersize = lyxrc.default_papersize;
1242         switch (real_papersize) {
1243         case PAPER_A3PAPER:
1244                 return "a3";
1245         case PAPER_A4PAPER:
1246                 return "a4";
1247         case PAPER_A5PAPER:
1248                 return "a5";
1249         case PAPER_B5PAPER:
1250                 return "b5";
1251         case PAPER_EXECUTIVEPAPER:
1252                 return "foolscap";
1253         case PAPER_LEGALPAPER:
1254                 return "legal";
1255         case PAPER_USLETTER:
1256         default:
1257                 return "letter";
1258         }
1262 string const BufferParams::dvips_options() const
1264         string result;
1266         if (use_geometry
1267             && papersize2 == VM_PAPER_CUSTOM
1268             && !lyxrc.print_paper_dimension_flag.empty()
1269             && !paperwidth.empty()
1270             && !paperheight.empty()) {
1271                 // using a custom papersize
1272                 result = lyxrc.print_paper_dimension_flag;
1273                 result += ' ' + paperwidth;
1274                 result += ',' + paperheight;
1275         } else {
1276                 string const paper_option = paperSizeName();
1277                 if (paper_option != "letter" ||
1278                     orientation != ORIENTATION_LANDSCAPE) {
1279                         // dvips won't accept -t letter -t landscape.
1280                         // In all other cases, include the paper size
1281                         // explicitly.
1282                         result = lyxrc.print_paper_flag;
1283                         result += ' ' + paper_option;
1284                 }
1285         }
1286         if (orientation == ORIENTATION_LANDSCAPE &&
1287             papersize2 != VM_PAPER_CUSTOM)
1288                 result += ' ' + lyxrc.print_landscape_flag;
1289         return result;
1293 string const BufferParams::babelCall(string const & lang_opts) const
1295         string tmp = lyxrc.language_package;
1296         if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1297                 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1298         return tmp;