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"
22 #include "buffer_funcs.h"
28 #include "LaTeXFeatures.h"
30 #include "ModuleList.h"
35 #include "TextClassList.h"
36 #include "OutputParams.h"
41 #include "frontends/alert.h"
42 #include "insets/InsetListingsParams.h"
44 #include "support/convert.h"
45 #include "support/filetools.h"
46 #include "support/Translator.h"
48 #include <boost/array.hpp>
56 using std::istringstream;
58 using std::ostringstream;
61 using lyx::support::FileName;
62 using lyx::support::libFileSearch;
63 using lyx::support::bformat;
64 using lyx::support::rtrim;
65 using lyx::support::tokenPos;
68 static char const * const string_paragraph_separation[] = {
73 static char const * const string_quotes_language[] = {
74 "english", "swedish", "german", "polish", "french", "danish", ""
78 static char const * const string_papersize[] = {
79 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
80 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
84 static char const * const string_orientation[] = {
85 "portrait", "landscape", ""
89 static char const * const string_footnotekinds[] = {
90 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
94 static char const * const tex_graphics[] = {
95 "default", "dvips", "dvitops", "emtex",
96 "ln", "oztex", "textures", "none", ""
105 // Paragraph separation
106 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
109 ParSepTranslator const init_parseptranslator()
111 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
112 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
117 ParSepTranslator const & parseptranslator()
119 static ParSepTranslator translator = init_parseptranslator();
125 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
128 QuotesLangTranslator const init_quoteslangtranslator()
130 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
131 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
132 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
133 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
134 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
135 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
140 QuotesLangTranslator const & quoteslangtranslator()
142 static QuotesLangTranslator translator = init_quoteslangtranslator();
148 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
151 PaperSizeTranslator const init_papersizetranslator()
153 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
154 translator.addPair(string_papersize[1], PAPER_CUSTOM);
155 translator.addPair(string_papersize[2], PAPER_USLETTER);
156 translator.addPair(string_papersize[3], PAPER_USLEGAL);
157 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
158 translator.addPair(string_papersize[5], PAPER_A3);
159 translator.addPair(string_papersize[6], PAPER_A4);
160 translator.addPair(string_papersize[7], PAPER_A5);
161 translator.addPair(string_papersize[8], PAPER_B3);
162 translator.addPair(string_papersize[9], PAPER_B4);
163 translator.addPair(string_papersize[10], PAPER_B5);
168 PaperSizeTranslator const & papersizetranslator()
170 static PaperSizeTranslator translator = init_papersizetranslator();
176 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
179 PaperOrientationTranslator const init_paperorientationtranslator()
181 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
182 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
187 PaperOrientationTranslator const & paperorientationtranslator()
189 static PaperOrientationTranslator translator = init_paperorientationtranslator();
195 typedef Translator<int, TextClass::PageSides> SidesTranslator;
198 SidesTranslator const init_sidestranslator()
200 SidesTranslator translator(1, TextClass::OneSide);
201 translator.addPair(2, TextClass::TwoSides);
206 SidesTranslator const & sidestranslator()
208 static SidesTranslator translator = init_sidestranslator();
214 typedef Translator<int, BufferParams::Package> PackageTranslator;
217 PackageTranslator const init_packagetranslator()
219 PackageTranslator translator(0, BufferParams::package_off);
220 translator.addPair(1, BufferParams::package_auto);
221 translator.addPair(2, BufferParams::package_on);
226 PackageTranslator const & packagetranslator()
228 static PackageTranslator translator = init_packagetranslator();
234 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
237 CiteEngineTranslator const init_citeenginetranslator()
239 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
240 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
241 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
242 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
247 CiteEngineTranslator const & citeenginetranslator()
249 static CiteEngineTranslator translator = init_citeenginetranslator();
255 typedef Translator<string, Spacing::Space> SpaceTranslator;
258 SpaceTranslator const init_spacetranslator()
260 SpaceTranslator translator("default", Spacing::Default);
261 translator.addPair("single", Spacing::Single);
262 translator.addPair("onehalf", Spacing::Onehalf);
263 translator.addPair("double", Spacing::Double);
264 translator.addPair("other", Spacing::Other);
269 SpaceTranslator const & spacetranslator()
271 static SpaceTranslator translator = init_spacetranslator();
279 class BufferParams::Impl
284 AuthorList authorlist;
285 BranchList branchlist;
286 boost::array<Bullet, 4> temp_bullets;
287 boost::array<Bullet, 4> user_defined_bullets;
289 /** This is the amount of space used for paragraph_separation "skip",
290 * and for detached paragraphs in "indented" documents.
296 BufferParams::Impl::Impl()
297 : defskip(VSpace::MEDSKIP)
299 // set initial author
301 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
306 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
310 return new BufferParams::Impl(*ptr);
314 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
320 BufferParams::BufferParams()
323 setBaseClass(defaultTextclass());
324 paragraph_separation = PARSEP_INDENT;
325 quotes_language = InsetQuotes::EnglishQ;
326 fontsize = "default";
329 papersize = PAPER_DEFAULT;
330 orientation = ORIENTATION_PORTRAIT;
331 use_geometry = false;
332 use_amsmath = package_auto;
333 use_esint = package_auto;
334 cite_engine_ = biblio::ENGINE_BASIC;
335 use_bibtopic = false;
336 trackChanges = false;
337 outputChanges = false;
340 language = default_language;
341 fontsRoman = "default";
342 fontsSans = "default";
343 fontsTypewriter = "default";
344 fontsDefaultFamily = "default";
347 fontsSansScale = 100;
348 fontsTypewriterScale = 100;
350 graphicsDriver = "default";
351 sides = TextClass::OneSide;
353 listings_params = string();
354 pagestyle = "default";
357 for (int iter = 0; iter < 4; ++iter) {
358 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
359 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
364 BufferParams::~BufferParams()
368 docstring const BufferParams::B_(string const & l10n) const
370 BOOST_ASSERT(language);
371 return getMessages(language->code()).get(l10n);
375 AuthorList & BufferParams::authors()
377 return pimpl_->authorlist;
381 AuthorList const & BufferParams::authors() const
383 return pimpl_->authorlist;
387 BranchList & BufferParams::branchlist()
389 return pimpl_->branchlist;
393 BranchList const & BufferParams::branchlist() const
395 return pimpl_->branchlist;
399 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
401 BOOST_ASSERT(index < 4);
402 return pimpl_->temp_bullets[index];
406 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
408 BOOST_ASSERT(index < 4);
409 return pimpl_->temp_bullets[index];
413 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
415 BOOST_ASSERT(index < 4);
416 return pimpl_->user_defined_bullets[index];
420 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
422 BOOST_ASSERT(index < 4);
423 return pimpl_->user_defined_bullets[index];
427 Spacing & BufferParams::spacing()
429 return pimpl_->spacing;
433 Spacing const & BufferParams::spacing() const
435 return pimpl_->spacing;
439 VSpace const & BufferParams::getDefSkip() const
441 return pimpl_->defskip;
445 void BufferParams::setDefSkip(VSpace const & vs)
447 pimpl_->defskip = vs;
451 string const BufferParams::readToken(Lexer & lex, string const & token)
453 if (token == "\\textclass") {
455 string const classname = lex.getString();
456 pair<bool, lyx::textclass_type> pp =
457 textclasslist.numberOfClass(classname);
459 setBaseClass(pp.second);
461 // if text class does not exist, try to load it from filepath
462 pp = textclasslist.addTextClass(classname, filepath);
464 setBaseClass(pp.second);
466 setBaseClass(defaultTextclass());
470 if (!getTextClass().isTeXClassAvailable()) {
471 docstring const msg =
472 bformat(_("The layout file requested by this document,\n"
474 "is not usable. This is probably because a LaTeX\n"
475 "class or style file required by it is not\n"
476 "available. See the Customization documentation\n"
477 "for more information.\n"), from_utf8(classname));
478 frontend::Alert::warning(_("Document class not available"),
479 msg + _("LyX will not be able to produce output."));
482 } else if (token == "\\begin_preamble") {
484 } else if (token == "\\begin_modules") {
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 listings_params = InsetListingsParams(par).params();
612 } else if (token == "\\papersides") {
615 sides = sidestranslator().find(psides);
616 } else if (token == "\\paperpagestyle") {
618 } else if (token == "\\bullet") {
620 } else if (token == "\\bulletLaTeX") {
621 readBulletsLaTeX(lex);
622 } else if (token == "\\secnumdepth") {
624 } else if (token == "\\tocdepth") {
626 } else if (token == "\\spacing") {
630 if (nspacing == "other") {
633 spacing().set(spacetranslator().find(nspacing), tmp_val);
634 } else if (token == "\\float_placement") {
635 lex >> float_placement;
637 lyxerr << "BufferParams::readToken(): Unknown token: " <<
646 void BufferParams::writeFile(ostream & os) const
648 // The top of the file is written by the buffer.
649 // Prints out the buffer info into the .lyx file given by file
652 os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
655 if (!preamble.empty()) {
656 // remove '\n' from the end of preamble
657 string const tmppreamble = rtrim(preamble, "\n");
658 os << "\\begin_preamble\n"
660 << "\n\\end_preamble\n";
664 if (!options.empty()) {
665 os << "\\options " << options << '\n';
669 if (!layoutModules_.empty()) {
670 os << "\\begin_modules" << '\n';
671 LayoutModuleList::const_iterator it = layoutModules_.begin();
672 for (; it != layoutModules_.end(); it++)
674 os << "\\end_modules" << '\n';
677 // then the text parameters
678 if (language != ignore_language)
679 os << "\\language " << language->lang() << '\n';
680 os << "\\inputencoding " << inputenc
681 << "\n\\font_roman " << fontsRoman
682 << "\n\\font_sans " << fontsSans
683 << "\n\\font_typewriter " << fontsTypewriter
684 << "\n\\font_default_family " << fontsDefaultFamily
685 << "\n\\font_sc " << convert<string>(fontsSC)
686 << "\n\\font_osf " << convert<string>(fontsOSF)
687 << "\n\\font_sf_scale " << fontsSansScale
688 << "\n\\font_tt_scale " << fontsTypewriterScale
689 << "\n\\graphics " << graphicsDriver << '\n';
691 if (!float_placement.empty()) {
692 os << "\\float_placement " << float_placement << '\n';
694 os << "\\paperfontsize " << fontsize << '\n';
696 spacing().writeFile(os);
698 os << "\\papersize " << string_papersize[papersize]
699 << "\n\\use_geometry " << convert<string>(use_geometry)
700 << "\n\\use_amsmath " << use_amsmath
701 << "\n\\use_esint " << use_esint
702 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
703 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
704 << "\n\\paperorientation " << string_orientation[orientation]
707 BranchList::const_iterator it = branchlist().begin();
708 BranchList::const_iterator end = branchlist().end();
709 for (; it != end; ++it) {
710 os << "\\branch " << to_utf8(it->getBranch())
711 << "\n\\selected " << it->getSelected()
712 << "\n\\color " << lyx::X11hexname(it->getColor())
717 if (!paperwidth.empty())
718 os << "\\paperwidth "
719 << VSpace(paperwidth).asLyXCommand() << '\n';
720 if (!paperheight.empty())
721 os << "\\paperheight "
722 << VSpace(paperheight).asLyXCommand() << '\n';
723 if (!leftmargin.empty())
724 os << "\\leftmargin "
725 << VSpace(leftmargin).asLyXCommand() << '\n';
726 if (!topmargin.empty())
728 << VSpace(topmargin).asLyXCommand() << '\n';
729 if (!rightmargin.empty())
730 os << "\\rightmargin "
731 << VSpace(rightmargin).asLyXCommand() << '\n';
732 if (!bottommargin.empty())
733 os << "\\bottommargin "
734 << VSpace(bottommargin).asLyXCommand() << '\n';
735 if (!headheight.empty())
736 os << "\\headheight "
737 << VSpace(headheight).asLyXCommand() << '\n';
738 if (!headsep.empty())
740 << VSpace(headsep).asLyXCommand() << '\n';
741 if (!footskip.empty())
743 << VSpace(footskip).asLyXCommand() << '\n';
744 os << "\\secnumdepth " << secnumdepth
745 << "\n\\tocdepth " << tocdepth
746 << "\n\\paragraph_separation "
747 << string_paragraph_separation[paragraph_separation]
748 << "\n\\defskip " << getDefSkip().asLyXCommand()
749 << "\n\\quotes_language "
750 << string_quotes_language[quotes_language]
751 << "\n\\papercolumns " << columns
752 << "\n\\papersides " << sides
753 << "\n\\paperpagestyle " << pagestyle << '\n';
754 if (!listings_params.empty())
755 os << "\\listings_params \"" <<
756 InsetListingsParams(listings_params).encodedString() << "\"\n";
757 for (int i = 0; i < 4; ++i) {
758 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
759 if (user_defined_bullet(i).getFont() != -1) {
760 os << "\\bullet " << i << " "
761 << user_defined_bullet(i).getFont() << " "
762 << user_defined_bullet(i).getCharacter() << " "
763 << user_defined_bullet(i).getSize() << "\n";
767 os << "\\bulletLaTeX " << i << " \""
768 << lyx::to_ascii(user_defined_bullet(i).getText())
774 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
775 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
777 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
778 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
779 for (; a_it != a_end; ++a_it) {
780 if (a_it->second.used())
781 os << "\\author " << a_it->second << "\n";
783 os << "\\author " << Author() << "\n";
788 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
789 TexRow & texrow) const
791 os << "\\documentclass";
793 TextClass const & tclass = getTextClass();
795 ostringstream clsoptions; // the document class options.
797 if (tokenPos(tclass.opt_fontsize(),
798 '|', fontsize) >= 0) {
799 // only write if existing in list (and not default)
800 clsoptions << fontsize << "pt,";
803 // custom, A3, B3 and B4 paper sizes need geometry
804 bool nonstandard_papersize = papersize == PAPER_B3
805 || papersize == PAPER_B4
806 || papersize == PAPER_A3
807 || papersize == PAPER_CUSTOM;
812 clsoptions << "a4paper,";
815 clsoptions << "letterpaper,";
818 clsoptions << "a5paper,";
821 clsoptions << "b5paper,";
823 case PAPER_USEXECUTIVE:
824 clsoptions << "executivepaper,";
827 clsoptions << "legalpaper,";
839 if (sides != tclass.sides()) {
841 case TextClass::OneSide:
842 clsoptions << "oneside,";
844 case TextClass::TwoSides:
845 clsoptions << "twoside,";
851 if (columns != tclass.columns()) {
853 clsoptions << "twocolumn,";
855 clsoptions << "onecolumn,";
859 && orientation == ORIENTATION_LANDSCAPE)
860 clsoptions << "landscape,";
862 // language should be a parameter to \documentclass
863 if (language->babel() == "hebrew"
864 && default_language->babel() != "hebrew")
865 // This seems necessary
866 features.useLanguage(default_language);
868 ostringstream language_options;
869 bool const use_babel = features.useBabel();
871 language_options << features.getLanguages();
872 if (!language->babel().empty()) {
873 if (!language_options.str().empty())
874 language_options << ',';
875 language_options << language->babel();
877 if (lyxrc.language_global_options && !language_options.str().empty())
878 clsoptions << language_options.str() << ',';
881 // the user-defined options
882 if (!options.empty()) {
883 clsoptions << options << ',';
886 string strOptions(clsoptions.str());
887 if (!strOptions.empty()) {
888 strOptions = rtrim(strOptions, ",");
890 os << '[' << from_utf8(strOptions) << ']';
893 os << '{' << from_ascii(tclass.latexname()) << "}\n";
895 // end of \documentclass defs
897 // font selection must be done before loading fontenc.sty
899 loadFonts(fontsRoman, fontsSans,
900 fontsTypewriter, fontsSC, fontsOSF,
901 fontsSansScale, fontsTypewriterScale);
902 if (!fonts.empty()) {
903 os << from_ascii(fonts);
906 if (fontsDefaultFamily != "default")
907 os << "\\renewcommand{\\familydefault}{\\"
908 << from_ascii(fontsDefaultFamily) << "}\n";
911 // this one is not per buffer
912 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
913 if (lyxrc.fontenc != "default") {
914 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
915 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
916 << ",LFE,LAE]{fontenc}\n";
919 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
925 // handle inputenc etc.
926 writeEncodingPreamble(os, features, texrow);
928 if (!listings_params.empty()) {
929 os << "\\usepackage{listings}\n";
932 // do not test validity because listings_params is supposed to be valid
933 string par = InsetListingsParams(listings_params).separatedParams(true);
934 os << from_ascii(par);
935 // count the number of newlines
936 for (size_t i = 0; i < par.size(); ++i)
942 if (use_geometry || nonstandard_papersize) {
943 os << "\\usepackage{geometry}\n";
945 os << "\\geometry{verbose";
946 if (orientation == ORIENTATION_LANDSCAPE)
950 if (!paperwidth.empty())
952 << from_ascii(paperwidth);
953 if (!paperheight.empty())
954 os << ",paperheight="
955 << from_ascii(paperheight);
958 os << ",letterpaper";
963 case PAPER_USEXECUTIVE:
964 os << ",executivepaper";
985 // default papersize ie PAPER_DEFAULT
986 switch (lyxrc.default_papersize) {
987 case PAPER_DEFAULT: // keep compiler happy
989 os << ",letterpaper";
994 case PAPER_USEXECUTIVE:
995 os << ",executivepaper";
1015 if (!topmargin.empty())
1016 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1017 if (!bottommargin.empty())
1018 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1019 if (!leftmargin.empty())
1020 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1021 if (!rightmargin.empty())
1022 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1023 if (!headheight.empty())
1024 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1025 if (!headsep.empty())
1026 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1027 if (!footskip.empty())
1028 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1033 if (tokenPos(tclass.opt_pagestyle(),
1034 '|', pagestyle) >= 0) {
1035 if (pagestyle == "fancy") {
1036 os << "\\usepackage{fancyhdr}\n";
1039 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1043 // Only if class has a ToC hierarchy
1044 if (tclass.hasTocLevels()) {
1045 if (secnumdepth != tclass.secnumdepth()) {
1046 os << "\\setcounter{secnumdepth}{"
1051 if (tocdepth != tclass.tocdepth()) {
1052 os << "\\setcounter{tocdepth}{"
1059 if (paragraph_separation) {
1060 switch (getDefSkip().kind()) {
1061 case VSpace::SMALLSKIP:
1062 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1064 case VSpace::MEDSKIP:
1065 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1067 case VSpace::BIGSKIP:
1068 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1070 case VSpace::LENGTH:
1071 os << "\\setlength{\\parskip}{"
1072 << from_utf8(getDefSkip().length().asLatexString())
1075 default: // should never happen // Then delete it.
1076 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1081 os << "\\setlength{\\parindent}{0pt}\n";
1085 // If we use jurabib, we have to call babel here.
1086 if (use_babel && features.isRequired("jurabib")) {
1087 os << from_ascii(babelCall(language_options.str()))
1089 << from_ascii(features.getBabelOptions());
1093 // Now insert the LyX specific LaTeX commands...
1095 // The optional packages;
1096 docstring lyxpreamble(from_ascii(features.getPackages()));
1098 // this might be useful...
1099 lyxpreamble += "\n\\makeatletter\n";
1101 // Some macros LyX will need
1102 docstring tmppreamble(from_ascii(features.getMacros()));
1104 if (!tmppreamble.empty()) {
1105 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1106 "LyX specific LaTeX commands.\n"
1107 + tmppreamble + '\n';
1110 // the text class specific preamble
1111 tmppreamble = features.getTClassPreamble();
1112 if (!tmppreamble.empty()) {
1113 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1114 "Textclass specific LaTeX commands.\n"
1115 + tmppreamble + '\n';
1118 /* the user-defined preamble */
1119 if (!preamble.empty()) {
1121 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1122 "User specified LaTeX commands.\n"
1123 + from_utf8(preamble) + '\n';
1126 // Itemize bullet settings need to be last in case the user
1127 // defines their own bullets that use a package included
1128 // in the user-defined preamble -- ARRae
1129 // Actually it has to be done much later than that
1130 // since some packages like frenchb make modifications
1131 // at \begin{document} time -- JMarc
1132 docstring bullets_def;
1133 for (int i = 0; i < 4; ++i) {
1134 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1135 if (bullets_def.empty())
1136 bullets_def += "\\AtBeginDocument{\n";
1137 bullets_def += " \\def\\labelitemi";
1139 // `i' is one less than the item to modify
1146 bullets_def += "ii";
1152 bullets_def += '{' +
1153 user_defined_bullet(i).getText()
1158 if (!bullets_def.empty())
1159 lyxpreamble += bullets_def + "}\n\n";
1161 // We try to load babel late, in case it interferes
1162 // with other packages.
1163 // Jurabib has to be called after babel, though.
1164 if (use_babel && !features.isRequired("jurabib")) {
1166 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1167 lyxpreamble += from_utf8(features.getBabelOptions());
1170 lyxpreamble += "\\makeatother\n\n";
1173 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1174 for (int j = 0; j != nlines; ++j) {
1183 void BufferParams::useClassDefaults()
1185 TextClass const & tclass = textclasslist[baseClass_];
1187 sides = tclass.sides();
1188 columns = tclass.columns();
1189 pagestyle = tclass.pagestyle();
1190 options = tclass.options();
1191 // Only if class has a ToC hierarchy
1192 if (tclass.hasTocLevels()) {
1193 secnumdepth = tclass.secnumdepth();
1194 tocdepth = tclass.tocdepth();
1199 bool BufferParams::hasClassDefaults() const
1201 TextClass const & tclass = textclasslist[baseClass_];
1203 return (sides == tclass.sides()
1204 && columns == tclass.columns()
1205 && pagestyle == tclass.pagestyle()
1206 && options == tclass.options()
1207 && secnumdepth == tclass.secnumdepth()
1208 && tocdepth == tclass.tocdepth());
1212 TextClass const & BufferParams::getTextClass() const
1218 TextClass_ptr BufferParams::getTextClass_ptr() const {
1223 void BufferParams::setTextClass(TextClass_ptr tc) {
1228 bool BufferParams::setBaseClass(textclass_type tc)
1230 if (!textclasslist[tc].load()) {
1231 docstring s = bformat(_("The document class %1$s."
1232 "could not be loaded."),
1233 from_utf8(textclasslist[tc].name()));
1234 frontend::Alert::error(_("Could not load class"), s);
1244 void BufferParams::setJustBaseClass(textclass_type tc)
1250 textclass_type BufferParams::getBaseClass() const
1256 void BufferParams::makeTextClass()
1258 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1259 //FIXME It might be worth loading the children's modules here,
1260 //instead of just doing a check in InsetInclude.
1261 LayoutModuleList::const_iterator it = layoutModules_.begin();
1262 for (; it != layoutModules_.end(); it++) {
1263 string const modName = *it;
1264 LyXModule * lm = moduleList[modName];
1266 docstring const msg =
1267 bformat(_("The module %1$s has been requested by\n"
1268 "this document but has not been found in the list of\n"
1269 "available modules. If you recently installed it, you\n"
1270 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1271 frontend::Alert::warning(_("Module not available"),
1272 msg + _("Some layouts may not be available."));
1273 lyxerr << "BufferParams::makeTextClass(): Module " <<
1274 modName << " requested but not found in module list." <<
1278 FileName layout_file = libFileSearch("layouts", lm->filename);
1279 textClass_->read(layout_file, TextClass::MODULE);
1284 std::vector<string> const & BufferParams::getModules() const {
1285 return layoutModules_;
1290 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1291 LayoutModuleList::const_iterator it = layoutModules_.begin();
1292 LayoutModuleList::const_iterator end = layoutModules_.end();
1293 for (; it != end; it++) {
1297 if (it != layoutModules_.end())
1299 layoutModules_.push_back(modName);
1306 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1309 std::vector<string>::const_iterator it = modNames.begin();
1310 std::vector<string>::const_iterator end = modNames.end();
1311 for (; it != end; ++it)
1312 retval &= addLayoutModule(*it, false);
1318 void BufferParams::clearLayoutModules() {
1319 layoutModules_.clear();
1324 Font const BufferParams::getFont() const
1326 Font f = getTextClass().defaultfont();
1327 f.setLanguage(language);
1328 if (fontsDefaultFamily == "rmdefault")
1329 f.setFamily(Font::ROMAN_FAMILY);
1330 else if (fontsDefaultFamily == "sfdefault")
1331 f.setFamily(Font::SANS_FAMILY);
1332 else if (fontsDefaultFamily == "ttdefault")
1333 f.setFamily(Font::TYPEWRITER_FAMILY);
1338 void BufferParams::readPreamble(Lexer & lex)
1340 if (lex.getString() != "\\begin_preamble")
1341 lyxerr << "Error (BufferParams::readPreamble):"
1342 "consistency check failed." << endl;
1344 preamble = lex.getLongString("\\end_preamble");
1348 void BufferParams::readLanguage(Lexer & lex)
1350 if (!lex.next()) return;
1352 string const tmptok = lex.getString();
1354 // check if tmptok is part of tex_babel in tex-defs.h
1355 language = languages.getLanguage(tmptok);
1357 // Language tmptok was not found
1358 language = default_language;
1359 lyxerr << "Warning: Setting language `"
1360 << tmptok << "' to `" << language->lang()
1366 void BufferParams::readGraphicsDriver(Lexer & lex)
1368 if (!lex.next()) return;
1370 string const tmptok = lex.getString();
1371 // check if tmptok is part of tex_graphics in tex_defs.h
1374 string const test = tex_graphics[n++];
1376 if (test == tmptok) {
1377 graphicsDriver = tmptok;
1379 } else if (test == "") {
1381 "Warning: graphics driver `$$Token' not recognized!\n"
1382 " Setting graphics driver to `default'.\n");
1383 graphicsDriver = "default";
1390 void BufferParams::readBullets(Lexer & lex)
1392 if (!lex.next()) return;
1394 int const index = lex.getInteger();
1396 int temp_int = lex.getInteger();
1397 user_defined_bullet(index).setFont(temp_int);
1398 temp_bullet(index).setFont(temp_int);
1400 user_defined_bullet(index).setCharacter(temp_int);
1401 temp_bullet(index).setCharacter(temp_int);
1403 user_defined_bullet(index).setSize(temp_int);
1404 temp_bullet(index).setSize(temp_int);
1408 void BufferParams::readBulletsLaTeX(Lexer & lex)
1410 // The bullet class should be able to read this.
1411 if (!lex.next()) return;
1412 int const index = lex.getInteger();
1414 docstring const temp_str = lex.getDocString();
1416 user_defined_bullet(index).setText(temp_str);
1417 temp_bullet(index).setText(temp_str);
1421 void BufferParams::readModules(Lexer & lex)
1423 if (!lex.eatLine()) {
1424 lyxerr << "Error (BufferParams::readModules):"
1425 "Unexpected end of input." << endl;
1429 string mod = lex.getString();
1430 if (mod == "\\end_modules")
1432 addLayoutModule(mod);
1438 string const BufferParams::paperSizeName() const
1440 char real_papersize = papersize;
1441 if (real_papersize == PAPER_DEFAULT)
1442 real_papersize = lyxrc.default_papersize;
1444 switch (real_papersize) {
1453 case PAPER_USEXECUTIVE:
1457 case PAPER_USLETTER:
1464 string const BufferParams::dvips_options() const
1469 && papersize == PAPER_CUSTOM
1470 && !lyxrc.print_paper_dimension_flag.empty()
1471 && !paperwidth.empty()
1472 && !paperheight.empty()) {
1473 // using a custom papersize
1474 result = lyxrc.print_paper_dimension_flag;
1475 result += ' ' + paperwidth;
1476 result += ',' + paperheight;
1478 string const paper_option = paperSizeName();
1479 if (paper_option != "letter" ||
1480 orientation != ORIENTATION_LANDSCAPE) {
1481 // dvips won't accept -t letter -t landscape.
1482 // In all other cases, include the paper size
1484 result = lyxrc.print_paper_flag;
1485 result += ' ' + paper_option;
1488 if (orientation == ORIENTATION_LANDSCAPE &&
1489 papersize != PAPER_CUSTOM)
1490 result += ' ' + lyxrc.print_landscape_flag;
1495 string const BufferParams::babelCall(string const & lang_opts) const
1497 string lang_pack = lyxrc.language_package;
1498 if (lang_pack != "\\usepackage{babel}")
1500 // suppress the babel call when there is no babel language defined
1501 // for the document language in the lib/languages file and if no
1502 // other languages are used (lang_opts is then empty)
1503 if (lang_opts.empty())
1505 if (!lyxrc.language_global_options)
1506 return "\\usepackage[" + lang_opts + "]{babel}";
1511 void BufferParams::writeEncodingPreamble(odocstream & os,
1512 LaTeXFeatures & features, TexRow & texrow) const
1514 if (inputenc == "auto") {
1515 string const doc_encoding =
1516 language->encoding()->latexName();
1517 Encoding::Package const package =
1518 language->encoding()->package();
1520 // Create a list with all the input encodings used
1522 std::set<string> encodings =
1523 features.getEncodingSet(doc_encoding);
1525 if (!encodings.empty() || package == Encoding::inputenc) {
1526 os << "\\usepackage[";
1527 std::set<string>::const_iterator it = encodings.begin();
1528 std::set<string>::const_iterator const end = encodings.end();
1530 os << from_ascii(*it);
1533 for (; it != end; ++it)
1534 os << ',' << from_ascii(*it);
1535 if (package == Encoding::inputenc) {
1536 if (!encodings.empty())
1538 os << from_ascii(doc_encoding);
1540 os << "]{inputenc}\n";
1543 if (package == Encoding::CJK) {
1544 os << "\\usepackage{CJK}\n";
1547 } else if (inputenc != "default") {
1548 switch (encoding().package()) {
1549 case Encoding::none:
1551 case Encoding::inputenc:
1552 os << "\\usepackage[" << from_ascii(inputenc)
1557 os << "\\usepackage{CJK}\n";
1563 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1564 // armscii8 is used for Armenian.
1565 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1566 os << "\\usepackage{armtex}\n";
1572 string const BufferParams::loadFonts(string const & rm,
1573 string const & sf, string const & tt,
1574 bool const & sc, bool const & osf,
1575 int const & sfscale, int const & ttscale) const
1577 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1578 several packages have been replaced by others, that might not
1579 be installed on every system. We have to take care for that
1580 (see psnfss.pdf). We try to support all psnfss fonts as well
1581 as the fonts that have become de facto standard in the LaTeX
1582 world (e.g. Latin Modern). We do not support obsolete fonts
1583 (like PSLatex). In general, it should be possible to mix any
1584 rm font with any sf or tt font, respectively. (JSpitzm)
1586 -- separate math fonts.
1589 if (rm == "default" && sf == "default" && tt == "default")
1596 // Computer Modern (must be explicitely selectable -- there might be classes
1597 // that define a different default font!
1599 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1600 // osf for Computer Modern needs eco.sty
1602 os << "\\usepackage{eco}\n";
1604 // Latin Modern Roman
1605 else if (rm == "lmodern")
1606 os << "\\usepackage{lmodern}\n";
1608 else if (rm == "ae") {
1609 // not needed when using OT1 font encoding.
1610 if (lyxrc.fontenc != "default")
1611 os << "\\usepackage{ae,aecompl}\n";
1614 else if (rm == "times") {
1615 // try to load the best available package
1616 if (LaTeXFeatures::isAvailable("mathptmx"))
1617 os << "\\usepackage{mathptmx}\n";
1618 else if (LaTeXFeatures::isAvailable("mathptm"))
1619 os << "\\usepackage{mathptm}\n";
1621 os << "\\usepackage{times}\n";
1624 else if (rm == "palatino") {
1625 // try to load the best available package
1626 if (LaTeXFeatures::isAvailable("mathpazo")) {
1627 os << "\\usepackage";
1633 // "osf" includes "sc"!
1637 os << "{mathpazo}\n";
1639 else if (LaTeXFeatures::isAvailable("mathpple"))
1640 os << "\\usepackage{mathpple}\n";
1642 os << "\\usepackage{palatino}\n";
1645 else if (rm == "utopia") {
1646 // fourier supersedes utopia.sty, but does
1647 // not work with OT1 encoding.
1648 if (LaTeXFeatures::isAvailable("fourier")
1649 && lyxrc.fontenc != "default") {
1650 os << "\\usepackage";
1661 os << "{fourier}\n";
1664 os << "\\usepackage{utopia}\n";
1666 // Bera (complete fontset)
1667 else if (rm == "bera" && sf == "default" && tt == "default")
1668 os << "\\usepackage{bera}\n";
1670 else if (rm != "default")
1671 os << "\\usepackage" << "{" << rm << "}\n";
1674 // Helvetica, Bera Sans
1675 if (sf == "helvet" || sf == "berasans") {
1677 os << "\\usepackage[scaled=" << float(sfscale) / 100
1678 << "]{" << sf << "}\n";
1680 os << "\\usepackage{" << sf << "}\n";
1683 else if (sf == "avant")
1684 os << "\\usepackage{" << sf << "}\n";
1685 // Computer Modern, Latin Modern, CM Bright
1686 else if (sf != "default")
1687 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1689 // monospaced/typewriter
1690 // Courier, LuxiMono
1691 if (tt == "luximono" || tt == "beramono") {
1693 os << "\\usepackage[scaled=" << float(ttscale) / 100
1694 << "]{" << tt << "}\n";
1696 os << "\\usepackage{" << tt << "}\n";
1699 else if (tt == "courier" )
1700 os << "\\usepackage{" << tt << "}\n";
1701 // Computer Modern, Latin Modern, CM Bright
1702 else if (tt != "default")
1703 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1709 Encoding const & BufferParams::encoding() const
1711 if (inputenc == "auto" || inputenc == "default")
1712 return *(language->encoding());
1713 Encoding const * const enc =
1714 encodings.getFromLaTeXName(inputenc);
1717 lyxerr << "Unknown inputenc value `" << inputenc
1718 << "'. Using `auto' instead." << endl;
1719 return *(language->encoding());
1723 biblio::CiteEngine BufferParams::getEngine() const
1725 // FIXME the class should provide the numerical/
1726 // authoryear choice
1727 if (getTextClass().provides("natbib")
1728 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1729 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1730 return cite_engine_;
1734 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1736 cite_engine_ = cite_engine;