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 language_options << language->babel();
850 if (lyxrc.language_global_options)
851 clsoptions << language_options.str() << ',';
854 // the user-defined options
855 if (!options.empty()) {
856 clsoptions << options << ',';
859 string strOptions(clsoptions.str());
860 if (!strOptions.empty()) {
861 strOptions = rtrim(strOptions, ",");
863 os << '[' << from_utf8(strOptions) << ']';
866 os << '{' << from_ascii(tclass.latexname()) << "}\n";
868 // end of \documentclass defs
870 // font selection must be done before loading fontenc.sty
872 loadFonts(fontsRoman, fontsSans,
873 fontsTypewriter, fontsSC, fontsOSF,
874 fontsSansScale, fontsTypewriterScale);
875 if (!fonts.empty()) {
876 os << from_ascii(fonts);
879 if (fontsDefaultFamily != "default")
880 os << "\\renewcommand{\\familydefault}{\\"
881 << from_ascii(fontsDefaultFamily) << "}\n";
882 // this one is not per buffer
883 if (lyxrc.fontenc != "default") {
884 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
889 if (inputenc == "auto") {
890 string const doc_encoding =
891 language->encoding()->latexName();
893 // Create a list with all the input encodings used
895 std::set<string> encodings =
896 features.getEncodingSet(doc_encoding);
898 // thailatex does not use the inputenc package, but sets up
899 // babel directly for tis620-0 encoding, therefore we must
900 // not request inputenc for tis620-0 encoding
901 if (!encodings.empty() || doc_encoding != "tis620-0") {
902 os << "\\usepackage[";
903 std::set<string>::const_iterator it = encodings.begin();
904 std::set<string>::const_iterator const end = encodings.end();
906 os << from_ascii(*it);
909 for (; it != end; ++it)
910 os << ',' << from_ascii(*it);
911 if (doc_encoding != "tis620-0") {
912 if (!encodings.empty())
914 os << from_ascii(doc_encoding);
916 os << "]{inputenc}\n";
919 } else if (inputenc != "default" && inputenc != "tis620-0" &&
920 inputenc != "ascii") {
921 os << "\\usepackage[" << from_ascii(inputenc)
926 // The encoding "armscii8" is only available when the package "armtex" is loaded.
927 // armscii8 is used for Armenian.
928 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
929 os << "\\usepackage{armtex}\n";
933 if (use_geometry || nonstandard_papersize) {
934 os << "\\usepackage{geometry}\n";
936 os << "\\geometry{verbose";
937 if (orientation == ORIENTATION_LANDSCAPE)
941 if (!paperwidth.empty())
943 << from_ascii(paperwidth);
944 if (!paperheight.empty())
945 os << ",paperheight="
946 << from_ascii(paperheight);
949 os << ",letterpaper";
954 case PAPER_USEXECUTIVE:
955 os << ",executivepaper";
976 // default papersize ie PAPER_DEFAULT
977 switch (lyxrc.default_papersize) {
978 case PAPER_DEFAULT: // keep compiler happy
980 os << ",letterpaper";
985 case PAPER_USEXECUTIVE:
986 os << ",executivepaper";
1006 if (!topmargin.empty())
1007 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1008 if (!bottommargin.empty())
1009 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1010 if (!leftmargin.empty())
1011 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1012 if (!rightmargin.empty())
1013 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1014 if (!headheight.empty())
1015 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1016 if (!headsep.empty())
1017 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1018 if (!footskip.empty())
1019 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1024 if (tokenPos(tclass.opt_pagestyle(),
1025 '|', pagestyle) >= 0) {
1026 if (pagestyle == "fancy") {
1027 os << "\\usepackage{fancyhdr}\n";
1030 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1034 // Only if class has a ToC hierarchy
1035 if (tclass.hasTocLevels()) {
1036 if (secnumdepth != tclass.secnumdepth()) {
1037 os << "\\setcounter{secnumdepth}{"
1042 if (tocdepth != tclass.tocdepth()) {
1043 os << "\\setcounter{tocdepth}{"
1050 if (paragraph_separation) {
1051 switch (getDefSkip().kind()) {
1052 case VSpace::SMALLSKIP:
1053 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1055 case VSpace::MEDSKIP:
1056 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1058 case VSpace::BIGSKIP:
1059 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1061 case VSpace::LENGTH:
1062 os << "\\setlength{\\parskip}{"
1063 << from_utf8(getDefSkip().length().asLatexString())
1066 default: // should never happen // Then delete it.
1067 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1072 os << "\\setlength{\\parindent}{0pt}\n";
1076 // If we use jurabib, we have to call babel here.
1077 if (use_babel && features.isRequired("jurabib")) {
1078 os << from_ascii(babelCall(language_options.str()))
1080 << from_ascii(features.getBabelOptions());
1084 // Now insert the LyX specific LaTeX commands...
1086 // The optional packages;
1087 docstring lyxpreamble(from_ascii(features.getPackages()));
1089 // this might be useful...
1090 lyxpreamble += "\n\\makeatletter\n";
1092 // Some macros LyX will need
1093 docstring tmppreamble(from_ascii(features.getMacros()));
1095 if (!tmppreamble.empty()) {
1096 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1097 "LyX specific LaTeX commands.\n"
1098 + tmppreamble + '\n';
1101 // the text class specific preamble
1102 tmppreamble = features.getTClassPreamble();
1103 if (!tmppreamble.empty()) {
1104 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1105 "Textclass specific LaTeX commands.\n"
1106 + tmppreamble + '\n';
1109 /* the user-defined preamble */
1110 if (!preamble.empty()) {
1112 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1113 "User specified LaTeX commands.\n"
1114 + from_utf8(preamble) + '\n';
1117 // Itemize bullet settings need to be last in case the user
1118 // defines their own bullets that use a package included
1119 // in the user-defined preamble -- ARRae
1120 // Actually it has to be done much later than that
1121 // since some packages like frenchb make modifications
1122 // at \begin{document} time -- JMarc
1123 docstring bullets_def;
1124 for (int i = 0; i < 4; ++i) {
1125 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1126 if (bullets_def.empty())
1127 bullets_def += "\\AtBeginDocument{\n";
1128 bullets_def += " \\def\\labelitemi";
1130 // `i' is one less than the item to modify
1137 bullets_def += "ii";
1143 bullets_def += '{' +
1144 user_defined_bullet(i).getText()
1149 if (!bullets_def.empty())
1150 lyxpreamble += bullets_def + "}\n\n";
1152 // We try to load babel late, in case it interferes
1153 // with other packages.
1154 // Jurabib has to be called after babel, though.
1155 if (use_babel && !features.isRequired("jurabib")) {
1157 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1158 lyxpreamble += from_utf8(features.getBabelOptions());
1161 lyxpreamble += "\\makeatother\n";
1163 // dvipost settings come after everything else
1164 if (features.isAvailable("dvipost") && outputChanges) {
1167 "\\dvipost{osstart color push Red}\n"
1168 "\\dvipost{osend color pop}\n"
1169 "\\dvipost{cbstart color push Blue}\n"
1170 "\\dvipost{cbend color pop}\n";
1174 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1175 for (int j = 0; j != nlines; ++j) {
1184 void BufferParams::useClassDefaults()
1186 TextClass const & tclass = textclasslist[textclass];
1188 sides = tclass.sides();
1189 columns = tclass.columns();
1190 pagestyle = tclass.pagestyle();
1191 options = tclass.options();
1192 // Only if class has a ToC hierarchy
1193 if (tclass.hasTocLevels()) {
1194 secnumdepth = tclass.secnumdepth();
1195 tocdepth = tclass.tocdepth();
1200 bool BufferParams::hasClassDefaults() const
1202 TextClass const & tclass = textclasslist[textclass];
1204 return (sides == tclass.sides()
1205 && columns == tclass.columns()
1206 && pagestyle == tclass.pagestyle()
1207 && options == tclass.options()
1208 && secnumdepth == tclass.secnumdepth()
1209 && tocdepth == tclass.tocdepth());
1213 TextClass const & BufferParams::getTextClass() const
1215 return textclasslist[textclass];
1219 Font const BufferParams::getFont() const
1221 Font f = getTextClass().defaultfont();
1222 f.setLanguage(language);
1223 if (fontsDefaultFamily == "rmdefault")
1224 f.setFamily(Font::ROMAN_FAMILY);
1225 else if (fontsDefaultFamily == "sfdefault")
1226 f.setFamily(Font::SANS_FAMILY);
1227 else if (fontsDefaultFamily == "ttdefault")
1228 f.setFamily(Font::TYPEWRITER_FAMILY);
1233 void BufferParams::readPreamble(Lexer & lex)
1235 if (lex.getString() != "\\begin_preamble")
1236 lyxerr << "Error (BufferParams::readPreamble):"
1237 "consistency check failed." << endl;
1239 preamble = lex.getLongString("\\end_preamble");
1243 void BufferParams::readLanguage(Lexer & lex)
1245 if (!lex.next()) return;
1247 string const tmptok = lex.getString();
1249 // check if tmptok is part of tex_babel in tex-defs.h
1250 language = languages.getLanguage(tmptok);
1252 // Language tmptok was not found
1253 language = default_language;
1254 lyxerr << "Warning: Setting language `"
1255 << tmptok << "' to `" << language->lang()
1261 void BufferParams::readGraphicsDriver(Lexer & lex)
1263 if (!lex.next()) return;
1265 string const tmptok = lex.getString();
1266 // check if tmptok is part of tex_graphics in tex_defs.h
1269 string const test = tex_graphics[n++];
1271 if (test == tmptok) {
1272 graphicsDriver = tmptok;
1274 } else if (test == "") {
1276 "Warning: graphics driver `$$Token' not recognized!\n"
1277 " Setting graphics driver to `default'.\n");
1278 graphicsDriver = "default";
1285 void BufferParams::readBullets(Lexer & lex)
1287 if (!lex.next()) return;
1289 int const index = lex.getInteger();
1291 int temp_int = lex.getInteger();
1292 user_defined_bullet(index).setFont(temp_int);
1293 temp_bullet(index).setFont(temp_int);
1295 user_defined_bullet(index).setCharacter(temp_int);
1296 temp_bullet(index).setCharacter(temp_int);
1298 user_defined_bullet(index).setSize(temp_int);
1299 temp_bullet(index).setSize(temp_int);
1303 void BufferParams::readBulletsLaTeX(Lexer & lex)
1305 // The bullet class should be able to read this.
1306 if (!lex.next()) return;
1307 int const index = lex.getInteger();
1309 docstring const temp_str = lex.getDocString();
1311 user_defined_bullet(index).setText(temp_str);
1312 temp_bullet(index).setText(temp_str);
1316 string const BufferParams::paperSizeName() const
1318 char real_papersize = papersize;
1319 if (real_papersize == PAPER_DEFAULT)
1320 real_papersize = lyxrc.default_papersize;
1322 switch (real_papersize) {
1331 case PAPER_USEXECUTIVE:
1335 case PAPER_USLETTER:
1342 string const BufferParams::dvips_options() const
1347 && papersize == PAPER_CUSTOM
1348 && !lyxrc.print_paper_dimension_flag.empty()
1349 && !paperwidth.empty()
1350 && !paperheight.empty()) {
1351 // using a custom papersize
1352 result = lyxrc.print_paper_dimension_flag;
1353 result += ' ' + paperwidth;
1354 result += ',' + paperheight;
1356 string const paper_option = paperSizeName();
1357 if (paper_option != "letter" ||
1358 orientation != ORIENTATION_LANDSCAPE) {
1359 // dvips won't accept -t letter -t landscape.
1360 // In all other cases, include the paper size
1362 result = lyxrc.print_paper_flag;
1363 result += ' ' + paper_option;
1366 if (orientation == ORIENTATION_LANDSCAPE &&
1367 papersize != PAPER_CUSTOM)
1368 result += ' ' + lyxrc.print_landscape_flag;
1373 string const BufferParams::babelCall(string const & lang_opts) const
1375 string tmp = lyxrc.language_package;
1376 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1377 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1382 string const BufferParams::loadFonts(string const & rm,
1383 string const & sf, string const & tt,
1384 bool const & sc, bool const & osf,
1385 int const & sfscale, int const & ttscale) const
1387 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1388 several packages have been replaced by others, that might not
1389 be installed on every system. We have to take care for that
1390 (see psnfss.pdf). We try to support all psnfss fonts as well
1391 as the fonts that have become de facto standard in the LaTeX
1392 world (e.g. Latin Modern). We do not support obsolete fonts
1393 (like PSLatex). In general, it should be possible to mix any
1394 rm font with any sf or tt font, respectively. (JSpitzm)
1396 -- separate math fonts.
1399 if (rm == "default" && sf == "default" && tt == "default")
1406 // Computer Modern (must be explicitely selectable -- there might be classes
1407 // that define a different default font!
1409 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1410 // osf for Computer Modern needs eco.sty
1412 os << "\\usepackage{eco}\n";
1414 // Latin Modern Roman
1415 else if (rm == "lmodern")
1416 os << "\\usepackage{lmodern}\n";
1418 else if (rm == "ae") {
1419 // not needed when using OT1 font encoding.
1420 if (lyxrc.fontenc != "default")
1421 os << "\\usepackage{ae,aecompl}\n";
1424 else if (rm == "times") {
1425 // try to load the best available package
1426 if (LaTeXFeatures::isAvailable("mathptmx"))
1427 os << "\\usepackage{mathptmx}\n";
1428 else if (LaTeXFeatures::isAvailable("mathptm"))
1429 os << "\\usepackage{mathptm}\n";
1431 os << "\\usepackage{times}\n";
1434 else if (rm == "palatino") {
1435 // try to load the best available package
1436 if (LaTeXFeatures::isAvailable("mathpazo")) {
1437 os << "\\usepackage";
1443 // "osf" includes "sc"!
1447 os << "{mathpazo}\n";
1449 else if (LaTeXFeatures::isAvailable("mathpple"))
1450 os << "\\usepackage{mathpple}\n";
1452 os << "\\usepackage{palatino}\n";
1455 else if (rm == "utopia") {
1456 // fourier supersedes utopia.sty, but does
1457 // not work with OT1 encoding.
1458 if (LaTeXFeatures::isAvailable("fourier")
1459 && lyxrc.fontenc != "default") {
1460 os << "\\usepackage";
1471 os << "{fourier}\n";
1474 os << "\\usepackage{utopia}\n";
1476 // Bera (complete fontset)
1477 else if (rm == "bera" && sf == "default" && tt == "default")
1478 os << "\\usepackage{bera}\n";
1480 else if (rm != "default")
1481 os << "\\usepackage" << "{" << rm << "}\n";
1484 // Helvetica, Bera Sans
1485 if (sf == "helvet" || sf == "berasans") {
1487 os << "\\usepackage[scaled=" << float(sfscale) / 100
1488 << "]{" << sf << "}\n";
1490 os << "\\usepackage{" << sf << "}\n";
1493 else if (sf == "avant")
1494 os << "\\usepackage{" << sf << "}\n";
1495 // Computer Modern, Latin Modern, CM Bright
1496 else if (sf != "default")
1497 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1499 // monospaced/typewriter
1500 // Courier, LuxiMono
1501 if (tt == "luximono" || tt == "beramono") {
1503 os << "\\usepackage[scaled=" << float(ttscale) / 100
1504 << "]{" << tt << "}\n";
1506 os << "\\usepackage{" << tt << "}\n";
1509 else if (tt == "courier" )
1510 os << "\\usepackage{" << tt << "}\n";
1511 // Computer Modern, Latin Modern, CM Bright
1512 else if (tt != "default")
1513 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1519 Encoding const & BufferParams::encoding() const
1521 if (inputenc == "auto" || inputenc == "default")
1522 return *(language->encoding());
1523 Encoding const * const enc =
1524 encodings.getFromLaTeXName(inputenc);
1527 lyxerr << "Unknown inputenc value `" << inputenc
1528 << "'. Using `auto' instead." << endl;
1529 return *(language->encoding());
1533 biblio::CiteEngine BufferParams::getEngine() const
1535 // FIXME the class should provide the numerical/
1536 // authoryear choice
1537 if (getTextClass().provides("natbib")
1538 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1539 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1540 return cite_engine_;
1544 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1546 cite_engine_ = cite_engine;