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 if (use_geometry || nonstandard_papersize) {
927 os << "\\usepackage{geometry}\n";
929 os << "\\geometry{verbose";
930 if (orientation == ORIENTATION_LANDSCAPE)
934 if (!paperwidth.empty())
936 << from_ascii(paperwidth);
937 if (!paperheight.empty())
938 os << ",paperheight="
939 << from_ascii(paperheight);
942 os << ",letterpaper";
947 case PAPER_USEXECUTIVE:
948 os << ",executivepaper";
969 // default papersize ie PAPER_DEFAULT
970 switch (lyxrc.default_papersize) {
971 case PAPER_DEFAULT: // keep compiler happy
973 os << ",letterpaper";
978 case PAPER_USEXECUTIVE:
979 os << ",executivepaper";
999 if (!topmargin.empty())
1000 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1001 if (!bottommargin.empty())
1002 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1003 if (!leftmargin.empty())
1004 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1005 if (!rightmargin.empty())
1006 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1007 if (!headheight.empty())
1008 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1009 if (!headsep.empty())
1010 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1011 if (!footskip.empty())
1012 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1017 if (tokenPos(tclass.opt_pagestyle(),
1018 '|', pagestyle) >= 0) {
1019 if (pagestyle == "fancy") {
1020 os << "\\usepackage{fancyhdr}\n";
1023 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1027 // Only if class has a ToC hierarchy
1028 if (tclass.hasTocLevels()) {
1029 if (secnumdepth != tclass.secnumdepth()) {
1030 os << "\\setcounter{secnumdepth}{"
1035 if (tocdepth != tclass.tocdepth()) {
1036 os << "\\setcounter{tocdepth}{"
1043 if (paragraph_separation) {
1044 switch (getDefSkip().kind()) {
1045 case VSpace::SMALLSKIP:
1046 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1048 case VSpace::MEDSKIP:
1049 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1051 case VSpace::BIGSKIP:
1052 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1054 case VSpace::LENGTH:
1055 os << "\\setlength{\\parskip}{"
1056 << from_utf8(getDefSkip().length().asLatexString())
1059 default: // should never happen // Then delete it.
1060 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1065 os << "\\setlength{\\parindent}{0pt}\n";
1069 // If we use jurabib, we have to call babel here.
1070 if (use_babel && features.isRequired("jurabib")) {
1071 os << from_ascii(babelCall(language_options.str()))
1073 << from_ascii(features.getBabelOptions());
1077 // Now insert the LyX specific LaTeX commands...
1079 // The optional packages;
1080 docstring lyxpreamble(from_ascii(features.getPackages()));
1082 // this might be useful...
1083 lyxpreamble += "\n\\makeatletter\n";
1085 // Some macros LyX will need
1086 docstring tmppreamble(from_ascii(features.getMacros()));
1088 if (!tmppreamble.empty()) {
1089 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1090 "LyX specific LaTeX commands.\n"
1091 + tmppreamble + '\n';
1094 // the text class specific preamble
1095 tmppreamble = features.getTClassPreamble();
1096 if (!tmppreamble.empty()) {
1097 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1098 "Textclass specific LaTeX commands.\n"
1099 + tmppreamble + '\n';
1102 /* the user-defined preamble */
1103 if (!preamble.empty()) {
1105 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1106 "User specified LaTeX commands.\n"
1107 + from_utf8(preamble) + '\n';
1110 // Itemize bullet settings need to be last in case the user
1111 // defines their own bullets that use a package included
1112 // in the user-defined preamble -- ARRae
1113 // Actually it has to be done much later than that
1114 // since some packages like frenchb make modifications
1115 // at \begin{document} time -- JMarc
1116 docstring bullets_def;
1117 for (int i = 0; i < 4; ++i) {
1118 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1119 if (bullets_def.empty())
1120 bullets_def += "\\AtBeginDocument{\n";
1121 bullets_def += " \\def\\labelitemi";
1123 // `i' is one less than the item to modify
1130 bullets_def += "ii";
1136 bullets_def += '{' +
1137 user_defined_bullet(i).getText()
1142 if (!bullets_def.empty())
1143 lyxpreamble += bullets_def + "}\n\n";
1145 // We try to load babel late, in case it interferes
1146 // with other packages.
1147 // Jurabib has to be called after babel, though.
1148 if (use_babel && !features.isRequired("jurabib")) {
1150 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1151 lyxpreamble += from_utf8(features.getBabelOptions());
1154 lyxpreamble += "\\makeatother\n";
1156 // dvipost settings come after everything else
1157 if (features.isAvailable("dvipost") && outputChanges) {
1160 "\\dvipost{osstart color push Red}\n"
1161 "\\dvipost{osend color pop}\n"
1162 "\\dvipost{cbstart color push Blue}\n"
1163 "\\dvipost{cbend color pop}\n";
1167 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1168 for (int j = 0; j != nlines; ++j) {
1177 void BufferParams::useClassDefaults()
1179 TextClass const & tclass = textclasslist[textclass];
1181 sides = tclass.sides();
1182 columns = tclass.columns();
1183 pagestyle = tclass.pagestyle();
1184 options = tclass.options();
1185 // Only if class has a ToC hierarchy
1186 if (tclass.hasTocLevels()) {
1187 secnumdepth = tclass.secnumdepth();
1188 tocdepth = tclass.tocdepth();
1193 bool BufferParams::hasClassDefaults() const
1195 TextClass const & tclass = textclasslist[textclass];
1197 return (sides == tclass.sides()
1198 && columns == tclass.columns()
1199 && pagestyle == tclass.pagestyle()
1200 && options == tclass.options()
1201 && secnumdepth == tclass.secnumdepth()
1202 && tocdepth == tclass.tocdepth());
1206 TextClass const & BufferParams::getTextClass() const
1208 return textclasslist[textclass];
1212 Font const BufferParams::getFont() const
1214 Font f = getTextClass().defaultfont();
1215 f.setLanguage(language);
1216 if (fontsDefaultFamily == "rmdefault")
1217 f.setFamily(Font::ROMAN_FAMILY);
1218 else if (fontsDefaultFamily == "sfdefault")
1219 f.setFamily(Font::SANS_FAMILY);
1220 else if (fontsDefaultFamily == "ttdefault")
1221 f.setFamily(Font::TYPEWRITER_FAMILY);
1226 void BufferParams::readPreamble(Lexer & lex)
1228 if (lex.getString() != "\\begin_preamble")
1229 lyxerr << "Error (BufferParams::readPreamble):"
1230 "consistency check failed." << endl;
1232 preamble = lex.getLongString("\\end_preamble");
1236 void BufferParams::readLanguage(Lexer & lex)
1238 if (!lex.next()) return;
1240 string const tmptok = lex.getString();
1242 // check if tmptok is part of tex_babel in tex-defs.h
1243 language = languages.getLanguage(tmptok);
1245 // Language tmptok was not found
1246 language = default_language;
1247 lyxerr << "Warning: Setting language `"
1248 << tmptok << "' to `" << language->lang()
1254 void BufferParams::readGraphicsDriver(Lexer & lex)
1256 if (!lex.next()) return;
1258 string const tmptok = lex.getString();
1259 // check if tmptok is part of tex_graphics in tex_defs.h
1262 string const test = tex_graphics[n++];
1264 if (test == tmptok) {
1265 graphicsDriver = tmptok;
1267 } else if (test == "") {
1269 "Warning: graphics driver `$$Token' not recognized!\n"
1270 " Setting graphics driver to `default'.\n");
1271 graphicsDriver = "default";
1278 void BufferParams::readBullets(Lexer & lex)
1280 if (!lex.next()) return;
1282 int const index = lex.getInteger();
1284 int temp_int = lex.getInteger();
1285 user_defined_bullet(index).setFont(temp_int);
1286 temp_bullet(index).setFont(temp_int);
1288 user_defined_bullet(index).setCharacter(temp_int);
1289 temp_bullet(index).setCharacter(temp_int);
1291 user_defined_bullet(index).setSize(temp_int);
1292 temp_bullet(index).setSize(temp_int);
1296 void BufferParams::readBulletsLaTeX(Lexer & lex)
1298 // The bullet class should be able to read this.
1299 if (!lex.next()) return;
1300 int const index = lex.getInteger();
1302 docstring const temp_str = lex.getDocString();
1304 user_defined_bullet(index).setText(temp_str);
1305 temp_bullet(index).setText(temp_str);
1309 string const BufferParams::paperSizeName() const
1311 char real_papersize = papersize;
1312 if (real_papersize == PAPER_DEFAULT)
1313 real_papersize = lyxrc.default_papersize;
1315 switch (real_papersize) {
1324 case PAPER_USEXECUTIVE:
1328 case PAPER_USLETTER:
1335 string const BufferParams::dvips_options() const
1340 && papersize == PAPER_CUSTOM
1341 && !lyxrc.print_paper_dimension_flag.empty()
1342 && !paperwidth.empty()
1343 && !paperheight.empty()) {
1344 // using a custom papersize
1345 result = lyxrc.print_paper_dimension_flag;
1346 result += ' ' + paperwidth;
1347 result += ',' + paperheight;
1349 string const paper_option = paperSizeName();
1350 if (paper_option != "letter" ||
1351 orientation != ORIENTATION_LANDSCAPE) {
1352 // dvips won't accept -t letter -t landscape.
1353 // In all other cases, include the paper size
1355 result = lyxrc.print_paper_flag;
1356 result += ' ' + paper_option;
1359 if (orientation == ORIENTATION_LANDSCAPE &&
1360 papersize != PAPER_CUSTOM)
1361 result += ' ' + lyxrc.print_landscape_flag;
1366 string const BufferParams::babelCall(string const & lang_opts) const
1368 string tmp = lyxrc.language_package;
1369 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1370 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1375 string const BufferParams::loadFonts(string const & rm,
1376 string const & sf, string const & tt,
1377 bool const & sc, bool const & osf,
1378 int const & sfscale, int const & ttscale) const
1380 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1381 several packages have been replaced by others, that might not
1382 be installed on every system. We have to take care for that
1383 (see psnfss.pdf). We try to support all psnfss fonts as well
1384 as the fonts that have become de facto standard in the LaTeX
1385 world (e.g. Latin Modern). We do not support obsolete fonts
1386 (like PSLatex). In general, it should be possible to mix any
1387 rm font with any sf or tt font, respectively. (JSpitzm)
1389 -- separate math fonts.
1392 if (rm == "default" && sf == "default" && tt == "default")
1399 // Computer Modern (must be explicitely selectable -- there might be classes
1400 // that define a different default font!
1402 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1403 // osf for Computer Modern needs eco.sty
1405 os << "\\usepackage{eco}\n";
1407 // Latin Modern Roman
1408 else if (rm == "lmodern")
1409 os << "\\usepackage{lmodern}\n";
1411 else if (rm == "ae") {
1412 // not needed when using OT1 font encoding.
1413 if (lyxrc.fontenc != "default")
1414 os << "\\usepackage{ae,aecompl}\n";
1417 else if (rm == "times") {
1418 // try to load the best available package
1419 if (LaTeXFeatures::isAvailable("mathptmx"))
1420 os << "\\usepackage{mathptmx}\n";
1421 else if (LaTeXFeatures::isAvailable("mathptm"))
1422 os << "\\usepackage{mathptm}\n";
1424 os << "\\usepackage{times}\n";
1427 else if (rm == "palatino") {
1428 // try to load the best available package
1429 if (LaTeXFeatures::isAvailable("mathpazo")) {
1430 os << "\\usepackage";
1436 // "osf" includes "sc"!
1440 os << "{mathpazo}\n";
1442 else if (LaTeXFeatures::isAvailable("mathpple"))
1443 os << "\\usepackage{mathpple}\n";
1445 os << "\\usepackage{palatino}\n";
1448 else if (rm == "utopia") {
1449 // fourier supersedes utopia.sty, but does
1450 // not work with OT1 encoding.
1451 if (LaTeXFeatures::isAvailable("fourier")
1452 && lyxrc.fontenc != "default") {
1453 os << "\\usepackage";
1464 os << "{fourier}\n";
1467 os << "\\usepackage{utopia}\n";
1469 // Bera (complete fontset)
1470 else if (rm == "bera" && sf == "default" && tt == "default")
1471 os << "\\usepackage{bera}\n";
1473 else if (rm != "default")
1474 os << "\\usepackage" << "{" << rm << "}\n";
1477 // Helvetica, Bera Sans
1478 if (sf == "helvet" || sf == "berasans") {
1480 os << "\\usepackage[scaled=" << float(sfscale) / 100
1481 << "]{" << sf << "}\n";
1483 os << "\\usepackage{" << sf << "}\n";
1486 else if (sf == "avant")
1487 os << "\\usepackage{" << sf << "}\n";
1488 // Computer Modern, Latin Modern, CM Bright
1489 else if (sf != "default")
1490 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1492 // monospaced/typewriter
1493 // Courier, LuxiMono
1494 if (tt == "luximono" || tt == "beramono") {
1496 os << "\\usepackage[scaled=" << float(ttscale) / 100
1497 << "]{" << tt << "}\n";
1499 os << "\\usepackage{" << tt << "}\n";
1502 else if (tt == "courier" )
1503 os << "\\usepackage{" << tt << "}\n";
1504 // Computer Modern, Latin Modern, CM Bright
1505 else if (tt != "default")
1506 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1512 Encoding const & BufferParams::encoding() const
1514 if (inputenc == "auto" || inputenc == "default")
1515 return *(language->encoding());
1516 Encoding const * const enc =
1517 encodings.getFromLaTeXName(inputenc);
1520 lyxerr << "Unknown inputenc value `" << inputenc
1521 << "'. Using `auto' instead." << endl;
1522 return *(language->encoding());
1526 biblio::CiteEngine BufferParams::getEngine() const
1528 // FIXME the class should provide the numerical/
1529 // authoryear choice
1530 if (getTextClass().provides("natbib")
1531 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1532 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1533 return cite_engine_;
1537 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1539 cite_engine_ = cite_engine;