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 //just as we load their bibliographies and such, instead of just
1261 //doing a check in InsetInclude.
1262 LayoutModuleList::const_iterator it = layoutModules_.begin();
1263 for (; it != layoutModules_.end(); it++) {
1264 string const modName = *it;
1265 LyXModule * lm = moduleList[modName];
1267 docstring const msg =
1268 bformat(_("The module %1$s has been requested by\n"
1269 "this document but has not been found in the list of\n"
1270 "available modules. If you recently installed it, you\n"
1271 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1272 frontend::Alert::warning(_("Module not available"),
1273 msg + _("Some layouts may not be available."));
1274 lyxerr << "BufferParams::makeTextClass(): Module " <<
1275 modName << " requested but not found in module list." <<
1279 FileName layout_file = libFileSearch("layouts", lm->filename);
1280 textClass_->read(layout_file, TextClass::MODULE);
1285 std::vector<string> const & BufferParams::getModules() const {
1286 return layoutModules_;
1291 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1292 LayoutModuleList::const_iterator it = layoutModules_.begin();
1293 LayoutModuleList::const_iterator end = layoutModules_.end();
1294 for (; it != end; it++) {
1298 if (it != layoutModules_.end())
1300 layoutModules_.push_back(modName);
1307 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1310 std::vector<string>::const_iterator it = modNames.begin();
1311 std::vector<string>::const_iterator end = modNames.end();
1312 for (; it != end; ++it)
1313 retval &= addLayoutModule(*it, false);
1319 void BufferParams::clearLayoutModules() {
1320 layoutModules_.clear();
1325 Font const BufferParams::getFont() const
1327 Font f = getTextClass().defaultfont();
1328 f.setLanguage(language);
1329 if (fontsDefaultFamily == "rmdefault")
1330 f.setFamily(Font::ROMAN_FAMILY);
1331 else if (fontsDefaultFamily == "sfdefault")
1332 f.setFamily(Font::SANS_FAMILY);
1333 else if (fontsDefaultFamily == "ttdefault")
1334 f.setFamily(Font::TYPEWRITER_FAMILY);
1339 void BufferParams::readPreamble(Lexer & lex)
1341 if (lex.getString() != "\\begin_preamble")
1342 lyxerr << "Error (BufferParams::readPreamble):"
1343 "consistency check failed." << endl;
1345 preamble = lex.getLongString("\\end_preamble");
1349 void BufferParams::readLanguage(Lexer & lex)
1351 if (!lex.next()) return;
1353 string const tmptok = lex.getString();
1355 // check if tmptok is part of tex_babel in tex-defs.h
1356 language = languages.getLanguage(tmptok);
1358 // Language tmptok was not found
1359 language = default_language;
1360 lyxerr << "Warning: Setting language `"
1361 << tmptok << "' to `" << language->lang()
1367 void BufferParams::readGraphicsDriver(Lexer & lex)
1369 if (!lex.next()) return;
1371 string const tmptok = lex.getString();
1372 // check if tmptok is part of tex_graphics in tex_defs.h
1375 string const test = tex_graphics[n++];
1377 if (test == tmptok) {
1378 graphicsDriver = tmptok;
1380 } else if (test == "") {
1382 "Warning: graphics driver `$$Token' not recognized!\n"
1383 " Setting graphics driver to `default'.\n");
1384 graphicsDriver = "default";
1391 void BufferParams::readBullets(Lexer & lex)
1393 if (!lex.next()) return;
1395 int const index = lex.getInteger();
1397 int temp_int = lex.getInteger();
1398 user_defined_bullet(index).setFont(temp_int);
1399 temp_bullet(index).setFont(temp_int);
1401 user_defined_bullet(index).setCharacter(temp_int);
1402 temp_bullet(index).setCharacter(temp_int);
1404 user_defined_bullet(index).setSize(temp_int);
1405 temp_bullet(index).setSize(temp_int);
1409 void BufferParams::readBulletsLaTeX(Lexer & lex)
1411 // The bullet class should be able to read this.
1412 if (!lex.next()) return;
1413 int const index = lex.getInteger();
1415 docstring const temp_str = lex.getDocString();
1417 user_defined_bullet(index).setText(temp_str);
1418 temp_bullet(index).setText(temp_str);
1422 void BufferParams::readModules(Lexer & lex)
1424 if (!lex.eatLine()) {
1425 lyxerr << "Error (BufferParams::readModules):"
1426 "Unexpected end of input." << endl;
1430 string mod = lex.getString();
1431 if (mod == "\\end_modules")
1433 addLayoutModule(mod);
1439 string const BufferParams::paperSizeName() const
1441 char real_papersize = papersize;
1442 if (real_papersize == PAPER_DEFAULT)
1443 real_papersize = lyxrc.default_papersize;
1445 switch (real_papersize) {
1454 case PAPER_USEXECUTIVE:
1458 case PAPER_USLETTER:
1465 string const BufferParams::dvips_options() const
1470 && papersize == PAPER_CUSTOM
1471 && !lyxrc.print_paper_dimension_flag.empty()
1472 && !paperwidth.empty()
1473 && !paperheight.empty()) {
1474 // using a custom papersize
1475 result = lyxrc.print_paper_dimension_flag;
1476 result += ' ' + paperwidth;
1477 result += ',' + paperheight;
1479 string const paper_option = paperSizeName();
1480 if (paper_option != "letter" ||
1481 orientation != ORIENTATION_LANDSCAPE) {
1482 // dvips won't accept -t letter -t landscape.
1483 // In all other cases, include the paper size
1485 result = lyxrc.print_paper_flag;
1486 result += ' ' + paper_option;
1489 if (orientation == ORIENTATION_LANDSCAPE &&
1490 papersize != PAPER_CUSTOM)
1491 result += ' ' + lyxrc.print_landscape_flag;
1496 string const BufferParams::babelCall(string const & lang_opts) const
1498 string lang_pack = lyxrc.language_package;
1499 if (lang_pack != "\\usepackage{babel}")
1501 // suppress the babel call when there is no babel language defined
1502 // for the document language in the lib/languages file and if no
1503 // other languages are used (lang_opts is then empty)
1504 if (lang_opts.empty())
1506 if (!lyxrc.language_global_options)
1507 return "\\usepackage[" + lang_opts + "]{babel}";
1512 void BufferParams::writeEncodingPreamble(odocstream & os,
1513 LaTeXFeatures & features, TexRow & texrow) const
1515 if (inputenc == "auto") {
1516 string const doc_encoding =
1517 language->encoding()->latexName();
1518 Encoding::Package const package =
1519 language->encoding()->package();
1521 // Create a list with all the input encodings used
1523 std::set<string> encodings =
1524 features.getEncodingSet(doc_encoding);
1526 if (!encodings.empty() || package == Encoding::inputenc) {
1527 os << "\\usepackage[";
1528 std::set<string>::const_iterator it = encodings.begin();
1529 std::set<string>::const_iterator const end = encodings.end();
1531 os << from_ascii(*it);
1534 for (; it != end; ++it)
1535 os << ',' << from_ascii(*it);
1536 if (package == Encoding::inputenc) {
1537 if (!encodings.empty())
1539 os << from_ascii(doc_encoding);
1541 os << "]{inputenc}\n";
1544 if (package == Encoding::CJK) {
1545 os << "\\usepackage{CJK}\n";
1548 } else if (inputenc != "default") {
1549 switch (encoding().package()) {
1550 case Encoding::none:
1552 case Encoding::inputenc:
1553 os << "\\usepackage[" << from_ascii(inputenc)
1558 os << "\\usepackage{CJK}\n";
1564 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1565 // armscii8 is used for Armenian.
1566 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1567 os << "\\usepackage{armtex}\n";
1573 string const BufferParams::loadFonts(string const & rm,
1574 string const & sf, string const & tt,
1575 bool const & sc, bool const & osf,
1576 int const & sfscale, int const & ttscale) const
1578 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1579 several packages have been replaced by others, that might not
1580 be installed on every system. We have to take care for that
1581 (see psnfss.pdf). We try to support all psnfss fonts as well
1582 as the fonts that have become de facto standard in the LaTeX
1583 world (e.g. Latin Modern). We do not support obsolete fonts
1584 (like PSLatex). In general, it should be possible to mix any
1585 rm font with any sf or tt font, respectively. (JSpitzm)
1587 -- separate math fonts.
1590 if (rm == "default" && sf == "default" && tt == "default")
1597 // Computer Modern (must be explicitely selectable -- there might be classes
1598 // that define a different default font!
1600 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1601 // osf for Computer Modern needs eco.sty
1603 os << "\\usepackage{eco}\n";
1605 // Latin Modern Roman
1606 else if (rm == "lmodern")
1607 os << "\\usepackage{lmodern}\n";
1609 else if (rm == "ae") {
1610 // not needed when using OT1 font encoding.
1611 if (lyxrc.fontenc != "default")
1612 os << "\\usepackage{ae,aecompl}\n";
1615 else if (rm == "times") {
1616 // try to load the best available package
1617 if (LaTeXFeatures::isAvailable("mathptmx"))
1618 os << "\\usepackage{mathptmx}\n";
1619 else if (LaTeXFeatures::isAvailable("mathptm"))
1620 os << "\\usepackage{mathptm}\n";
1622 os << "\\usepackage{times}\n";
1625 else if (rm == "palatino") {
1626 // try to load the best available package
1627 if (LaTeXFeatures::isAvailable("mathpazo")) {
1628 os << "\\usepackage";
1634 // "osf" includes "sc"!
1638 os << "{mathpazo}\n";
1640 else if (LaTeXFeatures::isAvailable("mathpple"))
1641 os << "\\usepackage{mathpple}\n";
1643 os << "\\usepackage{palatino}\n";
1646 else if (rm == "utopia") {
1647 // fourier supersedes utopia.sty, but does
1648 // not work with OT1 encoding.
1649 if (LaTeXFeatures::isAvailable("fourier")
1650 && lyxrc.fontenc != "default") {
1651 os << "\\usepackage";
1662 os << "{fourier}\n";
1665 os << "\\usepackage{utopia}\n";
1667 // Bera (complete fontset)
1668 else if (rm == "bera" && sf == "default" && tt == "default")
1669 os << "\\usepackage{bera}\n";
1671 else if (rm != "default")
1672 os << "\\usepackage" << "{" << rm << "}\n";
1675 // Helvetica, Bera Sans
1676 if (sf == "helvet" || sf == "berasans") {
1678 os << "\\usepackage[scaled=" << float(sfscale) / 100
1679 << "]{" << sf << "}\n";
1681 os << "\\usepackage{" << sf << "}\n";
1684 else if (sf == "avant")
1685 os << "\\usepackage{" << sf << "}\n";
1686 // Computer Modern, Latin Modern, CM Bright
1687 else if (sf != "default")
1688 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1690 // monospaced/typewriter
1691 // Courier, LuxiMono
1692 if (tt == "luximono" || tt == "beramono") {
1694 os << "\\usepackage[scaled=" << float(ttscale) / 100
1695 << "]{" << tt << "}\n";
1697 os << "\\usepackage{" << tt << "}\n";
1700 else if (tt == "courier" )
1701 os << "\\usepackage{" << tt << "}\n";
1702 // Computer Modern, Latin Modern, CM Bright
1703 else if (tt != "default")
1704 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1710 Encoding const & BufferParams::encoding() const
1712 if (inputenc == "auto" || inputenc == "default")
1713 return *(language->encoding());
1714 Encoding const * const enc =
1715 encodings.getFromLaTeXName(inputenc);
1718 lyxerr << "Unknown inputenc value `" << inputenc
1719 << "'. Using `auto' instead." << endl;
1720 return *(language->encoding());
1724 biblio::CiteEngine BufferParams::getEngine() const
1726 // FIXME the class should provide the numerical/
1727 // authoryear choice
1728 if (getTextClass().provides("natbib")
1729 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1730 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1731 return cite_engine_;
1735 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1737 cite_engine_ = cite_engine;