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 TextClassPtr BufferParams::getTextClassPtr() const {
1223 void BufferParams::setTextClass(TextClassPtr tc) {
1228 bool BufferParams::setBaseClass(textclass_type tc)
1231 if (textclasslist[tc].load())
1235 bformat(_("The document class %1$s could not be loaded."),
1236 from_utf8(textclasslist[tc].name()));
1237 frontend::Alert::error(_("Could not load class"), s);
1245 void BufferParams::setJustBaseClass(textclass_type tc)
1251 textclass_type BufferParams::getBaseClass() const
1257 void BufferParams::makeTextClass()
1259 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1260 //FIXME It might be worth loading the children's modules here,
1261 //just as we load their bibliographies and such, instead of just
1262 //doing a check in InsetInclude.
1263 LayoutModuleList::const_iterator it = layoutModules_.begin();
1264 for (; it != layoutModules_.end(); it++) {
1265 string const modName = *it;
1266 LyXModule * lm = moduleList[modName];
1268 docstring const msg =
1269 bformat(_("The module %1$s has been requested by\n"
1270 "this document but has not been found in the list of\n"
1271 "available modules. If you recently installed it, you\n"
1272 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1273 frontend::Alert::warning(_("Module not available"),
1274 msg + _("Some layouts may not be available."));
1275 lyxerr << "BufferParams::makeTextClass(): Module " <<
1276 modName << " requested but not found in module list." <<
1280 FileName layout_file = libFileSearch("layouts", lm->filename);
1281 textClass_->read(layout_file, TextClass::MODULE);
1286 std::vector<string> const & BufferParams::getModules() const {
1287 return layoutModules_;
1292 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1293 LayoutModuleList::const_iterator it = layoutModules_.begin();
1294 LayoutModuleList::const_iterator end = layoutModules_.end();
1295 for (; it != end; it++) {
1299 if (it != layoutModules_.end())
1301 layoutModules_.push_back(modName);
1308 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1311 std::vector<string>::const_iterator it = modNames.begin();
1312 std::vector<string>::const_iterator end = modNames.end();
1313 for (; it != end; ++it)
1314 retval &= addLayoutModule(*it, false);
1320 void BufferParams::clearLayoutModules() {
1321 layoutModules_.clear();
1326 Font const BufferParams::getFont() const
1328 Font f = getTextClass().defaultfont();
1329 f.setLanguage(language);
1330 if (fontsDefaultFamily == "rmdefault")
1331 f.setFamily(Font::ROMAN_FAMILY);
1332 else if (fontsDefaultFamily == "sfdefault")
1333 f.setFamily(Font::SANS_FAMILY);
1334 else if (fontsDefaultFamily == "ttdefault")
1335 f.setFamily(Font::TYPEWRITER_FAMILY);
1340 void BufferParams::readPreamble(Lexer & lex)
1342 if (lex.getString() != "\\begin_preamble")
1343 lyxerr << "Error (BufferParams::readPreamble):"
1344 "consistency check failed." << endl;
1346 preamble = lex.getLongString("\\end_preamble");
1350 void BufferParams::readLanguage(Lexer & lex)
1352 if (!lex.next()) return;
1354 string const tmptok = lex.getString();
1356 // check if tmptok is part of tex_babel in tex-defs.h
1357 language = languages.getLanguage(tmptok);
1359 // Language tmptok was not found
1360 language = default_language;
1361 lyxerr << "Warning: Setting language `"
1362 << tmptok << "' to `" << language->lang()
1368 void BufferParams::readGraphicsDriver(Lexer & lex)
1370 if (!lex.next()) return;
1372 string const tmptok = lex.getString();
1373 // check if tmptok is part of tex_graphics in tex_defs.h
1376 string const test = tex_graphics[n++];
1378 if (test == tmptok) {
1379 graphicsDriver = tmptok;
1381 } else if (test == "") {
1383 "Warning: graphics driver `$$Token' not recognized!\n"
1384 " Setting graphics driver to `default'.\n");
1385 graphicsDriver = "default";
1392 void BufferParams::readBullets(Lexer & lex)
1394 if (!lex.next()) return;
1396 int const index = lex.getInteger();
1398 int temp_int = lex.getInteger();
1399 user_defined_bullet(index).setFont(temp_int);
1400 temp_bullet(index).setFont(temp_int);
1402 user_defined_bullet(index).setCharacter(temp_int);
1403 temp_bullet(index).setCharacter(temp_int);
1405 user_defined_bullet(index).setSize(temp_int);
1406 temp_bullet(index).setSize(temp_int);
1410 void BufferParams::readBulletsLaTeX(Lexer & lex)
1412 // The bullet class should be able to read this.
1413 if (!lex.next()) return;
1414 int const index = lex.getInteger();
1416 docstring const temp_str = lex.getDocString();
1418 user_defined_bullet(index).setText(temp_str);
1419 temp_bullet(index).setText(temp_str);
1423 void BufferParams::readModules(Lexer & lex)
1425 if (!lex.eatLine()) {
1426 lyxerr << "Error (BufferParams::readModules):"
1427 "Unexpected end of input." << endl;
1431 string mod = lex.getString();
1432 if (mod == "\\end_modules")
1434 addLayoutModule(mod);
1440 string const BufferParams::paperSizeName() const
1442 char real_papersize = papersize;
1443 if (real_papersize == PAPER_DEFAULT)
1444 real_papersize = lyxrc.default_papersize;
1446 switch (real_papersize) {
1455 case PAPER_USEXECUTIVE:
1459 case PAPER_USLETTER:
1466 string const BufferParams::dvips_options() const
1471 && papersize == PAPER_CUSTOM
1472 && !lyxrc.print_paper_dimension_flag.empty()
1473 && !paperwidth.empty()
1474 && !paperheight.empty()) {
1475 // using a custom papersize
1476 result = lyxrc.print_paper_dimension_flag;
1477 result += ' ' + paperwidth;
1478 result += ',' + paperheight;
1480 string const paper_option = paperSizeName();
1481 if (paper_option != "letter" ||
1482 orientation != ORIENTATION_LANDSCAPE) {
1483 // dvips won't accept -t letter -t landscape.
1484 // In all other cases, include the paper size
1486 result = lyxrc.print_paper_flag;
1487 result += ' ' + paper_option;
1490 if (orientation == ORIENTATION_LANDSCAPE &&
1491 papersize != PAPER_CUSTOM)
1492 result += ' ' + lyxrc.print_landscape_flag;
1497 string const BufferParams::babelCall(string const & lang_opts) const
1499 string lang_pack = lyxrc.language_package;
1500 if (lang_pack != "\\usepackage{babel}")
1502 // suppress the babel call when there is no babel language defined
1503 // for the document language in the lib/languages file and if no
1504 // other languages are used (lang_opts is then empty)
1505 if (lang_opts.empty())
1507 if (!lyxrc.language_global_options)
1508 return "\\usepackage[" + lang_opts + "]{babel}";
1513 void BufferParams::writeEncodingPreamble(odocstream & os,
1514 LaTeXFeatures & features, TexRow & texrow) const
1516 if (inputenc == "auto") {
1517 string const doc_encoding =
1518 language->encoding()->latexName();
1519 Encoding::Package const package =
1520 language->encoding()->package();
1522 // Create a list with all the input encodings used
1524 std::set<string> encodings =
1525 features.getEncodingSet(doc_encoding);
1527 if (!encodings.empty() || package == Encoding::inputenc) {
1528 os << "\\usepackage[";
1529 std::set<string>::const_iterator it = encodings.begin();
1530 std::set<string>::const_iterator const end = encodings.end();
1532 os << from_ascii(*it);
1535 for (; it != end; ++it)
1536 os << ',' << from_ascii(*it);
1537 if (package == Encoding::inputenc) {
1538 if (!encodings.empty())
1540 os << from_ascii(doc_encoding);
1542 os << "]{inputenc}\n";
1545 if (package == Encoding::CJK) {
1546 os << "\\usepackage{CJK}\n";
1549 } else if (inputenc != "default") {
1550 switch (encoding().package()) {
1551 case Encoding::none:
1553 case Encoding::inputenc:
1554 os << "\\usepackage[" << from_ascii(inputenc)
1559 os << "\\usepackage{CJK}\n";
1565 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1566 // armscii8 is used for Armenian.
1567 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1568 os << "\\usepackage{armtex}\n";
1574 string const BufferParams::loadFonts(string const & rm,
1575 string const & sf, string const & tt,
1576 bool const & sc, bool const & osf,
1577 int const & sfscale, int const & ttscale) const
1579 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1580 several packages have been replaced by others, that might not
1581 be installed on every system. We have to take care for that
1582 (see psnfss.pdf). We try to support all psnfss fonts as well
1583 as the fonts that have become de facto standard in the LaTeX
1584 world (e.g. Latin Modern). We do not support obsolete fonts
1585 (like PSLatex). In general, it should be possible to mix any
1586 rm font with any sf or tt font, respectively. (JSpitzm)
1588 -- separate math fonts.
1591 if (rm == "default" && sf == "default" && tt == "default")
1598 // Computer Modern (must be explicitely selectable -- there might be classes
1599 // that define a different default font!
1601 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1602 // osf for Computer Modern needs eco.sty
1604 os << "\\usepackage{eco}\n";
1606 // Latin Modern Roman
1607 else if (rm == "lmodern")
1608 os << "\\usepackage{lmodern}\n";
1610 else if (rm == "ae") {
1611 // not needed when using OT1 font encoding.
1612 if (lyxrc.fontenc != "default")
1613 os << "\\usepackage{ae,aecompl}\n";
1616 else if (rm == "times") {
1617 // try to load the best available package
1618 if (LaTeXFeatures::isAvailable("mathptmx"))
1619 os << "\\usepackage{mathptmx}\n";
1620 else if (LaTeXFeatures::isAvailable("mathptm"))
1621 os << "\\usepackage{mathptm}\n";
1623 os << "\\usepackage{times}\n";
1626 else if (rm == "palatino") {
1627 // try to load the best available package
1628 if (LaTeXFeatures::isAvailable("mathpazo")) {
1629 os << "\\usepackage";
1635 // "osf" includes "sc"!
1639 os << "{mathpazo}\n";
1641 else if (LaTeXFeatures::isAvailable("mathpple"))
1642 os << "\\usepackage{mathpple}\n";
1644 os << "\\usepackage{palatino}\n";
1647 else if (rm == "utopia") {
1648 // fourier supersedes utopia.sty, but does
1649 // not work with OT1 encoding.
1650 if (LaTeXFeatures::isAvailable("fourier")
1651 && lyxrc.fontenc != "default") {
1652 os << "\\usepackage";
1663 os << "{fourier}\n";
1666 os << "\\usepackage{utopia}\n";
1668 // Bera (complete fontset)
1669 else if (rm == "bera" && sf == "default" && tt == "default")
1670 os << "\\usepackage{bera}\n";
1672 else if (rm != "default")
1673 os << "\\usepackage" << "{" << rm << "}\n";
1676 // Helvetica, Bera Sans
1677 if (sf == "helvet" || sf == "berasans") {
1679 os << "\\usepackage[scaled=" << float(sfscale) / 100
1680 << "]{" << sf << "}\n";
1682 os << "\\usepackage{" << sf << "}\n";
1685 else if (sf == "avant")
1686 os << "\\usepackage{" << sf << "}\n";
1687 // Computer Modern, Latin Modern, CM Bright
1688 else if (sf != "default")
1689 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1691 // monospaced/typewriter
1692 // Courier, LuxiMono
1693 if (tt == "luximono" || tt == "beramono") {
1695 os << "\\usepackage[scaled=" << float(ttscale) / 100
1696 << "]{" << tt << "}\n";
1698 os << "\\usepackage{" << tt << "}\n";
1701 else if (tt == "courier" )
1702 os << "\\usepackage{" << tt << "}\n";
1703 // Computer Modern, Latin Modern, CM Bright
1704 else if (tt != "default")
1705 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1711 Encoding const & BufferParams::encoding() const
1713 if (inputenc == "auto" || inputenc == "default")
1714 return *(language->encoding());
1715 Encoding const * const enc =
1716 encodings.getFromLaTeXName(inputenc);
1719 lyxerr << "Unknown inputenc value `" << inputenc
1720 << "'. Using `auto' instead." << endl;
1721 return *(language->encoding());
1725 biblio::CiteEngine BufferParams::getEngine() const
1727 // FIXME the class should provide the numerical/
1728 // authoryear choice
1729 if (getTextClass().provides("natbib")
1730 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1731 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1732 return cite_engine_;
1736 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1738 cite_engine_ = cite_engine;