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 void BufferParams::setBaseClass(textclass_type tc)
1235 void BufferParams::setJustBaseClass(textclass_type tc)
1241 textclass_type BufferParams::getBaseClass() const
1247 void BufferParams::makeTextClass()
1249 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1250 //FIXME It might be worth loading the children's modules here,
1251 //instead of just doing a check in InsetInclude.
1252 LayoutModuleList::const_iterator it = layoutModules_.begin();
1253 for (; it != layoutModules_.end(); it++) {
1254 string const modName = *it;
1255 LyXModule * lm = moduleList[modName];
1257 docstring const msg =
1258 bformat(_("The module %1$s has been requested by\n"
1259 "this document but has not been found in the list of\n"
1260 "available modules. If you recently installed it, you\n"
1261 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1262 frontend::Alert::warning(_("Module not available"),
1263 msg + _("Some layouts may not be available."));
1264 lyxerr << "BufferParams::makeTextClass(): Module " <<
1265 modName << " requested but not found in module list." <<
1269 FileName layout_file = libFileSearch("layouts", lm->filename);
1270 textClass_->read(layout_file, TextClass::MODULE);
1275 std::vector<string> const & BufferParams::getModules() const {
1276 return layoutModules_;
1281 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1282 LayoutModuleList::const_iterator it = layoutModules_.begin();
1283 LayoutModuleList::const_iterator end = layoutModules_.end();
1284 for (; it != end; it++) {
1288 if (it != layoutModules_.end())
1290 layoutModules_.push_back(modName);
1297 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1300 std::vector<string>::const_iterator it = modNames.begin();
1301 std::vector<string>::const_iterator end = modNames.end();
1302 for (; it != end; ++it)
1303 retval &= addLayoutModule(*it, false);
1309 void BufferParams::clearLayoutModules() {
1310 layoutModules_.clear();
1315 Font const BufferParams::getFont() const
1317 Font f = getTextClass().defaultfont();
1318 f.setLanguage(language);
1319 if (fontsDefaultFamily == "rmdefault")
1320 f.setFamily(Font::ROMAN_FAMILY);
1321 else if (fontsDefaultFamily == "sfdefault")
1322 f.setFamily(Font::SANS_FAMILY);
1323 else if (fontsDefaultFamily == "ttdefault")
1324 f.setFamily(Font::TYPEWRITER_FAMILY);
1329 void BufferParams::readPreamble(Lexer & lex)
1331 if (lex.getString() != "\\begin_preamble")
1332 lyxerr << "Error (BufferParams::readPreamble):"
1333 "consistency check failed." << endl;
1335 preamble = lex.getLongString("\\end_preamble");
1339 void BufferParams::readLanguage(Lexer & lex)
1341 if (!lex.next()) return;
1343 string const tmptok = lex.getString();
1345 // check if tmptok is part of tex_babel in tex-defs.h
1346 language = languages.getLanguage(tmptok);
1348 // Language tmptok was not found
1349 language = default_language;
1350 lyxerr << "Warning: Setting language `"
1351 << tmptok << "' to `" << language->lang()
1357 void BufferParams::readGraphicsDriver(Lexer & lex)
1359 if (!lex.next()) return;
1361 string const tmptok = lex.getString();
1362 // check if tmptok is part of tex_graphics in tex_defs.h
1365 string const test = tex_graphics[n++];
1367 if (test == tmptok) {
1368 graphicsDriver = tmptok;
1370 } else if (test == "") {
1372 "Warning: graphics driver `$$Token' not recognized!\n"
1373 " Setting graphics driver to `default'.\n");
1374 graphicsDriver = "default";
1381 void BufferParams::readBullets(Lexer & lex)
1383 if (!lex.next()) return;
1385 int const index = lex.getInteger();
1387 int temp_int = lex.getInteger();
1388 user_defined_bullet(index).setFont(temp_int);
1389 temp_bullet(index).setFont(temp_int);
1391 user_defined_bullet(index).setCharacter(temp_int);
1392 temp_bullet(index).setCharacter(temp_int);
1394 user_defined_bullet(index).setSize(temp_int);
1395 temp_bullet(index).setSize(temp_int);
1399 void BufferParams::readBulletsLaTeX(Lexer & lex)
1401 // The bullet class should be able to read this.
1402 if (!lex.next()) return;
1403 int const index = lex.getInteger();
1405 docstring const temp_str = lex.getDocString();
1407 user_defined_bullet(index).setText(temp_str);
1408 temp_bullet(index).setText(temp_str);
1412 void BufferParams::readModules(Lexer & lex)
1414 if (!lex.eatLine()) {
1415 lyxerr << "Error (BufferParams::readModules):"
1416 "Unexpected end of input." << endl;
1420 string mod = lex.getString();
1421 if (mod == "\\end_modules")
1423 addLayoutModule(mod);
1429 string const BufferParams::paperSizeName() const
1431 char real_papersize = papersize;
1432 if (real_papersize == PAPER_DEFAULT)
1433 real_papersize = lyxrc.default_papersize;
1435 switch (real_papersize) {
1444 case PAPER_USEXECUTIVE:
1448 case PAPER_USLETTER:
1455 string const BufferParams::dvips_options() const
1460 && papersize == PAPER_CUSTOM
1461 && !lyxrc.print_paper_dimension_flag.empty()
1462 && !paperwidth.empty()
1463 && !paperheight.empty()) {
1464 // using a custom papersize
1465 result = lyxrc.print_paper_dimension_flag;
1466 result += ' ' + paperwidth;
1467 result += ',' + paperheight;
1469 string const paper_option = paperSizeName();
1470 if (paper_option != "letter" ||
1471 orientation != ORIENTATION_LANDSCAPE) {
1472 // dvips won't accept -t letter -t landscape.
1473 // In all other cases, include the paper size
1475 result = lyxrc.print_paper_flag;
1476 result += ' ' + paper_option;
1479 if (orientation == ORIENTATION_LANDSCAPE &&
1480 papersize != PAPER_CUSTOM)
1481 result += ' ' + lyxrc.print_landscape_flag;
1486 string const BufferParams::babelCall(string const & lang_opts) const
1488 string lang_pack = lyxrc.language_package;
1489 if (lang_pack != "\\usepackage{babel}")
1491 // suppress the babel call when there is no babel language defined
1492 // for the document language in the lib/languages file and if no
1493 // other languages are used (lang_opts is then empty)
1494 if (lang_opts.empty())
1496 if (!lyxrc.language_global_options)
1497 return "\\usepackage[" + lang_opts + "]{babel}";
1502 void BufferParams::writeEncodingPreamble(odocstream & os,
1503 LaTeXFeatures & features, TexRow & texrow) const
1505 if (inputenc == "auto") {
1506 string const doc_encoding =
1507 language->encoding()->latexName();
1508 Encoding::Package const package =
1509 language->encoding()->package();
1511 // Create a list with all the input encodings used
1513 std::set<string> encodings =
1514 features.getEncodingSet(doc_encoding);
1516 if (!encodings.empty() || package == Encoding::inputenc) {
1517 os << "\\usepackage[";
1518 std::set<string>::const_iterator it = encodings.begin();
1519 std::set<string>::const_iterator const end = encodings.end();
1521 os << from_ascii(*it);
1524 for (; it != end; ++it)
1525 os << ',' << from_ascii(*it);
1526 if (package == Encoding::inputenc) {
1527 if (!encodings.empty())
1529 os << from_ascii(doc_encoding);
1531 os << "]{inputenc}\n";
1534 if (package == Encoding::CJK) {
1535 os << "\\usepackage{CJK}\n";
1538 } else if (inputenc != "default") {
1539 switch (encoding().package()) {
1540 case Encoding::none:
1542 case Encoding::inputenc:
1543 os << "\\usepackage[" << from_ascii(inputenc)
1548 os << "\\usepackage{CJK}\n";
1554 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1555 // armscii8 is used for Armenian.
1556 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1557 os << "\\usepackage{armtex}\n";
1563 string const BufferParams::loadFonts(string const & rm,
1564 string const & sf, string const & tt,
1565 bool const & sc, bool const & osf,
1566 int const & sfscale, int const & ttscale) const
1568 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1569 several packages have been replaced by others, that might not
1570 be installed on every system. We have to take care for that
1571 (see psnfss.pdf). We try to support all psnfss fonts as well
1572 as the fonts that have become de facto standard in the LaTeX
1573 world (e.g. Latin Modern). We do not support obsolete fonts
1574 (like PSLatex). In general, it should be possible to mix any
1575 rm font with any sf or tt font, respectively. (JSpitzm)
1577 -- separate math fonts.
1580 if (rm == "default" && sf == "default" && tt == "default")
1587 // Computer Modern (must be explicitely selectable -- there might be classes
1588 // that define a different default font!
1590 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1591 // osf for Computer Modern needs eco.sty
1593 os << "\\usepackage{eco}\n";
1595 // Latin Modern Roman
1596 else if (rm == "lmodern")
1597 os << "\\usepackage{lmodern}\n";
1599 else if (rm == "ae") {
1600 // not needed when using OT1 font encoding.
1601 if (lyxrc.fontenc != "default")
1602 os << "\\usepackage{ae,aecompl}\n";
1605 else if (rm == "times") {
1606 // try to load the best available package
1607 if (LaTeXFeatures::isAvailable("mathptmx"))
1608 os << "\\usepackage{mathptmx}\n";
1609 else if (LaTeXFeatures::isAvailable("mathptm"))
1610 os << "\\usepackage{mathptm}\n";
1612 os << "\\usepackage{times}\n";
1615 else if (rm == "palatino") {
1616 // try to load the best available package
1617 if (LaTeXFeatures::isAvailable("mathpazo")) {
1618 os << "\\usepackage";
1624 // "osf" includes "sc"!
1628 os << "{mathpazo}\n";
1630 else if (LaTeXFeatures::isAvailable("mathpple"))
1631 os << "\\usepackage{mathpple}\n";
1633 os << "\\usepackage{palatino}\n";
1636 else if (rm == "utopia") {
1637 // fourier supersedes utopia.sty, but does
1638 // not work with OT1 encoding.
1639 if (LaTeXFeatures::isAvailable("fourier")
1640 && lyxrc.fontenc != "default") {
1641 os << "\\usepackage";
1652 os << "{fourier}\n";
1655 os << "\\usepackage{utopia}\n";
1657 // Bera (complete fontset)
1658 else if (rm == "bera" && sf == "default" && tt == "default")
1659 os << "\\usepackage{bera}\n";
1661 else if (rm != "default")
1662 os << "\\usepackage" << "{" << rm << "}\n";
1665 // Helvetica, Bera Sans
1666 if (sf == "helvet" || sf == "berasans") {
1668 os << "\\usepackage[scaled=" << float(sfscale) / 100
1669 << "]{" << sf << "}\n";
1671 os << "\\usepackage{" << sf << "}\n";
1674 else if (sf == "avant")
1675 os << "\\usepackage{" << sf << "}\n";
1676 // Computer Modern, Latin Modern, CM Bright
1677 else if (sf != "default")
1678 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1680 // monospaced/typewriter
1681 // Courier, LuxiMono
1682 if (tt == "luximono" || tt == "beramono") {
1684 os << "\\usepackage[scaled=" << float(ttscale) / 100
1685 << "]{" << tt << "}\n";
1687 os << "\\usepackage{" << tt << "}\n";
1690 else if (tt == "courier" )
1691 os << "\\usepackage{" << tt << "}\n";
1692 // Computer Modern, Latin Modern, CM Bright
1693 else if (tt != "default")
1694 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1700 Encoding const & BufferParams::encoding() const
1702 if (inputenc == "auto" || inputenc == "default")
1703 return *(language->encoding());
1704 Encoding const * const enc =
1705 encodings.getFromLaTeXName(inputenc);
1708 lyxerr << "Unknown inputenc value `" << inputenc
1709 << "'. Using `auto' instead." << endl;
1710 return *(language->encoding());
1714 biblio::CiteEngine BufferParams::getEngine() const
1716 // FIXME the class should provide the numerical/
1717 // authoryear choice
1718 if (getTextClass().provides("natbib")
1719 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1720 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1721 return cite_engine_;
1725 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1727 cite_engine_ = cite_engine;