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"
40 #include "insets/InsetListingsParams.h"
42 #include "support/convert.h"
43 #include "support/Translator.h"
45 #include <boost/array.hpp>
53 using std::istringstream;
55 using std::ostringstream;
58 using lyx::support::bformat;
59 using lyx::support::rtrim;
60 using lyx::support::tokenPos;
63 static char const * const string_paragraph_separation[] = {
68 static char const * const string_quotes_language[] = {
69 "english", "swedish", "german", "polish", "french", "danish", ""
73 static char const * const string_papersize[] = {
74 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
75 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
79 static char const * const string_orientation[] = {
80 "portrait", "landscape", ""
84 static char const * const string_footnotekinds[] = {
85 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
89 static char const * const tex_graphics[] = {
90 "default", "dvips", "dvitops", "emtex",
91 "ln", "oztex", "textures", "none", ""
100 // Paragraph separation
101 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
104 ParSepTranslator const init_parseptranslator()
106 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
107 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
112 ParSepTranslator const & parseptranslator()
114 static ParSepTranslator translator = init_parseptranslator();
120 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
123 QuotesLangTranslator const init_quoteslangtranslator()
125 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
126 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
127 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
128 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
129 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
130 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
135 QuotesLangTranslator const & quoteslangtranslator()
137 static QuotesLangTranslator translator = init_quoteslangtranslator();
143 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
146 PaperSizeTranslator const init_papersizetranslator()
148 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
149 translator.addPair(string_papersize[1], PAPER_CUSTOM);
150 translator.addPair(string_papersize[2], PAPER_USLETTER);
151 translator.addPair(string_papersize[3], PAPER_USLEGAL);
152 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
153 translator.addPair(string_papersize[5], PAPER_A3);
154 translator.addPair(string_papersize[6], PAPER_A4);
155 translator.addPair(string_papersize[7], PAPER_A5);
156 translator.addPair(string_papersize[8], PAPER_B3);
157 translator.addPair(string_papersize[9], PAPER_B4);
158 translator.addPair(string_papersize[10], PAPER_B5);
163 PaperSizeTranslator const & papersizetranslator()
165 static PaperSizeTranslator translator = init_papersizetranslator();
171 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
174 PaperOrientationTranslator const init_paperorientationtranslator()
176 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
177 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
182 PaperOrientationTranslator const & paperorientationtranslator()
184 static PaperOrientationTranslator translator = init_paperorientationtranslator();
190 typedef Translator<int, TextClass::PageSides> SidesTranslator;
193 SidesTranslator const init_sidestranslator()
195 SidesTranslator translator(1, TextClass::OneSide);
196 translator.addPair(2, TextClass::TwoSides);
201 SidesTranslator const & sidestranslator()
203 static SidesTranslator translator = init_sidestranslator();
209 typedef Translator<int, BufferParams::Package> PackageTranslator;
212 PackageTranslator const init_packagetranslator()
214 PackageTranslator translator(0, BufferParams::package_off);
215 translator.addPair(1, BufferParams::package_auto);
216 translator.addPair(2, BufferParams::package_on);
221 PackageTranslator const & packagetranslator()
223 static PackageTranslator translator = init_packagetranslator();
229 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
232 CiteEngineTranslator const init_citeenginetranslator()
234 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
235 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
236 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
237 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
242 CiteEngineTranslator const & citeenginetranslator()
244 static CiteEngineTranslator translator = init_citeenginetranslator();
250 typedef Translator<string, Spacing::Space> SpaceTranslator;
253 SpaceTranslator const init_spacetranslator()
255 SpaceTranslator translator("default", Spacing::Default);
256 translator.addPair("single", Spacing::Single);
257 translator.addPair("onehalf", Spacing::Onehalf);
258 translator.addPair("double", Spacing::Double);
259 translator.addPair("other", Spacing::Other);
264 SpaceTranslator const & spacetranslator()
266 static SpaceTranslator translator = init_spacetranslator();
271 textclass_type defaultTextclass()
273 // Initialize textclass to point to article. if `first' is
274 // true in the returned pair, then `second' is the textclass
275 // number; if it is false, second is 0. In both cases, second
277 return textclasslist.numberOfClass("article").second;
283 class BufferParams::Impl
288 AuthorList authorlist;
289 BranchList branchlist;
290 boost::array<Bullet, 4> temp_bullets;
291 boost::array<Bullet, 4> user_defined_bullets;
293 /** This is the amount of space used for paragraph_separation "skip",
294 * and for detached paragraphs in "indented" documents.
300 BufferParams::Impl::Impl()
301 : defskip(VSpace::MEDSKIP)
303 // set initial author
305 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
310 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
314 return new BufferParams::Impl(*ptr);
318 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
324 BufferParams::BufferParams()
325 : textclass(defaultTextclass()), pimpl_(new Impl)
327 paragraph_separation = PARSEP_INDENT;
328 quotes_language = InsetQuotes::EnglishQ;
329 fontsize = "default";
332 papersize = PAPER_DEFAULT;
333 orientation = ORIENTATION_PORTRAIT;
334 use_geometry = false;
335 use_amsmath = package_auto;
336 use_esint = package_auto;
337 cite_engine_ = biblio::ENGINE_BASIC;
338 use_bibtopic = false;
339 trackChanges = false;
340 outputChanges = false;
343 language = default_language;
344 fontsRoman = "default";
345 fontsSans = "default";
346 fontsTypewriter = "default";
347 fontsDefaultFamily = "default";
350 fontsSansScale = 100;
351 fontsTypewriterScale = 100;
353 graphicsDriver = "default";
354 sides = TextClass::OneSide;
356 listings_params = string();
357 pagestyle = "default";
359 for (int iter = 0; iter < 4; ++iter) {
360 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
361 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
366 BufferParams::~BufferParams()
370 docstring const BufferParams::B_(string const & l10n) const
372 BOOST_ASSERT(language);
373 return getMessages(language->code()).get(l10n);
377 AuthorList & BufferParams::authors()
379 return pimpl_->authorlist;
383 AuthorList const & BufferParams::authors() const
385 return pimpl_->authorlist;
389 BranchList & BufferParams::branchlist()
391 return pimpl_->branchlist;
395 BranchList const & BufferParams::branchlist() const
397 return pimpl_->branchlist;
401 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
403 BOOST_ASSERT(index < 4);
404 return pimpl_->temp_bullets[index];
408 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
410 BOOST_ASSERT(index < 4);
411 return pimpl_->temp_bullets[index];
415 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
417 BOOST_ASSERT(index < 4);
418 return pimpl_->user_defined_bullets[index];
422 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
424 BOOST_ASSERT(index < 4);
425 return pimpl_->user_defined_bullets[index];
429 Spacing & BufferParams::spacing()
431 return pimpl_->spacing;
435 Spacing const & BufferParams::spacing() const
437 return pimpl_->spacing;
441 VSpace const & BufferParams::getDefSkip() const
443 return pimpl_->defskip;
447 void BufferParams::setDefSkip(VSpace const & vs)
449 pimpl_->defskip = vs;
453 string const BufferParams::readToken(Lexer & lex, string const & token)
455 if (token == "\\textclass") {
457 string const classname = lex.getString();
458 pair<bool, lyx::textclass_type> pp =
459 textclasslist.numberOfClass(classname);
461 textclass = pp.second;
463 // if text class does not exist, try to load it from filepath
464 pp = textclasslist.addTextClass(classname, filepath);
466 textclass = pp.second;
468 textclass = defaultTextclass();
472 // FIXME: isTeXClassAvailable will try to load the layout file, but will
473 // fail because of the lack of path info. Warnings will be given although
474 // the layout file will be correctly loaded later.
475 if (!getTextClass().isTeXClassAvailable()) {
476 docstring const msg =
477 bformat(_("The layout file requested by this document,\n"
479 "is not usable. This is probably because a LaTeX\n"
480 "class or style file required by it is not\n"
481 "available. See the Customization documentation\n"
482 "for more information.\n"), from_utf8(classname));
483 frontend::Alert::warning(_("Document class not available"),
484 msg + _("LyX will not be able to produce output."));
486 } else if (token == "\\begin_preamble") {
488 } else if (token == "\\options") {
490 options = lex.getString();
491 } else if (token == "\\language") {
493 } else if (token == "\\inputencoding") {
495 } else if (token == "\\graphics") {
496 readGraphicsDriver(lex);
497 } else if (token == "\\font_roman") {
499 } else if (token == "\\font_sans") {
501 } else if (token == "\\font_typewriter") {
502 lex >> fontsTypewriter;
503 } else if (token == "\\font_default_family") {
504 lex >> fontsDefaultFamily;
505 } else if (token == "\\font_sc") {
507 } else if (token == "\\font_osf") {
509 } else if (token == "\\font_sf_scale") {
510 lex >> fontsSansScale;
511 } else if (token == "\\font_tt_scale") {
512 lex >> fontsTypewriterScale;
513 } else if (token == "\\paragraph_separation") {
516 paragraph_separation = parseptranslator().find(parsep);
517 } else if (token == "\\defskip") {
519 pimpl_->defskip = VSpace(lex.getString());
520 } else if (token == "\\quotes_language") {
523 quotes_language = quoteslangtranslator().find(quotes_lang);
524 } else if (token == "\\papersize") {
527 papersize = papersizetranslator().find(ppsize);
528 } else if (token == "\\use_geometry") {
530 } else if (token == "\\use_amsmath") {
533 use_amsmath = packagetranslator().find(use_ams);
534 } else if (token == "\\use_esint") {
537 use_esint = packagetranslator().find(useesint);
538 } else if (token == "\\cite_engine") {
541 cite_engine_ = citeenginetranslator().find(engine);
542 } else if (token == "\\use_bibtopic") {
544 } else if (token == "\\tracking_changes") {
546 } else if (token == "\\output_changes") {
547 lex >> outputChanges;
548 } else if (token == "\\branch") {
550 docstring branch = lex.getDocString();
551 branchlist().add(branch);
554 string const tok = lex.getString();
555 if (tok == "\\end_branch")
557 Branch * branch_ptr = branchlist().find(branch);
558 if (tok == "\\selected") {
561 branch_ptr->setSelected(lex.getInteger());
563 // not yet operational
564 if (tok == "\\color") {
566 string color = lex.getString();
568 branch_ptr->setColor(color);
569 // Update also the Color table:
571 color = lcolor.getX11Name(Color::background);
573 lcolor.setColor(to_utf8(branch), color);
577 } else if (token == "\\author") {
579 istringstream ss(lex.getString());
582 author_map.push_back(pimpl_->authorlist.record(a));
583 } else if (token == "\\paperorientation") {
586 orientation = paperorientationtranslator().find(orient);
587 } else if (token == "\\paperwidth") {
589 } else if (token == "\\paperheight") {
591 } else if (token == "\\leftmargin") {
593 } else if (token == "\\topmargin") {
595 } else if (token == "\\rightmargin") {
597 } else if (token == "\\bottommargin") {
599 } else if (token == "\\headheight") {
601 } else if (token == "\\headsep") {
603 } else if (token == "\\footskip") {
605 } else if (token == "\\paperfontsize") {
607 } else if (token == "\\papercolumns") {
609 } else if (token == "\\listings_params") {
612 listings_params = InsetListingsParams(par).params();
613 } else if (token == "\\papersides") {
616 sides = sidestranslator().find(psides);
617 } else if (token == "\\paperpagestyle") {
619 } else if (token == "\\bullet") {
621 } else if (token == "\\bulletLaTeX") {
622 readBulletsLaTeX(lex);
623 } else if (token == "\\secnumdepth") {
625 } else if (token == "\\tocdepth") {
627 } else if (token == "\\spacing") {
631 if (nspacing == "other") {
634 spacing().set(spacetranslator().find(nspacing), tmp_val);
635 } else if (token == "\\float_placement") {
636 lex >> float_placement;
645 void BufferParams::writeFile(ostream & os) const
647 // The top of the file is written by the buffer.
648 // Prints out the buffer info into the .lyx file given by file
651 os << "\\textclass " << textclasslist[textclass].name() << '\n';
654 if (!preamble.empty()) {
655 // remove '\n' from the end of preamble
656 string const tmppreamble = rtrim(preamble, "\n");
657 os << "\\begin_preamble\n"
659 << "\n\\end_preamble\n";
663 if (!options.empty()) {
664 os << "\\options " << options << '\n';
667 // then the text parameters
668 if (language != ignore_language)
669 os << "\\language " << language->lang() << '\n';
670 os << "\\inputencoding " << inputenc
671 << "\n\\font_roman " << fontsRoman
672 << "\n\\font_sans " << fontsSans
673 << "\n\\font_typewriter " << fontsTypewriter
674 << "\n\\font_default_family " << fontsDefaultFamily
675 << "\n\\font_sc " << convert<string>(fontsSC)
676 << "\n\\font_osf " << convert<string>(fontsOSF)
677 << "\n\\font_sf_scale " << fontsSansScale
678 << "\n\\font_tt_scale " << fontsTypewriterScale
679 << "\n\\graphics " << graphicsDriver << '\n';
681 if (!float_placement.empty()) {
682 os << "\\float_placement " << float_placement << '\n';
684 os << "\\paperfontsize " << fontsize << '\n';
686 spacing().writeFile(os);
688 os << "\\papersize " << string_papersize[papersize]
689 << "\n\\use_geometry " << convert<string>(use_geometry)
690 << "\n\\use_amsmath " << use_amsmath
691 << "\n\\use_esint " << use_esint
692 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
693 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
694 << "\n\\paperorientation " << string_orientation[orientation]
697 BranchList::const_iterator it = branchlist().begin();
698 BranchList::const_iterator end = branchlist().end();
699 for (; it != end; ++it) {
700 os << "\\branch " << to_utf8(it->getBranch())
701 << "\n\\selected " << it->getSelected()
702 << "\n\\color " << lyx::X11hexname(it->getColor())
707 if (!paperwidth.empty())
708 os << "\\paperwidth "
709 << VSpace(paperwidth).asLyXCommand() << '\n';
710 if (!paperheight.empty())
711 os << "\\paperheight "
712 << VSpace(paperheight).asLyXCommand() << '\n';
713 if (!leftmargin.empty())
714 os << "\\leftmargin "
715 << VSpace(leftmargin).asLyXCommand() << '\n';
716 if (!topmargin.empty())
718 << VSpace(topmargin).asLyXCommand() << '\n';
719 if (!rightmargin.empty())
720 os << "\\rightmargin "
721 << VSpace(rightmargin).asLyXCommand() << '\n';
722 if (!bottommargin.empty())
723 os << "\\bottommargin "
724 << VSpace(bottommargin).asLyXCommand() << '\n';
725 if (!headheight.empty())
726 os << "\\headheight "
727 << VSpace(headheight).asLyXCommand() << '\n';
728 if (!headsep.empty())
730 << VSpace(headsep).asLyXCommand() << '\n';
731 if (!footskip.empty())
733 << VSpace(footskip).asLyXCommand() << '\n';
734 os << "\\secnumdepth " << secnumdepth
735 << "\n\\tocdepth " << tocdepth
736 << "\n\\paragraph_separation "
737 << string_paragraph_separation[paragraph_separation]
738 << "\n\\defskip " << getDefSkip().asLyXCommand()
739 << "\n\\quotes_language "
740 << string_quotes_language[quotes_language]
741 << "\n\\papercolumns " << columns
742 << "\n\\papersides " << sides
743 << "\n\\paperpagestyle " << pagestyle << '\n';
744 if (!listings_params.empty())
745 os << "\\listings_params \"" <<
746 InsetListingsParams(listings_params).encodedString() << "\"\n";
747 for (int i = 0; i < 4; ++i) {
748 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
749 if (user_defined_bullet(i).getFont() != -1) {
750 os << "\\bullet " << i << " "
751 << user_defined_bullet(i).getFont() << " "
752 << user_defined_bullet(i).getCharacter() << " "
753 << user_defined_bullet(i).getSize() << "\n";
757 os << "\\bulletLaTeX " << i << " \""
758 << lyx::to_ascii(user_defined_bullet(i).getText())
764 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
765 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
767 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
768 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
769 for (; a_it != a_end; ++a_it) {
770 if (a_it->second.used())
771 os << "\\author " << a_it->second << "\n";
773 os << "\\author " << Author() << "\n";
778 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
779 TexRow & texrow) const
781 os << "\\documentclass";
783 TextClass const & tclass = getTextClass();
785 ostringstream clsoptions; // the document class options.
787 if (tokenPos(tclass.opt_fontsize(),
788 '|', fontsize) >= 0) {
789 // only write if existing in list (and not default)
790 clsoptions << fontsize << "pt,";
793 // custom, A3, B3 and B4 paper sizes need geometry
794 bool nonstandard_papersize = papersize == PAPER_B3
795 || papersize == PAPER_B4
796 || papersize == PAPER_A3
797 || papersize == PAPER_CUSTOM;
802 clsoptions << "a4paper,";
805 clsoptions << "letterpaper,";
808 clsoptions << "a5paper,";
811 clsoptions << "b5paper,";
813 case PAPER_USEXECUTIVE:
814 clsoptions << "executivepaper,";
817 clsoptions << "legalpaper,";
829 if (sides != tclass.sides()) {
831 case TextClass::OneSide:
832 clsoptions << "oneside,";
834 case TextClass::TwoSides:
835 clsoptions << "twoside,";
841 if (columns != tclass.columns()) {
843 clsoptions << "twocolumn,";
845 clsoptions << "onecolumn,";
849 && orientation == ORIENTATION_LANDSCAPE)
850 clsoptions << "landscape,";
852 // language should be a parameter to \documentclass
853 if (language->babel() == "hebrew"
854 && default_language->babel() != "hebrew")
855 // This seems necessary
856 features.useLanguage(default_language);
858 ostringstream language_options;
859 bool const use_babel = features.useBabel();
861 language_options << features.getLanguages();
862 if (!language->babel().empty()) {
863 if (!language_options.str().empty())
864 language_options << ',';
865 language_options << language->babel();
867 if (lyxrc.language_global_options && !language_options.str().empty())
868 clsoptions << language_options.str() << ',';
871 // the user-defined options
872 if (!options.empty()) {
873 clsoptions << options << ',';
876 string strOptions(clsoptions.str());
877 if (!strOptions.empty()) {
878 strOptions = rtrim(strOptions, ",");
880 os << '[' << from_utf8(strOptions) << ']';
883 os << '{' << from_ascii(tclass.latexname()) << "}\n";
885 // end of \documentclass defs
887 // font selection must be done before loading fontenc.sty
889 loadFonts(fontsRoman, fontsSans,
890 fontsTypewriter, fontsSC, fontsOSF,
891 fontsSansScale, fontsTypewriterScale);
892 if (!fonts.empty()) {
893 os << from_ascii(fonts);
896 if (fontsDefaultFamily != "default")
897 os << "\\renewcommand{\\familydefault}{\\"
898 << from_ascii(fontsDefaultFamily) << "}\n";
901 // this one is not per buffer
902 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
903 if (lyxrc.fontenc != "default") {
904 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
905 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
906 << ",LFE,LAE]{fontenc}\n";
909 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
915 // handle inputenc etc.
916 writeEncodingPreamble(os, features, texrow);
918 if (!listings_params.empty()) {
919 os << "\\usepackage{listings}\n";
922 // do not test validity because listings_params is supposed to be valid
923 string par = InsetListingsParams(listings_params).separatedParams(true);
924 os << from_ascii(par);
925 // count the number of newlines
926 for (size_t i = 0; i < par.size(); ++i)
932 if (use_geometry || nonstandard_papersize) {
933 os << "\\usepackage{geometry}\n";
935 os << "\\geometry{verbose";
936 if (orientation == ORIENTATION_LANDSCAPE)
940 if (!paperwidth.empty())
942 << from_ascii(paperwidth);
943 if (!paperheight.empty())
944 os << ",paperheight="
945 << from_ascii(paperheight);
948 os << ",letterpaper";
953 case PAPER_USEXECUTIVE:
954 os << ",executivepaper";
975 // default papersize ie PAPER_DEFAULT
976 switch (lyxrc.default_papersize) {
977 case PAPER_DEFAULT: // keep compiler happy
979 os << ",letterpaper";
984 case PAPER_USEXECUTIVE:
985 os << ",executivepaper";
1005 if (!topmargin.empty())
1006 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1007 if (!bottommargin.empty())
1008 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1009 if (!leftmargin.empty())
1010 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1011 if (!rightmargin.empty())
1012 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1013 if (!headheight.empty())
1014 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1015 if (!headsep.empty())
1016 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1017 if (!footskip.empty())
1018 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1023 if (tokenPos(tclass.opt_pagestyle(),
1024 '|', pagestyle) >= 0) {
1025 if (pagestyle == "fancy") {
1026 os << "\\usepackage{fancyhdr}\n";
1029 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1033 // Only if class has a ToC hierarchy
1034 if (tclass.hasTocLevels()) {
1035 if (secnumdepth != tclass.secnumdepth()) {
1036 os << "\\setcounter{secnumdepth}{"
1041 if (tocdepth != tclass.tocdepth()) {
1042 os << "\\setcounter{tocdepth}{"
1049 if (paragraph_separation) {
1050 switch (getDefSkip().kind()) {
1051 case VSpace::SMALLSKIP:
1052 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1054 case VSpace::MEDSKIP:
1055 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1057 case VSpace::BIGSKIP:
1058 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1060 case VSpace::LENGTH:
1061 os << "\\setlength{\\parskip}{"
1062 << from_utf8(getDefSkip().length().asLatexString())
1065 default: // should never happen // Then delete it.
1066 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1071 os << "\\setlength{\\parindent}{0pt}\n";
1075 // If we use jurabib, we have to call babel here.
1076 if (use_babel && features.isRequired("jurabib")) {
1077 os << from_ascii(babelCall(language_options.str()))
1079 << from_ascii(features.getBabelOptions());
1083 // Now insert the LyX specific LaTeX commands...
1085 // The optional packages;
1086 docstring lyxpreamble(from_ascii(features.getPackages()));
1088 // this might be useful...
1089 lyxpreamble += "\n\\makeatletter\n";
1091 // Some macros LyX will need
1092 docstring tmppreamble(from_ascii(features.getMacros()));
1094 if (!tmppreamble.empty()) {
1095 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1096 "LyX specific LaTeX commands.\n"
1097 + tmppreamble + '\n';
1100 // the text class specific preamble
1101 tmppreamble = features.getTClassPreamble();
1102 if (!tmppreamble.empty()) {
1103 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1104 "Textclass specific LaTeX commands.\n"
1105 + tmppreamble + '\n';
1108 /* the user-defined preamble */
1109 if (!preamble.empty()) {
1111 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1112 "User specified LaTeX commands.\n"
1113 + from_utf8(preamble) + '\n';
1116 // Itemize bullet settings need to be last in case the user
1117 // defines their own bullets that use a package included
1118 // in the user-defined preamble -- ARRae
1119 // Actually it has to be done much later than that
1120 // since some packages like frenchb make modifications
1121 // at \begin{document} time -- JMarc
1122 docstring bullets_def;
1123 for (int i = 0; i < 4; ++i) {
1124 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1125 if (bullets_def.empty())
1126 bullets_def += "\\AtBeginDocument{\n";
1127 bullets_def += " \\def\\labelitemi";
1129 // `i' is one less than the item to modify
1136 bullets_def += "ii";
1142 bullets_def += '{' +
1143 user_defined_bullet(i).getText()
1148 if (!bullets_def.empty())
1149 lyxpreamble += bullets_def + "}\n\n";
1151 // We try to load babel late, in case it interferes
1152 // with other packages.
1153 // Jurabib has to be called after babel, though.
1154 if (use_babel && !features.isRequired("jurabib")) {
1156 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1157 lyxpreamble += from_utf8(features.getBabelOptions());
1160 lyxpreamble += "\\makeatother\n\n";
1163 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1164 for (int j = 0; j != nlines; ++j) {
1173 void BufferParams::useClassDefaults()
1175 TextClass const & tclass = textclasslist[textclass];
1177 sides = tclass.sides();
1178 columns = tclass.columns();
1179 pagestyle = tclass.pagestyle();
1180 options = tclass.options();
1181 // Only if class has a ToC hierarchy
1182 if (tclass.hasTocLevels()) {
1183 secnumdepth = tclass.secnumdepth();
1184 tocdepth = tclass.tocdepth();
1189 bool BufferParams::hasClassDefaults() const
1191 TextClass const & tclass = textclasslist[textclass];
1193 return (sides == tclass.sides()
1194 && columns == tclass.columns()
1195 && pagestyle == tclass.pagestyle()
1196 && options == tclass.options()
1197 && secnumdepth == tclass.secnumdepth()
1198 && tocdepth == tclass.tocdepth());
1202 TextClass const & BufferParams::getTextClass() const
1204 return textclasslist[textclass];
1208 Font const BufferParams::getFont() const
1210 Font f = getTextClass().defaultfont();
1211 f.setLanguage(language);
1212 if (fontsDefaultFamily == "rmdefault")
1213 f.setFamily(Font::ROMAN_FAMILY);
1214 else if (fontsDefaultFamily == "sfdefault")
1215 f.setFamily(Font::SANS_FAMILY);
1216 else if (fontsDefaultFamily == "ttdefault")
1217 f.setFamily(Font::TYPEWRITER_FAMILY);
1222 void BufferParams::readPreamble(Lexer & lex)
1224 if (lex.getString() != "\\begin_preamble")
1225 lyxerr << "Error (BufferParams::readPreamble):"
1226 "consistency check failed." << endl;
1228 preamble = lex.getLongString("\\end_preamble");
1232 void BufferParams::readLanguage(Lexer & lex)
1234 if (!lex.next()) return;
1236 string const tmptok = lex.getString();
1238 // check if tmptok is part of tex_babel in tex-defs.h
1239 language = languages.getLanguage(tmptok);
1241 // Language tmptok was not found
1242 language = default_language;
1243 lyxerr << "Warning: Setting language `"
1244 << tmptok << "' to `" << language->lang()
1250 void BufferParams::readGraphicsDriver(Lexer & lex)
1252 if (!lex.next()) return;
1254 string const tmptok = lex.getString();
1255 // check if tmptok is part of tex_graphics in tex_defs.h
1258 string const test = tex_graphics[n++];
1260 if (test == tmptok) {
1261 graphicsDriver = tmptok;
1263 } else if (test == "") {
1265 "Warning: graphics driver `$$Token' not recognized!\n"
1266 " Setting graphics driver to `default'.\n");
1267 graphicsDriver = "default";
1274 void BufferParams::readBullets(Lexer & lex)
1276 if (!lex.next()) return;
1278 int const index = lex.getInteger();
1280 int temp_int = lex.getInteger();
1281 user_defined_bullet(index).setFont(temp_int);
1282 temp_bullet(index).setFont(temp_int);
1284 user_defined_bullet(index).setCharacter(temp_int);
1285 temp_bullet(index).setCharacter(temp_int);
1287 user_defined_bullet(index).setSize(temp_int);
1288 temp_bullet(index).setSize(temp_int);
1292 void BufferParams::readBulletsLaTeX(Lexer & lex)
1294 // The bullet class should be able to read this.
1295 if (!lex.next()) return;
1296 int const index = lex.getInteger();
1298 docstring const temp_str = lex.getDocString();
1300 user_defined_bullet(index).setText(temp_str);
1301 temp_bullet(index).setText(temp_str);
1305 string const BufferParams::paperSizeName() const
1307 char real_papersize = papersize;
1308 if (real_papersize == PAPER_DEFAULT)
1309 real_papersize = lyxrc.default_papersize;
1311 switch (real_papersize) {
1320 case PAPER_USEXECUTIVE:
1324 case PAPER_USLETTER:
1331 string const BufferParams::dvips_options() const
1336 && papersize == PAPER_CUSTOM
1337 && !lyxrc.print_paper_dimension_flag.empty()
1338 && !paperwidth.empty()
1339 && !paperheight.empty()) {
1340 // using a custom papersize
1341 result = lyxrc.print_paper_dimension_flag;
1342 result += ' ' + paperwidth;
1343 result += ',' + paperheight;
1345 string const paper_option = paperSizeName();
1346 if (paper_option != "letter" ||
1347 orientation != ORIENTATION_LANDSCAPE) {
1348 // dvips won't accept -t letter -t landscape.
1349 // In all other cases, include the paper size
1351 result = lyxrc.print_paper_flag;
1352 result += ' ' + paper_option;
1355 if (orientation == ORIENTATION_LANDSCAPE &&
1356 papersize != PAPER_CUSTOM)
1357 result += ' ' + lyxrc.print_landscape_flag;
1362 string const BufferParams::babelCall(string const & lang_opts) const
1364 string lang_pack = lyxrc.language_package;
1365 if (lang_pack != "\\usepackage{babel}")
1367 // suppress the babel call when there is no babel language defined
1368 // for the document language in the lib/languages file and if no
1369 // other languages are used (lang_opts is then empty)
1370 if (lang_opts.empty())
1372 if (!lyxrc.language_global_options)
1373 return "\\usepackage[" + lang_opts + "]{babel}";
1378 void BufferParams::writeEncodingPreamble(odocstream & os,
1379 LaTeXFeatures & features, TexRow & texrow) const
1381 if (inputenc == "auto") {
1382 string const doc_encoding =
1383 language->encoding()->latexName();
1384 Encoding::Package const package =
1385 language->encoding()->package();
1387 // Create a list with all the input encodings used
1389 std::set<string> encodings =
1390 features.getEncodingSet(doc_encoding);
1392 if (!encodings.empty() || package == Encoding::inputenc) {
1393 os << "\\usepackage[";
1394 std::set<string>::const_iterator it = encodings.begin();
1395 std::set<string>::const_iterator const end = encodings.end();
1397 os << from_ascii(*it);
1400 for (; it != end; ++it)
1401 os << ',' << from_ascii(*it);
1402 if (package == Encoding::inputenc) {
1403 if (!encodings.empty())
1405 os << from_ascii(doc_encoding);
1407 os << "]{inputenc}\n";
1410 if (package == Encoding::CJK) {
1411 os << "\\usepackage{CJK}\n";
1414 } else if (inputenc != "default") {
1415 switch (encoding().package()) {
1416 case Encoding::none:
1418 case Encoding::inputenc:
1419 os << "\\usepackage[" << from_ascii(inputenc)
1424 os << "\\usepackage{CJK}\n";
1430 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1431 // armscii8 is used for Armenian.
1432 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1433 os << "\\usepackage{armtex}\n";
1439 string const BufferParams::loadFonts(string const & rm,
1440 string const & sf, string const & tt,
1441 bool const & sc, bool const & osf,
1442 int const & sfscale, int const & ttscale) const
1444 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1445 several packages have been replaced by others, that might not
1446 be installed on every system. We have to take care for that
1447 (see psnfss.pdf). We try to support all psnfss fonts as well
1448 as the fonts that have become de facto standard in the LaTeX
1449 world (e.g. Latin Modern). We do not support obsolete fonts
1450 (like PSLatex). In general, it should be possible to mix any
1451 rm font with any sf or tt font, respectively. (JSpitzm)
1453 -- separate math fonts.
1456 if (rm == "default" && sf == "default" && tt == "default")
1463 // Computer Modern (must be explicitely selectable -- there might be classes
1464 // that define a different default font!
1466 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1467 // osf for Computer Modern needs eco.sty
1469 os << "\\usepackage{eco}\n";
1471 // Latin Modern Roman
1472 else if (rm == "lmodern")
1473 os << "\\usepackage{lmodern}\n";
1475 else if (rm == "ae") {
1476 // not needed when using OT1 font encoding.
1477 if (lyxrc.fontenc != "default")
1478 os << "\\usepackage{ae,aecompl}\n";
1481 else if (rm == "times") {
1482 // try to load the best available package
1483 if (LaTeXFeatures::isAvailable("mathptmx"))
1484 os << "\\usepackage{mathptmx}\n";
1485 else if (LaTeXFeatures::isAvailable("mathptm"))
1486 os << "\\usepackage{mathptm}\n";
1488 os << "\\usepackage{times}\n";
1491 else if (rm == "palatino") {
1492 // try to load the best available package
1493 if (LaTeXFeatures::isAvailable("mathpazo")) {
1494 os << "\\usepackage";
1500 // "osf" includes "sc"!
1504 os << "{mathpazo}\n";
1506 else if (LaTeXFeatures::isAvailable("mathpple"))
1507 os << "\\usepackage{mathpple}\n";
1509 os << "\\usepackage{palatino}\n";
1512 else if (rm == "utopia") {
1513 // fourier supersedes utopia.sty, but does
1514 // not work with OT1 encoding.
1515 if (LaTeXFeatures::isAvailable("fourier")
1516 && lyxrc.fontenc != "default") {
1517 os << "\\usepackage";
1528 os << "{fourier}\n";
1531 os << "\\usepackage{utopia}\n";
1533 // Bera (complete fontset)
1534 else if (rm == "bera" && sf == "default" && tt == "default")
1535 os << "\\usepackage{bera}\n";
1537 else if (rm != "default")
1538 os << "\\usepackage" << "{" << rm << "}\n";
1541 // Helvetica, Bera Sans
1542 if (sf == "helvet" || sf == "berasans") {
1544 os << "\\usepackage[scaled=" << float(sfscale) / 100
1545 << "]{" << sf << "}\n";
1547 os << "\\usepackage{" << sf << "}\n";
1550 else if (sf == "avant")
1551 os << "\\usepackage{" << sf << "}\n";
1552 // Computer Modern, Latin Modern, CM Bright
1553 else if (sf != "default")
1554 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1556 // monospaced/typewriter
1557 // Courier, LuxiMono
1558 if (tt == "luximono" || tt == "beramono") {
1560 os << "\\usepackage[scaled=" << float(ttscale) / 100
1561 << "]{" << tt << "}\n";
1563 os << "\\usepackage{" << tt << "}\n";
1566 else if (tt == "courier" )
1567 os << "\\usepackage{" << tt << "}\n";
1568 // Computer Modern, Latin Modern, CM Bright
1569 else if (tt != "default")
1570 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1576 Encoding const & BufferParams::encoding() const
1578 if (inputenc == "auto" || inputenc == "default")
1579 return *(language->encoding());
1580 Encoding const * const enc =
1581 encodings.getFromLaTeXName(inputenc);
1584 lyxerr << "Unknown inputenc value `" << inputenc
1585 << "'. Using `auto' instead." << endl;
1586 return *(language->encoding());
1590 biblio::CiteEngine BufferParams::getEngine() const
1592 // FIXME the class should provide the numerical/
1593 // authoryear choice
1594 if (getTextClass().provides("natbib")
1595 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1596 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1597 return cite_engine_;
1601 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1603 cite_engine_ = cite_engine;