2 * \file BufferParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
10 * \author André Pönitz
11 * \author Martin Vermeer
13 * Full author contact details are available in file CREDITS.
18 #include "BufferParams.h"
21 #include "BranchList.h"
27 #include "LaTeXFeatures.h"
33 #include "TextClassList.h"
34 #include "OutputParams.h"
39 #include "frontends/alert.h"
41 #include "support/lyxalgo.h" // for lyx::count
42 #include "support/convert.h"
43 #include "support/Translator.h"
45 #include <boost/array.hpp>
51 using std::istringstream;
53 using std::ostringstream;
56 using lyx::support::bformat;
57 using lyx::support::rtrim;
58 using lyx::support::tokenPos;
61 static char const * const string_paragraph_separation[] = {
66 static char const * const string_quotes_language[] = {
67 "english", "swedish", "german", "polish", "french", "danish", ""
71 static char const * const string_papersize[] = {
72 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
73 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
77 static char const * const string_orientation[] = {
78 "portrait", "landscape", ""
82 static char const * const string_footnotekinds[] = {
83 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
87 static char const * const tex_graphics[] = {
88 "default", "dvips", "dvitops", "emtex",
89 "ln", "oztex", "textures", "none", ""
98 // Paragraph separation
99 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
102 ParSepTranslator const init_parseptranslator()
104 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
105 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
110 ParSepTranslator const & parseptranslator()
112 static ParSepTranslator translator = init_parseptranslator();
118 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
121 QuotesLangTranslator const init_quoteslangtranslator()
123 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
124 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
125 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
126 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
127 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
128 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
133 QuotesLangTranslator const & quoteslangtranslator()
135 static QuotesLangTranslator translator = init_quoteslangtranslator();
141 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
144 PaperSizeTranslator const init_papersizetranslator()
146 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
147 translator.addPair(string_papersize[1], PAPER_CUSTOM);
148 translator.addPair(string_papersize[2], PAPER_USLETTER);
149 translator.addPair(string_papersize[3], PAPER_USLEGAL);
150 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
151 translator.addPair(string_papersize[5], PAPER_A3);
152 translator.addPair(string_papersize[6], PAPER_A4);
153 translator.addPair(string_papersize[7], PAPER_A5);
154 translator.addPair(string_papersize[8], PAPER_B3);
155 translator.addPair(string_papersize[9], PAPER_B4);
156 translator.addPair(string_papersize[10], PAPER_B5);
161 PaperSizeTranslator const & papersizetranslator()
163 static PaperSizeTranslator translator = init_papersizetranslator();
169 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
172 PaperOrientationTranslator const init_paperorientationtranslator()
174 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
175 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
180 PaperOrientationTranslator const & paperorientationtranslator()
182 static PaperOrientationTranslator translator = init_paperorientationtranslator();
188 typedef Translator<int, TextClass::PageSides> SidesTranslator;
191 SidesTranslator const init_sidestranslator()
193 SidesTranslator translator(1, TextClass::OneSide);
194 translator.addPair(2, TextClass::TwoSides);
199 SidesTranslator const & sidestranslator()
201 static SidesTranslator translator = init_sidestranslator();
207 typedef Translator<int, BufferParams::Package> PackageTranslator;
210 PackageTranslator const init_packagetranslator()
212 PackageTranslator translator(0, BufferParams::package_off);
213 translator.addPair(1, BufferParams::package_auto);
214 translator.addPair(2, BufferParams::package_on);
219 PackageTranslator const & packagetranslator()
221 static PackageTranslator translator = init_packagetranslator();
227 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
230 CiteEngineTranslator const init_citeenginetranslator()
232 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
233 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
234 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
235 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
240 CiteEngineTranslator const & citeenginetranslator()
242 static CiteEngineTranslator translator = init_citeenginetranslator();
248 typedef Translator<string, Spacing::Space> SpaceTranslator;
251 SpaceTranslator const init_spacetranslator()
253 SpaceTranslator translator("default", Spacing::Default);
254 translator.addPair("single", Spacing::Single);
255 translator.addPair("onehalf", Spacing::Onehalf);
256 translator.addPair("double", Spacing::Double);
257 translator.addPair("other", Spacing::Other);
262 SpaceTranslator const & spacetranslator()
264 static SpaceTranslator translator = init_spacetranslator();
269 textclass_type defaultTextclass()
271 // Initialize textclass to point to article. if `first' is
272 // true in the returned pair, then `second' is the textclass
273 // number; if it is false, second is 0. In both cases, second
275 return textclasslist.numberOfClass("article").second;
281 class BufferParams::Impl
286 AuthorList authorlist;
287 BranchList branchlist;
288 boost::array<Bullet, 4> temp_bullets;
289 boost::array<Bullet, 4> user_defined_bullets;
291 /** This is the amount of space used for paragraph_separation "skip",
292 * and for detached paragraphs in "indented" documents.
298 BufferParams::Impl::Impl()
299 : defskip(VSpace::MEDSKIP)
301 // set initial author
303 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
308 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
312 return new BufferParams::Impl(*ptr);
316 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
322 BufferParams::BufferParams()
323 : textclass(defaultTextclass()), pimpl_(new Impl)
325 paragraph_separation = PARSEP_INDENT;
326 quotes_language = InsetQuotes::EnglishQ;
327 fontsize = "default";
330 papersize = PAPER_DEFAULT;
331 orientation = ORIENTATION_PORTRAIT;
332 use_geometry = false;
333 use_amsmath = package_auto;
334 use_esint = package_auto;
335 cite_engine_ = biblio::ENGINE_BASIC;
336 use_bibtopic = false;
337 trackChanges = false;
338 outputChanges = false;
341 language = default_language;
342 fontsRoman = "default";
343 fontsSans = "default";
344 fontsTypewriter = "default";
345 fontsDefaultFamily = "default";
348 fontsSansScale = 100;
349 fontsTypewriterScale = 100;
351 graphicsDriver = "default";
352 sides = TextClass::OneSide;
354 pagestyle = "default";
356 for (int iter = 0; iter < 4; ++iter) {
357 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
358 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
363 BufferParams::~BufferParams()
367 docstring const BufferParams::B_(string const & l10n) const
369 BOOST_ASSERT(language);
370 return getMessages(language->code()).get(l10n);
374 AuthorList & BufferParams::authors()
376 return pimpl_->authorlist;
380 AuthorList const & BufferParams::authors() const
382 return pimpl_->authorlist;
386 BranchList & BufferParams::branchlist()
388 return pimpl_->branchlist;
392 BranchList const & BufferParams::branchlist() const
394 return pimpl_->branchlist;
398 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
400 BOOST_ASSERT(index < 4);
401 return pimpl_->temp_bullets[index];
405 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
407 BOOST_ASSERT(index < 4);
408 return pimpl_->temp_bullets[index];
412 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
414 BOOST_ASSERT(index < 4);
415 return pimpl_->user_defined_bullets[index];
419 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
421 BOOST_ASSERT(index < 4);
422 return pimpl_->user_defined_bullets[index];
426 Spacing & BufferParams::spacing()
428 return pimpl_->spacing;
432 Spacing const & BufferParams::spacing() const
434 return pimpl_->spacing;
438 VSpace const & BufferParams::getDefSkip() const
440 return pimpl_->defskip;
444 void BufferParams::setDefSkip(VSpace const & vs)
446 pimpl_->defskip = vs;
450 string const BufferParams::readToken(Lexer & lex, string const & token)
452 if (token == "\\textclass") {
454 string const classname = lex.getString();
455 pair<bool, lyx::textclass_type> pp =
456 textclasslist.numberOfClass(classname);
458 textclass = pp.second;
460 // if text class does not exist, try to load it from filepath
461 pp = textclasslist.addTextClass(classname, filepath);
463 textclass = pp.second;
465 textclass = defaultTextclass();
469 // FIXME: isTeXClassAvailable will try to load the layout file, but will
470 // fail because of the lack of path info. Warnings will be given although
471 // the layout file will be correctly loaded later.
472 if (!getTextClass().isTeXClassAvailable()) {
473 docstring const msg =
474 bformat(_("The layout file requested by this document,\n"
476 "is not usable. This is probably because a LaTeX\n"
477 "class or style file required by it is not\n"
478 "available. See the Customization documentation\n"
479 "for more information.\n"), from_utf8(classname));
480 frontend::Alert::warning(_("Document class not available"),
481 msg + _("LyX will not be able to produce output."));
483 } else if (token == "\\begin_preamble") {
485 } else if (token == "\\options") {
487 options = lex.getString();
488 } else if (token == "\\language") {
490 } else if (token == "\\inputencoding") {
492 } else if (token == "\\graphics") {
493 readGraphicsDriver(lex);
494 } else if (token == "\\font_roman") {
496 } else if (token == "\\font_sans") {
498 } else if (token == "\\font_typewriter") {
499 lex >> fontsTypewriter;
500 } else if (token == "\\font_default_family") {
501 lex >> fontsDefaultFamily;
502 } else if (token == "\\font_sc") {
504 } else if (token == "\\font_osf") {
506 } else if (token == "\\font_sf_scale") {
507 lex >> fontsSansScale;
508 } else if (token == "\\font_tt_scale") {
509 lex >> fontsTypewriterScale;
510 } else if (token == "\\paragraph_separation") {
513 paragraph_separation = parseptranslator().find(parsep);
514 } else if (token == "\\defskip") {
516 pimpl_->defskip = VSpace(lex.getString());
517 } else if (token == "\\quotes_language") {
520 quotes_language = quoteslangtranslator().find(quotes_lang);
521 } else if (token == "\\papersize") {
524 papersize = papersizetranslator().find(ppsize);
525 } else if (token == "\\use_geometry") {
527 } else if (token == "\\use_amsmath") {
530 use_amsmath = packagetranslator().find(use_ams);
531 } else if (token == "\\use_esint") {
534 use_esint = packagetranslator().find(useesint);
535 } else if (token == "\\cite_engine") {
538 cite_engine_ = citeenginetranslator().find(engine);
539 } else if (token == "\\use_bibtopic") {
541 } else if (token == "\\tracking_changes") {
543 } else if (token == "\\output_changes") {
544 lex >> outputChanges;
545 } else if (token == "\\branch") {
547 docstring branch = lex.getDocString();
548 branchlist().add(branch);
551 string const tok = lex.getString();
552 if (tok == "\\end_branch")
554 Branch * branch_ptr = branchlist().find(branch);
555 if (tok == "\\selected") {
558 branch_ptr->setSelected(lex.getInteger());
560 // not yet operational
561 if (tok == "\\color") {
563 string color = lex.getString();
565 branch_ptr->setColor(color);
566 // Update also the Color table:
568 color = lcolor.getX11Name(Color::background);
570 lcolor.setColor(to_utf8(branch), color);
574 } else if (token == "\\author") {
576 istringstream ss(lex.getString());
579 author_map.push_back(pimpl_->authorlist.record(a));
580 } else if (token == "\\paperorientation") {
583 orientation = paperorientationtranslator().find(orient);
584 } else if (token == "\\paperwidth") {
586 } else if (token == "\\paperheight") {
588 } else if (token == "\\leftmargin") {
590 } else if (token == "\\topmargin") {
592 } else if (token == "\\rightmargin") {
594 } else if (token == "\\bottommargin") {
596 } else if (token == "\\headheight") {
598 } else if (token == "\\headsep") {
600 } else if (token == "\\footskip") {
602 } else if (token == "\\paperfontsize") {
604 } else if (token == "\\papercolumns") {
606 } else if (token == "\\papersides") {
609 sides = sidestranslator().find(psides);
610 } else if (token == "\\paperpagestyle") {
612 } else if (token == "\\bullet") {
614 } else if (token == "\\bulletLaTeX") {
615 readBulletsLaTeX(lex);
616 } else if (token == "\\secnumdepth") {
618 } else if (token == "\\tocdepth") {
620 } else if (token == "\\spacing") {
624 if (nspacing == "other") {
627 spacing().set(spacetranslator().find(nspacing), tmp_val);
628 } else if (token == "\\float_placement") {
629 lex >> float_placement;
638 void BufferParams::writeFile(ostream & os) const
640 // The top of the file is written by the buffer.
641 // Prints out the buffer info into the .lyx file given by file
644 os << "\\textclass " << textclasslist[textclass].name() << '\n';
647 if (!preamble.empty()) {
648 // remove '\n' from the end of preamble
649 string const tmppreamble = rtrim(preamble, "\n");
650 os << "\\begin_preamble\n"
652 << "\n\\end_preamble\n";
656 if (!options.empty()) {
657 os << "\\options " << options << '\n';
660 // then the text parameters
661 if (language != ignore_language)
662 os << "\\language " << language->lang() << '\n';
663 os << "\\inputencoding " << inputenc
664 << "\n\\font_roman " << fontsRoman
665 << "\n\\font_sans " << fontsSans
666 << "\n\\font_typewriter " << fontsTypewriter
667 << "\n\\font_default_family " << fontsDefaultFamily
668 << "\n\\font_sc " << convert<string>(fontsSC)
669 << "\n\\font_osf " << convert<string>(fontsOSF)
670 << "\n\\font_sf_scale " << fontsSansScale
671 << "\n\\font_tt_scale " << fontsTypewriterScale
672 << "\n\\graphics " << graphicsDriver << '\n';
674 if (!float_placement.empty()) {
675 os << "\\float_placement " << float_placement << '\n';
677 os << "\\paperfontsize " << fontsize << '\n';
679 spacing().writeFile(os);
681 os << "\\papersize " << string_papersize[papersize]
682 << "\n\\use_geometry " << convert<string>(use_geometry)
683 << "\n\\use_amsmath " << use_amsmath
684 << "\n\\use_esint " << use_esint
685 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
686 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
687 << "\n\\paperorientation " << string_orientation[orientation]
690 BranchList::const_iterator it = branchlist().begin();
691 BranchList::const_iterator end = branchlist().end();
692 for (; it != end; ++it) {
693 os << "\\branch " << to_utf8(it->getBranch())
694 << "\n\\selected " << it->getSelected()
695 << "\n\\color " << lyx::X11hexname(it->getColor())
700 if (!paperwidth.empty())
701 os << "\\paperwidth "
702 << VSpace(paperwidth).asLyXCommand() << '\n';
703 if (!paperheight.empty())
704 os << "\\paperheight "
705 << VSpace(paperheight).asLyXCommand() << '\n';
706 if (!leftmargin.empty())
707 os << "\\leftmargin "
708 << VSpace(leftmargin).asLyXCommand() << '\n';
709 if (!topmargin.empty())
711 << VSpace(topmargin).asLyXCommand() << '\n';
712 if (!rightmargin.empty())
713 os << "\\rightmargin "
714 << VSpace(rightmargin).asLyXCommand() << '\n';
715 if (!bottommargin.empty())
716 os << "\\bottommargin "
717 << VSpace(bottommargin).asLyXCommand() << '\n';
718 if (!headheight.empty())
719 os << "\\headheight "
720 << VSpace(headheight).asLyXCommand() << '\n';
721 if (!headsep.empty())
723 << VSpace(headsep).asLyXCommand() << '\n';
724 if (!footskip.empty())
726 << VSpace(footskip).asLyXCommand() << '\n';
727 os << "\\secnumdepth " << secnumdepth
728 << "\n\\tocdepth " << tocdepth
729 << "\n\\paragraph_separation "
730 << string_paragraph_separation[paragraph_separation]
731 << "\n\\defskip " << getDefSkip().asLyXCommand()
732 << "\n\\quotes_language "
733 << string_quotes_language[quotes_language]
734 << "\n\\papercolumns " << columns
735 << "\n\\papersides " << sides
736 << "\n\\paperpagestyle " << pagestyle << '\n';
737 for (int i = 0; i < 4; ++i) {
738 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
739 if (user_defined_bullet(i).getFont() != -1) {
740 os << "\\bullet " << i << " "
741 << user_defined_bullet(i).getFont() << " "
742 << user_defined_bullet(i).getCharacter() << " "
743 << user_defined_bullet(i).getSize() << "\n";
747 os << "\\bulletLaTeX " << i << " \""
748 << lyx::to_ascii(user_defined_bullet(i).getText())
754 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
755 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
757 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
758 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
759 for (; a_it != a_end; ++a_it) {
760 os << "\\author " << a_it->second << "\n";
765 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
766 TexRow & texrow) const
768 os << "\\documentclass";
770 TextClass const & tclass = getTextClass();
772 ostringstream clsoptions; // the document class options.
774 if (tokenPos(tclass.opt_fontsize(),
775 '|', fontsize) >= 0) {
776 // only write if existing in list (and not default)
777 clsoptions << fontsize << "pt,";
780 // custom, A3, B3 and B4 paper sizes need geometry
781 bool nonstandard_papersize = papersize == PAPER_B3
782 || papersize == PAPER_B4
783 || papersize == PAPER_A3
784 || papersize == PAPER_CUSTOM;
789 clsoptions << "a4paper,";
792 clsoptions << "letterpaper,";
795 clsoptions << "a5paper,";
798 clsoptions << "b5paper,";
800 case PAPER_USEXECUTIVE:
801 clsoptions << "executivepaper,";
804 clsoptions << "legalpaper,";
816 if (sides != tclass.sides()) {
818 case TextClass::OneSide:
819 clsoptions << "oneside,";
821 case TextClass::TwoSides:
822 clsoptions << "twoside,";
828 if (columns != tclass.columns()) {
830 clsoptions << "twocolumn,";
832 clsoptions << "onecolumn,";
836 && orientation == ORIENTATION_LANDSCAPE)
837 clsoptions << "landscape,";
839 // language should be a parameter to \documentclass
840 if (language->babel() == "hebrew"
841 && default_language->babel() != "hebrew")
842 // This seems necessary
843 features.useLanguage(default_language);
845 ostringstream language_options;
846 bool const use_babel = features.useBabel();
848 language_options << features.getLanguages();
849 if (!language->babel().empty()) {
850 if (!language_options.str().empty())
851 language_options << ',';
852 language_options << language->babel();
854 if (lyxrc.language_global_options)
855 clsoptions << language_options.str() << ',';
858 // the user-defined options
859 if (!options.empty()) {
860 clsoptions << options << ',';
863 string strOptions(clsoptions.str());
864 if (!strOptions.empty()) {
865 strOptions = rtrim(strOptions, ",");
867 os << '[' << from_utf8(strOptions) << ']';
870 os << '{' << from_ascii(tclass.latexname()) << "}\n";
872 // end of \documentclass defs
874 // font selection must be done before loading fontenc.sty
876 loadFonts(fontsRoman, fontsSans,
877 fontsTypewriter, fontsSC, fontsOSF,
878 fontsSansScale, fontsTypewriterScale);
879 if (!fonts.empty()) {
880 os << from_ascii(fonts);
883 if (fontsDefaultFamily != "default")
884 os << "\\renewcommand{\\familydefault}{\\"
885 << from_ascii(fontsDefaultFamily) << "}\n";
886 // this one is not per buffer
887 if (lyxrc.fontenc != "default") {
888 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
893 if (inputenc == "auto") {
894 string const doc_encoding =
895 language->encoding()->latexName();
896 Encoding::Package const package =
897 language->encoding()->package();
899 // Create a list with all the input encodings used
901 std::set<string> encodings =
902 features.getEncodingSet(doc_encoding);
904 if (!encodings.empty() || package == Encoding::inputenc) {
905 os << "\\usepackage[";
906 std::set<string>::const_iterator it = encodings.begin();
907 std::set<string>::const_iterator const end = encodings.end();
909 os << from_ascii(*it);
912 for (; it != end; ++it)
913 os << ',' << from_ascii(*it);
914 if (package == Encoding::inputenc) {
915 if (!encodings.empty())
917 os << from_ascii(doc_encoding);
919 os << "]{inputenc}\n";
922 if (package == Encoding::CJK) {
923 os << "\\usepackage{CJK}\n";
926 } else if (inputenc != "default") {
927 switch (language->encoding()->package()) {
930 case Encoding::inputenc:
931 os << "\\usepackage[" << from_ascii(inputenc)
936 os << "\\usepackage{CJK}\n";
942 // The encoding "armscii8" is only available when the package "armtex" is loaded.
943 // armscii8 is used for Armenian.
944 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
945 os << "\\usepackage{armtex}\n";
949 if (use_geometry || nonstandard_papersize) {
950 os << "\\usepackage{geometry}\n";
952 os << "\\geometry{verbose";
953 if (orientation == ORIENTATION_LANDSCAPE)
957 if (!paperwidth.empty())
959 << from_ascii(paperwidth);
960 if (!paperheight.empty())
961 os << ",paperheight="
962 << from_ascii(paperheight);
965 os << ",letterpaper";
970 case PAPER_USEXECUTIVE:
971 os << ",executivepaper";
992 // default papersize ie PAPER_DEFAULT
993 switch (lyxrc.default_papersize) {
994 case PAPER_DEFAULT: // keep compiler happy
996 os << ",letterpaper";
1001 case PAPER_USEXECUTIVE:
1002 os << ",executivepaper";
1022 if (!topmargin.empty())
1023 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1024 if (!bottommargin.empty())
1025 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1026 if (!leftmargin.empty())
1027 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1028 if (!rightmargin.empty())
1029 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1030 if (!headheight.empty())
1031 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1032 if (!headsep.empty())
1033 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1034 if (!footskip.empty())
1035 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1040 if (tokenPos(tclass.opt_pagestyle(),
1041 '|', pagestyle) >= 0) {
1042 if (pagestyle == "fancy") {
1043 os << "\\usepackage{fancyhdr}\n";
1046 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1050 // Only if class has a ToC hierarchy
1051 if (tclass.hasTocLevels()) {
1052 if (secnumdepth != tclass.secnumdepth()) {
1053 os << "\\setcounter{secnumdepth}{"
1058 if (tocdepth != tclass.tocdepth()) {
1059 os << "\\setcounter{tocdepth}{"
1066 if (paragraph_separation) {
1067 switch (getDefSkip().kind()) {
1068 case VSpace::SMALLSKIP:
1069 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1071 case VSpace::MEDSKIP:
1072 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1074 case VSpace::BIGSKIP:
1075 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1077 case VSpace::LENGTH:
1078 os << "\\setlength{\\parskip}{"
1079 << from_utf8(getDefSkip().length().asLatexString())
1082 default: // should never happen // Then delete it.
1083 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1088 os << "\\setlength{\\parindent}{0pt}\n";
1092 // If we use jurabib, we have to call babel here.
1093 if (use_babel && features.isRequired("jurabib")) {
1094 os << from_ascii(babelCall(language_options.str()))
1096 << from_ascii(features.getBabelOptions());
1100 // Now insert the LyX specific LaTeX commands...
1102 // The optional packages;
1103 docstring lyxpreamble(from_ascii(features.getPackages()));
1105 // this might be useful...
1106 lyxpreamble += "\n\\makeatletter\n";
1108 // Some macros LyX will need
1109 docstring tmppreamble(from_ascii(features.getMacros()));
1111 if (!tmppreamble.empty()) {
1112 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1113 "LyX specific LaTeX commands.\n"
1114 + tmppreamble + '\n';
1117 // the text class specific preamble
1118 tmppreamble = features.getTClassPreamble();
1119 if (!tmppreamble.empty()) {
1120 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1121 "Textclass specific LaTeX commands.\n"
1122 + tmppreamble + '\n';
1125 /* the user-defined preamble */
1126 if (!preamble.empty()) {
1128 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1129 "User specified LaTeX commands.\n"
1130 + from_utf8(preamble) + '\n';
1133 // Itemize bullet settings need to be last in case the user
1134 // defines their own bullets that use a package included
1135 // in the user-defined preamble -- ARRae
1136 // Actually it has to be done much later than that
1137 // since some packages like frenchb make modifications
1138 // at \begin{document} time -- JMarc
1139 docstring bullets_def;
1140 for (int i = 0; i < 4; ++i) {
1141 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1142 if (bullets_def.empty())
1143 bullets_def += "\\AtBeginDocument{\n";
1144 bullets_def += " \\def\\labelitemi";
1146 // `i' is one less than the item to modify
1153 bullets_def += "ii";
1159 bullets_def += '{' +
1160 user_defined_bullet(i).getText()
1165 if (!bullets_def.empty())
1166 lyxpreamble += bullets_def + "}\n\n";
1168 // We try to load babel late, in case it interferes
1169 // with other packages.
1170 // Jurabib has to be called after babel, though.
1171 if (use_babel && !features.isRequired("jurabib")) {
1173 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1174 lyxpreamble += from_utf8(features.getBabelOptions());
1177 lyxpreamble += "\\makeatother\n";
1179 // dvipost settings come after everything else
1180 if (features.isAvailable("dvipost") && outputChanges) {
1183 "\\dvipost{osstart color push Red}\n"
1184 "\\dvipost{osend color pop}\n"
1185 "\\dvipost{cbstart color push Blue}\n"
1186 "\\dvipost{cbend color pop}\n";
1190 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1191 for (int j = 0; j != nlines; ++j) {
1200 void BufferParams::useClassDefaults()
1202 TextClass const & tclass = textclasslist[textclass];
1204 sides = tclass.sides();
1205 columns = tclass.columns();
1206 pagestyle = tclass.pagestyle();
1207 options = tclass.options();
1208 // Only if class has a ToC hierarchy
1209 if (tclass.hasTocLevels()) {
1210 secnumdepth = tclass.secnumdepth();
1211 tocdepth = tclass.tocdepth();
1216 bool BufferParams::hasClassDefaults() const
1218 TextClass const & tclass = textclasslist[textclass];
1220 return (sides == tclass.sides()
1221 && columns == tclass.columns()
1222 && pagestyle == tclass.pagestyle()
1223 && options == tclass.options()
1224 && secnumdepth == tclass.secnumdepth()
1225 && tocdepth == tclass.tocdepth());
1229 TextClass const & BufferParams::getTextClass() const
1231 return textclasslist[textclass];
1235 Font const BufferParams::getFont() const
1237 Font f = getTextClass().defaultfont();
1238 f.setLanguage(language);
1239 if (fontsDefaultFamily == "rmdefault")
1240 f.setFamily(Font::ROMAN_FAMILY);
1241 else if (fontsDefaultFamily == "sfdefault")
1242 f.setFamily(Font::SANS_FAMILY);
1243 else if (fontsDefaultFamily == "ttdefault")
1244 f.setFamily(Font::TYPEWRITER_FAMILY);
1249 void BufferParams::readPreamble(Lexer & lex)
1251 if (lex.getString() != "\\begin_preamble")
1252 lyxerr << "Error (BufferParams::readPreamble):"
1253 "consistency check failed." << endl;
1255 preamble = lex.getLongString("\\end_preamble");
1259 void BufferParams::readLanguage(Lexer & lex)
1261 if (!lex.next()) return;
1263 string const tmptok = lex.getString();
1265 // check if tmptok is part of tex_babel in tex-defs.h
1266 language = languages.getLanguage(tmptok);
1268 // Language tmptok was not found
1269 language = default_language;
1270 lyxerr << "Warning: Setting language `"
1271 << tmptok << "' to `" << language->lang()
1277 void BufferParams::readGraphicsDriver(Lexer & lex)
1279 if (!lex.next()) return;
1281 string const tmptok = lex.getString();
1282 // check if tmptok is part of tex_graphics in tex_defs.h
1285 string const test = tex_graphics[n++];
1287 if (test == tmptok) {
1288 graphicsDriver = tmptok;
1290 } else if (test == "") {
1292 "Warning: graphics driver `$$Token' not recognized!\n"
1293 " Setting graphics driver to `default'.\n");
1294 graphicsDriver = "default";
1301 void BufferParams::readBullets(Lexer & lex)
1303 if (!lex.next()) return;
1305 int const index = lex.getInteger();
1307 int temp_int = lex.getInteger();
1308 user_defined_bullet(index).setFont(temp_int);
1309 temp_bullet(index).setFont(temp_int);
1311 user_defined_bullet(index).setCharacter(temp_int);
1312 temp_bullet(index).setCharacter(temp_int);
1314 user_defined_bullet(index).setSize(temp_int);
1315 temp_bullet(index).setSize(temp_int);
1319 void BufferParams::readBulletsLaTeX(Lexer & lex)
1321 // The bullet class should be able to read this.
1322 if (!lex.next()) return;
1323 int const index = lex.getInteger();
1325 docstring const temp_str = lex.getDocString();
1327 user_defined_bullet(index).setText(temp_str);
1328 temp_bullet(index).setText(temp_str);
1332 string const BufferParams::paperSizeName() const
1334 char real_papersize = papersize;
1335 if (real_papersize == PAPER_DEFAULT)
1336 real_papersize = lyxrc.default_papersize;
1338 switch (real_papersize) {
1347 case PAPER_USEXECUTIVE:
1351 case PAPER_USLETTER:
1358 string const BufferParams::dvips_options() const
1363 && papersize == PAPER_CUSTOM
1364 && !lyxrc.print_paper_dimension_flag.empty()
1365 && !paperwidth.empty()
1366 && !paperheight.empty()) {
1367 // using a custom papersize
1368 result = lyxrc.print_paper_dimension_flag;
1369 result += ' ' + paperwidth;
1370 result += ',' + paperheight;
1372 string const paper_option = paperSizeName();
1373 if (paper_option != "letter" ||
1374 orientation != ORIENTATION_LANDSCAPE) {
1375 // dvips won't accept -t letter -t landscape.
1376 // In all other cases, include the paper size
1378 result = lyxrc.print_paper_flag;
1379 result += ' ' + paper_option;
1382 if (orientation == ORIENTATION_LANDSCAPE &&
1383 papersize != PAPER_CUSTOM)
1384 result += ' ' + lyxrc.print_landscape_flag;
1389 string const BufferParams::babelCall(string const & lang_opts) const
1391 string tmp = lyxrc.language_package;
1392 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1393 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1398 string const BufferParams::loadFonts(string const & rm,
1399 string const & sf, string const & tt,
1400 bool const & sc, bool const & osf,
1401 int const & sfscale, int const & ttscale) const
1403 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1404 several packages have been replaced by others, that might not
1405 be installed on every system. We have to take care for that
1406 (see psnfss.pdf). We try to support all psnfss fonts as well
1407 as the fonts that have become de facto standard in the LaTeX
1408 world (e.g. Latin Modern). We do not support obsolete fonts
1409 (like PSLatex). In general, it should be possible to mix any
1410 rm font with any sf or tt font, respectively. (JSpitzm)
1412 -- separate math fonts.
1415 if (rm == "default" && sf == "default" && tt == "default")
1422 // Computer Modern (must be explicitely selectable -- there might be classes
1423 // that define a different default font!
1425 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1426 // osf for Computer Modern needs eco.sty
1428 os << "\\usepackage{eco}\n";
1430 // Latin Modern Roman
1431 else if (rm == "lmodern")
1432 os << "\\usepackage{lmodern}\n";
1434 else if (rm == "ae") {
1435 // not needed when using OT1 font encoding.
1436 if (lyxrc.fontenc != "default")
1437 os << "\\usepackage{ae,aecompl}\n";
1440 else if (rm == "times") {
1441 // try to load the best available package
1442 if (LaTeXFeatures::isAvailable("mathptmx"))
1443 os << "\\usepackage{mathptmx}\n";
1444 else if (LaTeXFeatures::isAvailable("mathptm"))
1445 os << "\\usepackage{mathptm}\n";
1447 os << "\\usepackage{times}\n";
1450 else if (rm == "palatino") {
1451 // try to load the best available package
1452 if (LaTeXFeatures::isAvailable("mathpazo")) {
1453 os << "\\usepackage";
1459 // "osf" includes "sc"!
1463 os << "{mathpazo}\n";
1465 else if (LaTeXFeatures::isAvailable("mathpple"))
1466 os << "\\usepackage{mathpple}\n";
1468 os << "\\usepackage{palatino}\n";
1471 else if (rm == "utopia") {
1472 // fourier supersedes utopia.sty, but does
1473 // not work with OT1 encoding.
1474 if (LaTeXFeatures::isAvailable("fourier")
1475 && lyxrc.fontenc != "default") {
1476 os << "\\usepackage";
1487 os << "{fourier}\n";
1490 os << "\\usepackage{utopia}\n";
1492 // Bera (complete fontset)
1493 else if (rm == "bera" && sf == "default" && tt == "default")
1494 os << "\\usepackage{bera}\n";
1496 else if (rm != "default")
1497 os << "\\usepackage" << "{" << rm << "}\n";
1500 // Helvetica, Bera Sans
1501 if (sf == "helvet" || sf == "berasans") {
1503 os << "\\usepackage[scaled=" << float(sfscale) / 100
1504 << "]{" << sf << "}\n";
1506 os << "\\usepackage{" << sf << "}\n";
1509 else if (sf == "avant")
1510 os << "\\usepackage{" << sf << "}\n";
1511 // Computer Modern, Latin Modern, CM Bright
1512 else if (sf != "default")
1513 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1515 // monospaced/typewriter
1516 // Courier, LuxiMono
1517 if (tt == "luximono" || tt == "beramono") {
1519 os << "\\usepackage[scaled=" << float(ttscale) / 100
1520 << "]{" << tt << "}\n";
1522 os << "\\usepackage{" << tt << "}\n";
1525 else if (tt == "courier" )
1526 os << "\\usepackage{" << tt << "}\n";
1527 // Computer Modern, Latin Modern, CM Bright
1528 else if (tt != "default")
1529 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1535 Encoding const & BufferParams::encoding() const
1537 if (inputenc == "auto" || inputenc == "default")
1538 return *(language->encoding());
1539 Encoding const * const enc =
1540 encodings.getFromLaTeXName(inputenc);
1543 lyxerr << "Unknown inputenc value `" << inputenc
1544 << "'. Using `auto' instead." << endl;
1545 return *(language->encoding());
1549 biblio::CiteEngine BufferParams::getEngine() const
1551 // FIXME the class should provide the numerical/
1552 // authoryear choice
1553 if (getTextClass().provides("natbib")
1554 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1555 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1556 return cite_engine_;
1560 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1562 cite_engine_ = cite_engine;