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/lyxalgo.h" // for lyx::count
43 #include "support/convert.h"
44 #include "support/Translator.h"
46 #include <boost/array.hpp>
52 using std::istringstream;
54 using std::ostringstream;
57 using lyx::support::bformat;
58 using lyx::support::rtrim;
59 using lyx::support::tokenPos;
62 static char const * const string_paragraph_separation[] = {
67 static char const * const string_quotes_language[] = {
68 "english", "swedish", "german", "polish", "french", "danish", ""
72 static char const * const string_papersize[] = {
73 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
74 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
78 static char const * const string_orientation[] = {
79 "portrait", "landscape", ""
83 static char const * const string_footnotekinds[] = {
84 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
88 static char const * const tex_graphics[] = {
89 "default", "dvips", "dvitops", "emtex",
90 "ln", "oztex", "textures", "none", ""
99 // Paragraph separation
100 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
103 ParSepTranslator const init_parseptranslator()
105 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
106 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
111 ParSepTranslator const & parseptranslator()
113 static ParSepTranslator translator = init_parseptranslator();
119 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
122 QuotesLangTranslator const init_quoteslangtranslator()
124 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
125 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
126 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
127 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
128 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
129 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
134 QuotesLangTranslator const & quoteslangtranslator()
136 static QuotesLangTranslator translator = init_quoteslangtranslator();
142 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
145 PaperSizeTranslator const init_papersizetranslator()
147 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
148 translator.addPair(string_papersize[1], PAPER_CUSTOM);
149 translator.addPair(string_papersize[2], PAPER_USLETTER);
150 translator.addPair(string_papersize[3], PAPER_USLEGAL);
151 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
152 translator.addPair(string_papersize[5], PAPER_A3);
153 translator.addPair(string_papersize[6], PAPER_A4);
154 translator.addPair(string_papersize[7], PAPER_A5);
155 translator.addPair(string_papersize[8], PAPER_B3);
156 translator.addPair(string_papersize[9], PAPER_B4);
157 translator.addPair(string_papersize[10], PAPER_B5);
162 PaperSizeTranslator const & papersizetranslator()
164 static PaperSizeTranslator translator = init_papersizetranslator();
170 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
173 PaperOrientationTranslator const init_paperorientationtranslator()
175 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
176 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
181 PaperOrientationTranslator const & paperorientationtranslator()
183 static PaperOrientationTranslator translator = init_paperorientationtranslator();
189 typedef Translator<int, TextClass::PageSides> SidesTranslator;
192 SidesTranslator const init_sidestranslator()
194 SidesTranslator translator(1, TextClass::OneSide);
195 translator.addPair(2, TextClass::TwoSides);
200 SidesTranslator const & sidestranslator()
202 static SidesTranslator translator = init_sidestranslator();
208 typedef Translator<int, BufferParams::Package> PackageTranslator;
211 PackageTranslator const init_packagetranslator()
213 PackageTranslator translator(0, BufferParams::package_off);
214 translator.addPair(1, BufferParams::package_auto);
215 translator.addPair(2, BufferParams::package_on);
220 PackageTranslator const & packagetranslator()
222 static PackageTranslator translator = init_packagetranslator();
228 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
231 CiteEngineTranslator const init_citeenginetranslator()
233 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
234 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
235 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
236 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
241 CiteEngineTranslator const & citeenginetranslator()
243 static CiteEngineTranslator translator = init_citeenginetranslator();
249 typedef Translator<string, Spacing::Space> SpaceTranslator;
252 SpaceTranslator const init_spacetranslator()
254 SpaceTranslator translator("default", Spacing::Default);
255 translator.addPair("single", Spacing::Single);
256 translator.addPair("onehalf", Spacing::Onehalf);
257 translator.addPair("double", Spacing::Double);
258 translator.addPair("other", Spacing::Other);
263 SpaceTranslator const & spacetranslator()
265 static SpaceTranslator translator = init_spacetranslator();
270 textclass_type defaultTextclass()
272 // Initialize textclass to point to article. if `first' is
273 // true in the returned pair, then `second' is the textclass
274 // number; if it is false, second is 0. In both cases, second
276 return textclasslist.numberOfClass("article").second;
282 class BufferParams::Impl
287 AuthorList authorlist;
288 BranchList branchlist;
289 boost::array<Bullet, 4> temp_bullets;
290 boost::array<Bullet, 4> user_defined_bullets;
292 /** This is the amount of space used for paragraph_separation "skip",
293 * and for detached paragraphs in "indented" documents.
299 BufferParams::Impl::Impl()
300 : defskip(VSpace::MEDSKIP)
302 // set initial author
304 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
309 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
313 return new BufferParams::Impl(*ptr);
317 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
323 BufferParams::BufferParams()
324 : textclass(defaultTextclass()), pimpl_(new Impl)
326 paragraph_separation = PARSEP_INDENT;
327 quotes_language = InsetQuotes::EnglishQ;
328 fontsize = "default";
331 papersize = PAPER_DEFAULT;
332 orientation = ORIENTATION_PORTRAIT;
333 use_geometry = false;
334 use_amsmath = package_auto;
335 use_esint = package_auto;
336 cite_engine_ = biblio::ENGINE_BASIC;
337 use_bibtopic = false;
338 trackChanges = false;
339 outputChanges = false;
342 language = default_language;
343 fontsRoman = "default";
344 fontsSans = "default";
345 fontsTypewriter = "default";
346 fontsDefaultFamily = "default";
349 fontsSansScale = 100;
350 fontsTypewriterScale = 100;
352 graphicsDriver = "default";
353 sides = TextClass::OneSide;
355 listings_params = string();
356 pagestyle = "default";
358 for (int iter = 0; iter < 4; ++iter) {
359 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
360 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
365 BufferParams::~BufferParams()
369 docstring const BufferParams::B_(string const & l10n) const
371 BOOST_ASSERT(language);
372 return getMessages(language->code()).get(l10n);
376 AuthorList & BufferParams::authors()
378 return pimpl_->authorlist;
382 AuthorList const & BufferParams::authors() const
384 return pimpl_->authorlist;
388 BranchList & BufferParams::branchlist()
390 return pimpl_->branchlist;
394 BranchList const & BufferParams::branchlist() const
396 return pimpl_->branchlist;
400 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
402 BOOST_ASSERT(index < 4);
403 return pimpl_->temp_bullets[index];
407 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
409 BOOST_ASSERT(index < 4);
410 return pimpl_->temp_bullets[index];
414 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
416 BOOST_ASSERT(index < 4);
417 return pimpl_->user_defined_bullets[index];
421 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
423 BOOST_ASSERT(index < 4);
424 return pimpl_->user_defined_bullets[index];
428 Spacing & BufferParams::spacing()
430 return pimpl_->spacing;
434 Spacing const & BufferParams::spacing() const
436 return pimpl_->spacing;
440 VSpace const & BufferParams::getDefSkip() const
442 return pimpl_->defskip;
446 void BufferParams::setDefSkip(VSpace const & vs)
448 pimpl_->defskip = vs;
452 string const BufferParams::readToken(Lexer & lex, string const & token)
454 if (token == "\\textclass") {
456 string const classname = lex.getString();
457 pair<bool, lyx::textclass_type> pp =
458 textclasslist.numberOfClass(classname);
460 textclass = pp.second;
462 // if text class does not exist, try to load it from filepath
463 pp = textclasslist.addTextClass(classname, filepath);
465 textclass = pp.second;
467 textclass = defaultTextclass();
471 // FIXME: isTeXClassAvailable will try to load the layout file, but will
472 // fail because of the lack of path info. Warnings will be given although
473 // the layout file will be correctly loaded later.
474 if (!getTextClass().isTeXClassAvailable()) {
475 docstring const msg =
476 bformat(_("The layout file requested by this document,\n"
478 "is not usable. This is probably because a LaTeX\n"
479 "class or style file required by it is not\n"
480 "available. See the Customization documentation\n"
481 "for more information.\n"), from_utf8(classname));
482 frontend::Alert::warning(_("Document class not available"),
483 msg + _("LyX will not be able to produce output."));
485 } else if (token == "\\begin_preamble") {
487 } else if (token == "\\options") {
489 options = lex.getString();
490 } else if (token == "\\language") {
492 } else if (token == "\\inputencoding") {
494 } else if (token == "\\graphics") {
495 readGraphicsDriver(lex);
496 } else if (token == "\\font_roman") {
498 } else if (token == "\\font_sans") {
500 } else if (token == "\\font_typewriter") {
501 lex >> fontsTypewriter;
502 } else if (token == "\\font_default_family") {
503 lex >> fontsDefaultFamily;
504 } else if (token == "\\font_sc") {
506 } else if (token == "\\font_osf") {
508 } else if (token == "\\font_sf_scale") {
509 lex >> fontsSansScale;
510 } else if (token == "\\font_tt_scale") {
511 lex >> fontsTypewriterScale;
512 } else if (token == "\\paragraph_separation") {
515 paragraph_separation = parseptranslator().find(parsep);
516 } else if (token == "\\defskip") {
518 pimpl_->defskip = VSpace(lex.getString());
519 } else if (token == "\\quotes_language") {
522 quotes_language = quoteslangtranslator().find(quotes_lang);
523 } else if (token == "\\papersize") {
526 papersize = papersizetranslator().find(ppsize);
527 } else if (token == "\\use_geometry") {
529 } else if (token == "\\use_amsmath") {
532 use_amsmath = packagetranslator().find(use_ams);
533 } else if (token == "\\use_esint") {
536 use_esint = packagetranslator().find(useesint);
537 } else if (token == "\\cite_engine") {
540 cite_engine_ = citeenginetranslator().find(engine);
541 } else if (token == "\\use_bibtopic") {
543 } else if (token == "\\tracking_changes") {
545 } else if (token == "\\output_changes") {
546 lex >> outputChanges;
547 } else if (token == "\\branch") {
549 docstring branch = lex.getDocString();
550 branchlist().add(branch);
553 string const tok = lex.getString();
554 if (tok == "\\end_branch")
556 Branch * branch_ptr = branchlist().find(branch);
557 if (tok == "\\selected") {
560 branch_ptr->setSelected(lex.getInteger());
562 // not yet operational
563 if (tok == "\\color") {
565 string color = lex.getString();
567 branch_ptr->setColor(color);
568 // Update also the Color table:
570 color = lcolor.getX11Name(Color::background);
572 lcolor.setColor(to_utf8(branch), color);
576 } else if (token == "\\author") {
578 istringstream ss(lex.getString());
581 author_map.push_back(pimpl_->authorlist.record(a));
582 } else if (token == "\\paperorientation") {
585 orientation = paperorientationtranslator().find(orient);
586 } else if (token == "\\paperwidth") {
588 } else if (token == "\\paperheight") {
590 } else if (token == "\\leftmargin") {
592 } else if (token == "\\topmargin") {
594 } else if (token == "\\rightmargin") {
596 } else if (token == "\\bottommargin") {
598 } else if (token == "\\headheight") {
600 } else if (token == "\\headsep") {
602 } else if (token == "\\footskip") {
604 } else if (token == "\\paperfontsize") {
606 } else if (token == "\\papercolumns") {
608 } else if (token == "\\listings_params") {
611 // validate par and produce a valid listings parameter string
613 listings_params = InsetListingsParams(par).params();
614 } catch (invalidParam & e) {
615 lyxerr << "Invalid parameter string " << par << endl;
616 lyxerr << e.what() << endl;
617 listings_params = string();
619 } else if (token == "\\papersides") {
622 sides = sidestranslator().find(psides);
623 } else if (token == "\\paperpagestyle") {
625 } else if (token == "\\bullet") {
627 } else if (token == "\\bulletLaTeX") {
628 readBulletsLaTeX(lex);
629 } else if (token == "\\secnumdepth") {
631 } else if (token == "\\tocdepth") {
633 } else if (token == "\\spacing") {
637 if (nspacing == "other") {
640 spacing().set(spacetranslator().find(nspacing), tmp_val);
641 } else if (token == "\\float_placement") {
642 lex >> float_placement;
651 void BufferParams::writeFile(ostream & os) const
653 // The top of the file is written by the buffer.
654 // Prints out the buffer info into the .lyx file given by file
657 os << "\\textclass " << textclasslist[textclass].name() << '\n';
660 if (!preamble.empty()) {
661 // remove '\n' from the end of preamble
662 string const tmppreamble = rtrim(preamble, "\n");
663 os << "\\begin_preamble\n"
665 << "\n\\end_preamble\n";
669 if (!options.empty()) {
670 os << "\\options " << options << '\n';
673 // then the text parameters
674 if (language != ignore_language)
675 os << "\\language " << language->lang() << '\n';
676 os << "\\inputencoding " << inputenc
677 << "\n\\font_roman " << fontsRoman
678 << "\n\\font_sans " << fontsSans
679 << "\n\\font_typewriter " << fontsTypewriter
680 << "\n\\font_default_family " << fontsDefaultFamily
681 << "\n\\font_sc " << convert<string>(fontsSC)
682 << "\n\\font_osf " << convert<string>(fontsOSF)
683 << "\n\\font_sf_scale " << fontsSansScale
684 << "\n\\font_tt_scale " << fontsTypewriterScale
685 << "\n\\graphics " << graphicsDriver << '\n';
687 if (!float_placement.empty()) {
688 os << "\\float_placement " << float_placement << '\n';
690 os << "\\paperfontsize " << fontsize << '\n';
692 spacing().writeFile(os);
694 os << "\\papersize " << string_papersize[papersize]
695 << "\n\\use_geometry " << convert<string>(use_geometry)
696 << "\n\\use_amsmath " << use_amsmath
697 << "\n\\use_esint " << use_esint
698 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
699 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
700 << "\n\\paperorientation " << string_orientation[orientation]
703 BranchList::const_iterator it = branchlist().begin();
704 BranchList::const_iterator end = branchlist().end();
705 for (; it != end; ++it) {
706 os << "\\branch " << to_utf8(it->getBranch())
707 << "\n\\selected " << it->getSelected()
708 << "\n\\color " << lyx::X11hexname(it->getColor())
713 if (!paperwidth.empty())
714 os << "\\paperwidth "
715 << VSpace(paperwidth).asLyXCommand() << '\n';
716 if (!paperheight.empty())
717 os << "\\paperheight "
718 << VSpace(paperheight).asLyXCommand() << '\n';
719 if (!leftmargin.empty())
720 os << "\\leftmargin "
721 << VSpace(leftmargin).asLyXCommand() << '\n';
722 if (!topmargin.empty())
724 << VSpace(topmargin).asLyXCommand() << '\n';
725 if (!rightmargin.empty())
726 os << "\\rightmargin "
727 << VSpace(rightmargin).asLyXCommand() << '\n';
728 if (!bottommargin.empty())
729 os << "\\bottommargin "
730 << VSpace(bottommargin).asLyXCommand() << '\n';
731 if (!headheight.empty())
732 os << "\\headheight "
733 << VSpace(headheight).asLyXCommand() << '\n';
734 if (!headsep.empty())
736 << VSpace(headsep).asLyXCommand() << '\n';
737 if (!footskip.empty())
739 << VSpace(footskip).asLyXCommand() << '\n';
740 os << "\\secnumdepth " << secnumdepth
741 << "\n\\tocdepth " << tocdepth
742 << "\n\\paragraph_separation "
743 << string_paragraph_separation[paragraph_separation]
744 << "\n\\defskip " << getDefSkip().asLyXCommand()
745 << "\n\\quotes_language "
746 << string_quotes_language[quotes_language]
747 << "\n\\papercolumns " << columns
748 << "\n\\papersides " << sides
749 << "\n\\paperpagestyle " << pagestyle << '\n';
750 if (!listings_params.empty())
751 os << "\\listings_params \"" <<
752 InsetListingsParams(listings_params).encodedString() << "\"\n";
753 for (int i = 0; i < 4; ++i) {
754 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
755 if (user_defined_bullet(i).getFont() != -1) {
756 os << "\\bullet " << i << " "
757 << user_defined_bullet(i).getFont() << " "
758 << user_defined_bullet(i).getCharacter() << " "
759 << user_defined_bullet(i).getSize() << "\n";
763 os << "\\bulletLaTeX " << i << " \""
764 << lyx::to_ascii(user_defined_bullet(i).getText())
770 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
771 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
773 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
774 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
775 for (; a_it != a_end; ++a_it) {
776 os << "\\author " << a_it->second << "\n";
781 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
782 TexRow & texrow) const
784 os << "\\documentclass";
786 TextClass const & tclass = getTextClass();
788 ostringstream clsoptions; // the document class options.
790 if (tokenPos(tclass.opt_fontsize(),
791 '|', fontsize) >= 0) {
792 // only write if existing in list (and not default)
793 clsoptions << fontsize << "pt,";
796 // custom, A3, B3 and B4 paper sizes need geometry
797 bool nonstandard_papersize = papersize == PAPER_B3
798 || papersize == PAPER_B4
799 || papersize == PAPER_A3
800 || papersize == PAPER_CUSTOM;
805 clsoptions << "a4paper,";
808 clsoptions << "letterpaper,";
811 clsoptions << "a5paper,";
814 clsoptions << "b5paper,";
816 case PAPER_USEXECUTIVE:
817 clsoptions << "executivepaper,";
820 clsoptions << "legalpaper,";
832 if (sides != tclass.sides()) {
834 case TextClass::OneSide:
835 clsoptions << "oneside,";
837 case TextClass::TwoSides:
838 clsoptions << "twoside,";
844 if (columns != tclass.columns()) {
846 clsoptions << "twocolumn,";
848 clsoptions << "onecolumn,";
852 && orientation == ORIENTATION_LANDSCAPE)
853 clsoptions << "landscape,";
855 // language should be a parameter to \documentclass
856 if (language->babel() == "hebrew"
857 && default_language->babel() != "hebrew")
858 // This seems necessary
859 features.useLanguage(default_language);
861 ostringstream language_options;
862 bool const use_babel = features.useBabel();
864 language_options << features.getLanguages();
865 if (!language->babel().empty()) {
866 if (!language_options.str().empty())
867 language_options << ',';
868 language_options << language->babel();
870 if (lyxrc.language_global_options && !language_options.str().empty())
871 clsoptions << language_options.str() << ',';
874 // the user-defined options
875 if (!options.empty()) {
876 clsoptions << options << ',';
879 string strOptions(clsoptions.str());
880 if (!strOptions.empty()) {
881 strOptions = rtrim(strOptions, ",");
883 os << '[' << from_utf8(strOptions) << ']';
886 os << '{' << from_ascii(tclass.latexname()) << "}\n";
888 // end of \documentclass defs
890 // font selection must be done before loading fontenc.sty
892 loadFonts(fontsRoman, fontsSans,
893 fontsTypewriter, fontsSC, fontsOSF,
894 fontsSansScale, fontsTypewriterScale);
895 if (!fonts.empty()) {
896 os << from_ascii(fonts);
899 if (fontsDefaultFamily != "default")
900 os << "\\renewcommand{\\familydefault}{\\"
901 << from_ascii(fontsDefaultFamily) << "}\n";
902 // this one is not per buffer
903 if (lyxrc.fontenc != "default") {
904 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
909 // handle inputenc etc.
910 writeEncodingPreamble(os, features, texrow);
912 if (!listings_params.empty()) {
913 os << "\\usepackage{listings}\n";
916 // do not test validity because listings_params is supposed to be valid
917 string par = InsetListingsParams(listings_params).separatedParams(true);
918 os << from_ascii(par);
919 // count the number of newlines
920 for (size_t i = 0; i < par.size(); ++i)
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";
1157 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1158 for (int j = 0; j != nlines; ++j) {
1167 void BufferParams::useClassDefaults()
1169 TextClass const & tclass = textclasslist[textclass];
1171 sides = tclass.sides();
1172 columns = tclass.columns();
1173 pagestyle = tclass.pagestyle();
1174 options = tclass.options();
1175 // Only if class has a ToC hierarchy
1176 if (tclass.hasTocLevels()) {
1177 secnumdepth = tclass.secnumdepth();
1178 tocdepth = tclass.tocdepth();
1183 bool BufferParams::hasClassDefaults() const
1185 TextClass const & tclass = textclasslist[textclass];
1187 return (sides == tclass.sides()
1188 && columns == tclass.columns()
1189 && pagestyle == tclass.pagestyle()
1190 && options == tclass.options()
1191 && secnumdepth == tclass.secnumdepth()
1192 && tocdepth == tclass.tocdepth());
1196 TextClass const & BufferParams::getTextClass() const
1198 return textclasslist[textclass];
1202 Font const BufferParams::getFont() const
1204 Font f = getTextClass().defaultfont();
1205 f.setLanguage(language);
1206 if (fontsDefaultFamily == "rmdefault")
1207 f.setFamily(Font::ROMAN_FAMILY);
1208 else if (fontsDefaultFamily == "sfdefault")
1209 f.setFamily(Font::SANS_FAMILY);
1210 else if (fontsDefaultFamily == "ttdefault")
1211 f.setFamily(Font::TYPEWRITER_FAMILY);
1216 void BufferParams::readPreamble(Lexer & lex)
1218 if (lex.getString() != "\\begin_preamble")
1219 lyxerr << "Error (BufferParams::readPreamble):"
1220 "consistency check failed." << endl;
1222 preamble = lex.getLongString("\\end_preamble");
1226 void BufferParams::readLanguage(Lexer & lex)
1228 if (!lex.next()) return;
1230 string const tmptok = lex.getString();
1232 // check if tmptok is part of tex_babel in tex-defs.h
1233 language = languages.getLanguage(tmptok);
1235 // Language tmptok was not found
1236 language = default_language;
1237 lyxerr << "Warning: Setting language `"
1238 << tmptok << "' to `" << language->lang()
1244 void BufferParams::readGraphicsDriver(Lexer & lex)
1246 if (!lex.next()) return;
1248 string const tmptok = lex.getString();
1249 // check if tmptok is part of tex_graphics in tex_defs.h
1252 string const test = tex_graphics[n++];
1254 if (test == tmptok) {
1255 graphicsDriver = tmptok;
1257 } else if (test == "") {
1259 "Warning: graphics driver `$$Token' not recognized!\n"
1260 " Setting graphics driver to `default'.\n");
1261 graphicsDriver = "default";
1268 void BufferParams::readBullets(Lexer & lex)
1270 if (!lex.next()) return;
1272 int const index = lex.getInteger();
1274 int temp_int = lex.getInteger();
1275 user_defined_bullet(index).setFont(temp_int);
1276 temp_bullet(index).setFont(temp_int);
1278 user_defined_bullet(index).setCharacter(temp_int);
1279 temp_bullet(index).setCharacter(temp_int);
1281 user_defined_bullet(index).setSize(temp_int);
1282 temp_bullet(index).setSize(temp_int);
1286 void BufferParams::readBulletsLaTeX(Lexer & lex)
1288 // The bullet class should be able to read this.
1289 if (!lex.next()) return;
1290 int const index = lex.getInteger();
1292 docstring const temp_str = lex.getDocString();
1294 user_defined_bullet(index).setText(temp_str);
1295 temp_bullet(index).setText(temp_str);
1299 string const BufferParams::paperSizeName() const
1301 char real_papersize = papersize;
1302 if (real_papersize == PAPER_DEFAULT)
1303 real_papersize = lyxrc.default_papersize;
1305 switch (real_papersize) {
1314 case PAPER_USEXECUTIVE:
1318 case PAPER_USLETTER:
1325 string const BufferParams::dvips_options() const
1330 && papersize == PAPER_CUSTOM
1331 && !lyxrc.print_paper_dimension_flag.empty()
1332 && !paperwidth.empty()
1333 && !paperheight.empty()) {
1334 // using a custom papersize
1335 result = lyxrc.print_paper_dimension_flag;
1336 result += ' ' + paperwidth;
1337 result += ',' + paperheight;
1339 string const paper_option = paperSizeName();
1340 if (paper_option != "letter" ||
1341 orientation != ORIENTATION_LANDSCAPE) {
1342 // dvips won't accept -t letter -t landscape.
1343 // In all other cases, include the paper size
1345 result = lyxrc.print_paper_flag;
1346 result += ' ' + paper_option;
1349 if (orientation == ORIENTATION_LANDSCAPE &&
1350 papersize != PAPER_CUSTOM)
1351 result += ' ' + lyxrc.print_landscape_flag;
1356 string const BufferParams::babelCall(string const & lang_opts) const
1358 string lang_pack = lyxrc.language_package;
1359 if (lang_pack != "\\usepackage{babel}")
1361 // suppress the babel call when there is no babel language defined
1362 // for the document language in the lib/languages file and if no
1363 // other languages are used (lang_opts is then empty)
1364 if (lang_opts.empty())
1366 if (!lyxrc.language_global_options)
1367 return "\\usepackage[" + lang_opts + "]{babel}";
1372 void BufferParams::writeEncodingPreamble(odocstream & os,
1373 LaTeXFeatures & features, TexRow & texrow) const
1375 if (inputenc == "auto") {
1376 string const doc_encoding =
1377 language->encoding()->latexName();
1378 Encoding::Package const package =
1379 language->encoding()->package();
1381 // Create a list with all the input encodings used
1383 std::set<string> encodings =
1384 features.getEncodingSet(doc_encoding);
1386 if (!encodings.empty() || package == Encoding::inputenc) {
1387 os << "\\usepackage[";
1388 std::set<string>::const_iterator it = encodings.begin();
1389 std::set<string>::const_iterator const end = encodings.end();
1391 os << from_ascii(*it);
1394 for (; it != end; ++it)
1395 os << ',' << from_ascii(*it);
1396 if (package == Encoding::inputenc) {
1397 if (!encodings.empty())
1399 os << from_ascii(doc_encoding);
1401 os << "]{inputenc}\n";
1404 if (package == Encoding::CJK) {
1405 os << "\\usepackage{CJK}\n";
1408 } else if (inputenc != "default") {
1409 switch (language->encoding()->package()) {
1410 case Encoding::none:
1412 case Encoding::inputenc:
1413 os << "\\usepackage[" << from_ascii(inputenc)
1418 os << "\\usepackage{CJK}\n";
1424 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1425 // armscii8 is used for Armenian.
1426 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1427 os << "\\usepackage{armtex}\n";
1433 string const BufferParams::loadFonts(string const & rm,
1434 string const & sf, string const & tt,
1435 bool const & sc, bool const & osf,
1436 int const & sfscale, int const & ttscale) const
1438 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1439 several packages have been replaced by others, that might not
1440 be installed on every system. We have to take care for that
1441 (see psnfss.pdf). We try to support all psnfss fonts as well
1442 as the fonts that have become de facto standard in the LaTeX
1443 world (e.g. Latin Modern). We do not support obsolete fonts
1444 (like PSLatex). In general, it should be possible to mix any
1445 rm font with any sf or tt font, respectively. (JSpitzm)
1447 -- separate math fonts.
1450 if (rm == "default" && sf == "default" && tt == "default")
1457 // Computer Modern (must be explicitely selectable -- there might be classes
1458 // that define a different default font!
1460 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1461 // osf for Computer Modern needs eco.sty
1463 os << "\\usepackage{eco}\n";
1465 // Latin Modern Roman
1466 else if (rm == "lmodern")
1467 os << "\\usepackage{lmodern}\n";
1469 else if (rm == "ae") {
1470 // not needed when using OT1 font encoding.
1471 if (lyxrc.fontenc != "default")
1472 os << "\\usepackage{ae,aecompl}\n";
1475 else if (rm == "times") {
1476 // try to load the best available package
1477 if (LaTeXFeatures::isAvailable("mathptmx"))
1478 os << "\\usepackage{mathptmx}\n";
1479 else if (LaTeXFeatures::isAvailable("mathptm"))
1480 os << "\\usepackage{mathptm}\n";
1482 os << "\\usepackage{times}\n";
1485 else if (rm == "palatino") {
1486 // try to load the best available package
1487 if (LaTeXFeatures::isAvailable("mathpazo")) {
1488 os << "\\usepackage";
1494 // "osf" includes "sc"!
1498 os << "{mathpazo}\n";
1500 else if (LaTeXFeatures::isAvailable("mathpple"))
1501 os << "\\usepackage{mathpple}\n";
1503 os << "\\usepackage{palatino}\n";
1506 else if (rm == "utopia") {
1507 // fourier supersedes utopia.sty, but does
1508 // not work with OT1 encoding.
1509 if (LaTeXFeatures::isAvailable("fourier")
1510 && lyxrc.fontenc != "default") {
1511 os << "\\usepackage";
1522 os << "{fourier}\n";
1525 os << "\\usepackage{utopia}\n";
1527 // Bera (complete fontset)
1528 else if (rm == "bera" && sf == "default" && tt == "default")
1529 os << "\\usepackage{bera}\n";
1531 else if (rm != "default")
1532 os << "\\usepackage" << "{" << rm << "}\n";
1535 // Helvetica, Bera Sans
1536 if (sf == "helvet" || sf == "berasans") {
1538 os << "\\usepackage[scaled=" << float(sfscale) / 100
1539 << "]{" << sf << "}\n";
1541 os << "\\usepackage{" << sf << "}\n";
1544 else if (sf == "avant")
1545 os << "\\usepackage{" << sf << "}\n";
1546 // Computer Modern, Latin Modern, CM Bright
1547 else if (sf != "default")
1548 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1550 // monospaced/typewriter
1551 // Courier, LuxiMono
1552 if (tt == "luximono" || tt == "beramono") {
1554 os << "\\usepackage[scaled=" << float(ttscale) / 100
1555 << "]{" << tt << "}\n";
1557 os << "\\usepackage{" << tt << "}\n";
1560 else if (tt == "courier" )
1561 os << "\\usepackage{" << tt << "}\n";
1562 // Computer Modern, Latin Modern, CM Bright
1563 else if (tt != "default")
1564 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1570 Encoding const & BufferParams::encoding() const
1572 if (inputenc == "auto" || inputenc == "default")
1573 return *(language->encoding());
1574 Encoding const * const enc =
1575 encodings.getFromLaTeXName(inputenc);
1578 lyxerr << "Unknown inputenc value `" << inputenc
1579 << "'. Using `auto' instead." << endl;
1580 return *(language->encoding());
1584 biblio::CiteEngine BufferParams::getEngine() const
1586 // FIXME the class should provide the numerical/
1587 // authoryear choice
1588 if (getTextClass().provides("natbib")
1589 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1590 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1591 return cite_engine_;
1595 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1597 cite_engine_ = cite_engine;