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";
356 for (int iter = 0; iter < 4; ++iter) {
357 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
358 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
363 BufferParams::~BufferParams()
367 docstring const BufferParams::B_(string const & l10n) const
369 BOOST_ASSERT(language);
370 return getMessages(language->code()).get(l10n);
374 AuthorList & BufferParams::authors()
376 return pimpl_->authorlist;
380 AuthorList const & BufferParams::authors() const
382 return pimpl_->authorlist;
386 BranchList & BufferParams::branchlist()
388 return pimpl_->branchlist;
392 BranchList const & BufferParams::branchlist() const
394 return pimpl_->branchlist;
398 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
400 BOOST_ASSERT(index < 4);
401 return pimpl_->temp_bullets[index];
405 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
407 BOOST_ASSERT(index < 4);
408 return pimpl_->temp_bullets[index];
412 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
414 BOOST_ASSERT(index < 4);
415 return pimpl_->user_defined_bullets[index];
419 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
421 BOOST_ASSERT(index < 4);
422 return pimpl_->user_defined_bullets[index];
426 Spacing & BufferParams::spacing()
428 return pimpl_->spacing;
432 Spacing const & BufferParams::spacing() const
434 return pimpl_->spacing;
438 VSpace const & BufferParams::getDefSkip() const
440 return pimpl_->defskip;
444 void BufferParams::setDefSkip(VSpace const & vs)
446 pimpl_->defskip = vs;
450 string const BufferParams::readToken(Lexer & lex, string const & token)
452 if (token == "\\textclass") {
454 string const classname = lex.getString();
455 pair<bool, lyx::textclass_type> pp =
456 textclasslist.numberOfClass(classname);
458 setBaseClass(pp.second);
460 // if text class does not exist, try to load it from filepath
461 pp = textclasslist.addTextClass(classname, filepath);
463 setBaseClass(pp.second);
465 setBaseClass(defaultTextclass());
469 if (!getTextClass().isTeXClassAvailable()) {
470 docstring const msg =
471 bformat(_("The layout file requested by this document,\n"
473 "is not usable. This is probably because a LaTeX\n"
474 "class or style file required by it is not\n"
475 "available. See the Customization documentation\n"
476 "for more information.\n"), from_utf8(classname));
477 frontend::Alert::warning(_("Document class not available"),
478 msg + _("LyX will not be able to produce output."));
481 } else if (token == "\\begin_preamble") {
483 } else if (token == "\\begin_modules") {
486 } else if (token == "\\options") {
488 options = lex.getString();
489 } else if (token == "\\language") {
491 } else if (token == "\\inputencoding") {
493 } else if (token == "\\graphics") {
494 readGraphicsDriver(lex);
495 } else if (token == "\\font_roman") {
497 } else if (token == "\\font_sans") {
499 } else if (token == "\\font_typewriter") {
500 lex >> fontsTypewriter;
501 } else if (token == "\\font_default_family") {
502 lex >> fontsDefaultFamily;
503 } else if (token == "\\font_sc") {
505 } else if (token == "\\font_osf") {
507 } else if (token == "\\font_sf_scale") {
508 lex >> fontsSansScale;
509 } else if (token == "\\font_tt_scale") {
510 lex >> fontsTypewriterScale;
511 } else if (token == "\\paragraph_separation") {
514 paragraph_separation = parseptranslator().find(parsep);
515 } else if (token == "\\defskip") {
517 pimpl_->defskip = VSpace(lex.getString());
518 } else if (token == "\\quotes_language") {
521 quotes_language = quoteslangtranslator().find(quotes_lang);
522 } else if (token == "\\papersize") {
525 papersize = papersizetranslator().find(ppsize);
526 } else if (token == "\\use_geometry") {
528 } else if (token == "\\use_amsmath") {
531 use_amsmath = packagetranslator().find(use_ams);
532 } else if (token == "\\use_esint") {
535 use_esint = packagetranslator().find(useesint);
536 } else if (token == "\\cite_engine") {
539 cite_engine_ = citeenginetranslator().find(engine);
540 } else if (token == "\\use_bibtopic") {
542 } else if (token == "\\tracking_changes") {
544 } else if (token == "\\output_changes") {
545 lex >> outputChanges;
546 } else if (token == "\\branch") {
548 docstring branch = lex.getDocString();
549 branchlist().add(branch);
552 string const tok = lex.getString();
553 if (tok == "\\end_branch")
555 Branch * branch_ptr = branchlist().find(branch);
556 if (tok == "\\selected") {
559 branch_ptr->setSelected(lex.getInteger());
561 // not yet operational
562 if (tok == "\\color") {
564 string color = lex.getString();
566 branch_ptr->setColor(color);
567 // Update also the Color table:
569 color = lcolor.getX11Name(Color::background);
571 lcolor.setColor(to_utf8(branch), color);
575 } else if (token == "\\author") {
577 istringstream ss(lex.getString());
580 author_map.push_back(pimpl_->authorlist.record(a));
581 } else if (token == "\\paperorientation") {
584 orientation = paperorientationtranslator().find(orient);
585 } else if (token == "\\paperwidth") {
587 } else if (token == "\\paperheight") {
589 } else if (token == "\\leftmargin") {
591 } else if (token == "\\topmargin") {
593 } else if (token == "\\rightmargin") {
595 } else if (token == "\\bottommargin") {
597 } else if (token == "\\headheight") {
599 } else if (token == "\\headsep") {
601 } else if (token == "\\footskip") {
603 } else if (token == "\\paperfontsize") {
605 } else if (token == "\\papercolumns") {
607 } else if (token == "\\listings_params") {
610 listings_params = InsetListingsParams(par).params();
611 } else if (token == "\\papersides") {
614 sides = sidestranslator().find(psides);
615 } else if (token == "\\paperpagestyle") {
617 } else if (token == "\\bullet") {
619 } else if (token == "\\bulletLaTeX") {
620 readBulletsLaTeX(lex);
621 } else if (token == "\\secnumdepth") {
623 } else if (token == "\\tocdepth") {
625 } else if (token == "\\spacing") {
629 if (nspacing == "other") {
632 spacing().set(spacetranslator().find(nspacing), tmp_val);
633 } else if (token == "\\float_placement") {
634 lex >> float_placement;
636 lyxerr << "BufferParams::readToken(): Unknown token: " <<
645 void BufferParams::writeFile(ostream & os) const
647 // The top of the file is written by the buffer.
648 // Prints out the buffer info into the .lyx file given by file
651 os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
654 if (!preamble.empty()) {
655 // remove '\n' from the end of preamble
656 string const tmppreamble = rtrim(preamble, "\n");
657 os << "\\begin_preamble\n"
659 << "\n\\end_preamble\n";
663 if (!options.empty()) {
664 os << "\\options " << options << '\n';
668 if (!layoutModules_.empty()) {
669 os << "\\begin_modules" << '\n';
670 LayoutModuleList::const_iterator it = layoutModules_.begin();
671 for (; it != layoutModules_.end(); it++)
673 os << "\\end_modules" << '\n';
676 // then the text parameters
677 if (language != ignore_language)
678 os << "\\language " << language->lang() << '\n';
679 os << "\\inputencoding " << inputenc
680 << "\n\\font_roman " << fontsRoman
681 << "\n\\font_sans " << fontsSans
682 << "\n\\font_typewriter " << fontsTypewriter
683 << "\n\\font_default_family " << fontsDefaultFamily
684 << "\n\\font_sc " << convert<string>(fontsSC)
685 << "\n\\font_osf " << convert<string>(fontsOSF)
686 << "\n\\font_sf_scale " << fontsSansScale
687 << "\n\\font_tt_scale " << fontsTypewriterScale
688 << "\n\\graphics " << graphicsDriver << '\n';
690 if (!float_placement.empty()) {
691 os << "\\float_placement " << float_placement << '\n';
693 os << "\\paperfontsize " << fontsize << '\n';
695 spacing().writeFile(os);
697 os << "\\papersize " << string_papersize[papersize]
698 << "\n\\use_geometry " << convert<string>(use_geometry)
699 << "\n\\use_amsmath " << use_amsmath
700 << "\n\\use_esint " << use_esint
701 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
702 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
703 << "\n\\paperorientation " << string_orientation[orientation]
706 BranchList::const_iterator it = branchlist().begin();
707 BranchList::const_iterator end = branchlist().end();
708 for (; it != end; ++it) {
709 os << "\\branch " << to_utf8(it->getBranch())
710 << "\n\\selected " << it->getSelected()
711 << "\n\\color " << lyx::X11hexname(it->getColor())
716 if (!paperwidth.empty())
717 os << "\\paperwidth "
718 << VSpace(paperwidth).asLyXCommand() << '\n';
719 if (!paperheight.empty())
720 os << "\\paperheight "
721 << VSpace(paperheight).asLyXCommand() << '\n';
722 if (!leftmargin.empty())
723 os << "\\leftmargin "
724 << VSpace(leftmargin).asLyXCommand() << '\n';
725 if (!topmargin.empty())
727 << VSpace(topmargin).asLyXCommand() << '\n';
728 if (!rightmargin.empty())
729 os << "\\rightmargin "
730 << VSpace(rightmargin).asLyXCommand() << '\n';
731 if (!bottommargin.empty())
732 os << "\\bottommargin "
733 << VSpace(bottommargin).asLyXCommand() << '\n';
734 if (!headheight.empty())
735 os << "\\headheight "
736 << VSpace(headheight).asLyXCommand() << '\n';
737 if (!headsep.empty())
739 << VSpace(headsep).asLyXCommand() << '\n';
740 if (!footskip.empty())
742 << VSpace(footskip).asLyXCommand() << '\n';
743 os << "\\secnumdepth " << secnumdepth
744 << "\n\\tocdepth " << tocdepth
745 << "\n\\paragraph_separation "
746 << string_paragraph_separation[paragraph_separation]
747 << "\n\\defskip " << getDefSkip().asLyXCommand()
748 << "\n\\quotes_language "
749 << string_quotes_language[quotes_language]
750 << "\n\\papercolumns " << columns
751 << "\n\\papersides " << sides
752 << "\n\\paperpagestyle " << pagestyle << '\n';
753 if (!listings_params.empty())
754 os << "\\listings_params \"" <<
755 InsetListingsParams(listings_params).encodedString() << "\"\n";
756 for (int i = 0; i < 4; ++i) {
757 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
758 if (user_defined_bullet(i).getFont() != -1) {
759 os << "\\bullet " << i << " "
760 << user_defined_bullet(i).getFont() << " "
761 << user_defined_bullet(i).getCharacter() << " "
762 << user_defined_bullet(i).getSize() << "\n";
766 os << "\\bulletLaTeX " << i << " \""
767 << lyx::to_ascii(user_defined_bullet(i).getText())
773 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
774 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
776 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
777 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
778 for (; a_it != a_end; ++a_it) {
779 if (a_it->second.used())
780 os << "\\author " << a_it->second << "\n";
782 os << "\\author " << Author() << "\n";
787 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
788 TexRow & texrow) const
790 os << "\\documentclass";
792 TextClass const & tclass = getTextClass();
794 ostringstream clsoptions; // the document class options.
796 if (tokenPos(tclass.opt_fontsize(),
797 '|', fontsize) >= 0) {
798 // only write if existing in list (and not default)
799 clsoptions << fontsize << "pt,";
802 // custom, A3, B3 and B4 paper sizes need geometry
803 bool nonstandard_papersize = papersize == PAPER_B3
804 || papersize == PAPER_B4
805 || papersize == PAPER_A3
806 || papersize == PAPER_CUSTOM;
811 clsoptions << "a4paper,";
814 clsoptions << "letterpaper,";
817 clsoptions << "a5paper,";
820 clsoptions << "b5paper,";
822 case PAPER_USEXECUTIVE:
823 clsoptions << "executivepaper,";
826 clsoptions << "legalpaper,";
838 if (sides != tclass.sides()) {
840 case TextClass::OneSide:
841 clsoptions << "oneside,";
843 case TextClass::TwoSides:
844 clsoptions << "twoside,";
850 if (columns != tclass.columns()) {
852 clsoptions << "twocolumn,";
854 clsoptions << "onecolumn,";
858 && orientation == ORIENTATION_LANDSCAPE)
859 clsoptions << "landscape,";
861 // language should be a parameter to \documentclass
862 if (language->babel() == "hebrew"
863 && default_language->babel() != "hebrew")
864 // This seems necessary
865 features.useLanguage(default_language);
867 ostringstream language_options;
868 bool const use_babel = features.useBabel();
870 language_options << features.getLanguages();
871 if (!language->babel().empty()) {
872 if (!language_options.str().empty())
873 language_options << ',';
874 language_options << language->babel();
876 if (lyxrc.language_global_options && !language_options.str().empty())
877 clsoptions << language_options.str() << ',';
880 // the user-defined options
881 if (!options.empty()) {
882 clsoptions << options << ',';
885 string strOptions(clsoptions.str());
886 if (!strOptions.empty()) {
887 strOptions = rtrim(strOptions, ",");
889 os << '[' << from_utf8(strOptions) << ']';
892 os << '{' << from_ascii(tclass.latexname()) << "}\n";
894 // end of \documentclass defs
896 // font selection must be done before loading fontenc.sty
898 loadFonts(fontsRoman, fontsSans,
899 fontsTypewriter, fontsSC, fontsOSF,
900 fontsSansScale, fontsTypewriterScale);
901 if (!fonts.empty()) {
902 os << from_ascii(fonts);
905 if (fontsDefaultFamily != "default")
906 os << "\\renewcommand{\\familydefault}{\\"
907 << from_ascii(fontsDefaultFamily) << "}\n";
910 // this one is not per buffer
911 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
912 if (lyxrc.fontenc != "default") {
913 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
914 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
915 << ",LFE,LAE]{fontenc}\n";
918 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
924 // handle inputenc etc.
925 writeEncodingPreamble(os, features, texrow);
927 if (!listings_params.empty()) {
928 os << "\\usepackage{listings}\n";
931 // do not test validity because listings_params is supposed to be valid
932 string par = InsetListingsParams(listings_params).separatedParams(true);
933 os << from_ascii(par);
934 // count the number of newlines
935 for (size_t i = 0; i < par.size(); ++i)
941 if (use_geometry || nonstandard_papersize) {
942 os << "\\usepackage{geometry}\n";
944 os << "\\geometry{verbose";
945 if (orientation == ORIENTATION_LANDSCAPE)
949 if (!paperwidth.empty())
951 << from_ascii(paperwidth);
952 if (!paperheight.empty())
953 os << ",paperheight="
954 << from_ascii(paperheight);
957 os << ",letterpaper";
962 case PAPER_USEXECUTIVE:
963 os << ",executivepaper";
984 // default papersize ie PAPER_DEFAULT
985 switch (lyxrc.default_papersize) {
986 case PAPER_DEFAULT: // keep compiler happy
988 os << ",letterpaper";
993 case PAPER_USEXECUTIVE:
994 os << ",executivepaper";
1014 if (!topmargin.empty())
1015 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1016 if (!bottommargin.empty())
1017 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1018 if (!leftmargin.empty())
1019 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1020 if (!rightmargin.empty())
1021 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1022 if (!headheight.empty())
1023 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1024 if (!headsep.empty())
1025 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1026 if (!footskip.empty())
1027 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1032 if (tokenPos(tclass.opt_pagestyle(),
1033 '|', pagestyle) >= 0) {
1034 if (pagestyle == "fancy") {
1035 os << "\\usepackage{fancyhdr}\n";
1038 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1042 // Only if class has a ToC hierarchy
1043 if (tclass.hasTocLevels()) {
1044 if (secnumdepth != tclass.secnumdepth()) {
1045 os << "\\setcounter{secnumdepth}{"
1050 if (tocdepth != tclass.tocdepth()) {
1051 os << "\\setcounter{tocdepth}{"
1058 if (paragraph_separation) {
1059 switch (getDefSkip().kind()) {
1060 case VSpace::SMALLSKIP:
1061 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1063 case VSpace::MEDSKIP:
1064 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1066 case VSpace::BIGSKIP:
1067 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1069 case VSpace::LENGTH:
1070 os << "\\setlength{\\parskip}{"
1071 << from_utf8(getDefSkip().length().asLatexString())
1074 default: // should never happen // Then delete it.
1075 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1080 os << "\\setlength{\\parindent}{0pt}\n";
1084 // If we use jurabib, we have to call babel here.
1085 if (use_babel && features.isRequired("jurabib")) {
1086 os << from_ascii(babelCall(language_options.str()))
1088 << from_ascii(features.getBabelOptions());
1092 // Now insert the LyX specific LaTeX commands...
1094 // The optional packages;
1095 docstring lyxpreamble(from_ascii(features.getPackages()));
1097 // this might be useful...
1098 lyxpreamble += "\n\\makeatletter\n";
1100 // Some macros LyX will need
1101 docstring tmppreamble(from_ascii(features.getMacros()));
1103 if (!tmppreamble.empty()) {
1104 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1105 "LyX specific LaTeX commands.\n"
1106 + tmppreamble + '\n';
1109 // the text class specific preamble
1110 tmppreamble = features.getTClassPreamble();
1111 if (!tmppreamble.empty()) {
1112 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1113 "Textclass specific LaTeX commands.\n"
1114 + tmppreamble + '\n';
1117 /* the user-defined preamble */
1118 if (!preamble.empty()) {
1120 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1121 "User specified LaTeX commands.\n"
1122 + from_utf8(preamble) + '\n';
1125 // Itemize bullet settings need to be last in case the user
1126 // defines their own bullets that use a package included
1127 // in the user-defined preamble -- ARRae
1128 // Actually it has to be done much later than that
1129 // since some packages like frenchb make modifications
1130 // at \begin{document} time -- JMarc
1131 docstring bullets_def;
1132 for (int i = 0; i < 4; ++i) {
1133 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1134 if (bullets_def.empty())
1135 bullets_def += "\\AtBeginDocument{\n";
1136 bullets_def += " \\def\\labelitemi";
1138 // `i' is one less than the item to modify
1145 bullets_def += "ii";
1151 bullets_def += '{' +
1152 user_defined_bullet(i).getText()
1157 if (!bullets_def.empty())
1158 lyxpreamble += bullets_def + "}\n\n";
1160 // We try to load babel late, in case it interferes
1161 // with other packages.
1162 // Jurabib has to be called after babel, though.
1163 if (use_babel && !features.isRequired("jurabib")) {
1165 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1166 lyxpreamble += from_utf8(features.getBabelOptions());
1169 lyxpreamble += "\\makeatother\n\n";
1172 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1173 for (int j = 0; j != nlines; ++j) {
1182 void BufferParams::useClassDefaults()
1184 TextClass const & tclass = textclasslist[baseClass_];
1186 sides = tclass.sides();
1187 columns = tclass.columns();
1188 pagestyle = tclass.pagestyle();
1189 options = tclass.options();
1190 // Only if class has a ToC hierarchy
1191 if (tclass.hasTocLevels()) {
1192 secnumdepth = tclass.secnumdepth();
1193 tocdepth = tclass.tocdepth();
1198 bool BufferParams::hasClassDefaults() const
1200 TextClass const & tclass = textclasslist[baseClass_];
1202 return (sides == tclass.sides()
1203 && columns == tclass.columns()
1204 && pagestyle == tclass.pagestyle()
1205 && options == tclass.options()
1206 && secnumdepth == tclass.secnumdepth()
1207 && tocdepth == tclass.tocdepth());
1211 TextClass const & BufferParams::getTextClass() const
1217 TextClass_ptr BufferParams::getTextClass_ptr() const {
1222 void BufferParams::setTextClass(TextClass_ptr tc) {
1227 void BufferParams::setBaseClass(textclass_type tc)
1234 void BufferParams::setJustBaseClass(textclass_type tc)
1240 textclass_type BufferParams::getBaseClass() const
1246 void BufferParams::makeTextClass()
1248 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1249 //FIXME It might be worth loading the children's modules here,
1250 //instead of just doing a check in InsetInclude.
1251 LayoutModuleList::const_iterator it = layoutModules_.begin();
1252 for (; it != layoutModules_.end(); it++) {
1253 string const modName = *it;
1254 LyXModule * lm = moduleList[modName];
1256 docstring const msg =
1257 bformat(_("The module %1$s has been requested by\n"
1258 "this document but has not been found in the list of\n"
1259 "available modules. If you recently installed it, you\n"
1260 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1261 frontend::Alert::warning(_("Module not available"),
1262 msg + _("Some layouts may not be available."));
1263 lyxerr << "BufferParams::makeTextClass(): Module " <<
1264 modName << " requested but not found in module list." <<
1268 FileName layout_file = libFileSearch("layouts", lm->filename);
1269 textClass_->read(layout_file, TextClass::MODULE);
1274 std::vector<string> const & BufferParams::getModules() const {
1275 return layoutModules_;
1280 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1281 LayoutModuleList::const_iterator it = layoutModules_.begin();
1282 LayoutModuleList::const_iterator end = layoutModules_.end();
1283 for (; it != end; it++) {
1287 if (it != layoutModules_.end())
1289 layoutModules_.push_back(modName);
1296 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1299 std::vector<string>::const_iterator it = modNames.begin();
1300 std::vector<string>::const_iterator end = modNames.end();
1301 for (; it != end; ++it)
1302 retval &= addLayoutModule(*it, false);
1308 void BufferParams::clearLayoutModules() {
1309 layoutModules_.clear();
1314 Font const BufferParams::getFont() const
1316 Font f = getTextClass().defaultfont();
1317 f.setLanguage(language);
1318 if (fontsDefaultFamily == "rmdefault")
1319 f.setFamily(Font::ROMAN_FAMILY);
1320 else if (fontsDefaultFamily == "sfdefault")
1321 f.setFamily(Font::SANS_FAMILY);
1322 else if (fontsDefaultFamily == "ttdefault")
1323 f.setFamily(Font::TYPEWRITER_FAMILY);
1328 void BufferParams::readPreamble(Lexer & lex)
1330 if (lex.getString() != "\\begin_preamble")
1331 lyxerr << "Error (BufferParams::readPreamble):"
1332 "consistency check failed." << endl;
1334 preamble = lex.getLongString("\\end_preamble");
1338 void BufferParams::readLanguage(Lexer & lex)
1340 if (!lex.next()) return;
1342 string const tmptok = lex.getString();
1344 // check if tmptok is part of tex_babel in tex-defs.h
1345 language = languages.getLanguage(tmptok);
1347 // Language tmptok was not found
1348 language = default_language;
1349 lyxerr << "Warning: Setting language `"
1350 << tmptok << "' to `" << language->lang()
1356 void BufferParams::readGraphicsDriver(Lexer & lex)
1358 if (!lex.next()) return;
1360 string const tmptok = lex.getString();
1361 // check if tmptok is part of tex_graphics in tex_defs.h
1364 string const test = tex_graphics[n++];
1366 if (test == tmptok) {
1367 graphicsDriver = tmptok;
1369 } else if (test == "") {
1371 "Warning: graphics driver `$$Token' not recognized!\n"
1372 " Setting graphics driver to `default'.\n");
1373 graphicsDriver = "default";
1380 void BufferParams::readBullets(Lexer & lex)
1382 if (!lex.next()) return;
1384 int const index = lex.getInteger();
1386 int temp_int = lex.getInteger();
1387 user_defined_bullet(index).setFont(temp_int);
1388 temp_bullet(index).setFont(temp_int);
1390 user_defined_bullet(index).setCharacter(temp_int);
1391 temp_bullet(index).setCharacter(temp_int);
1393 user_defined_bullet(index).setSize(temp_int);
1394 temp_bullet(index).setSize(temp_int);
1398 void BufferParams::readBulletsLaTeX(Lexer & lex)
1400 // The bullet class should be able to read this.
1401 if (!lex.next()) return;
1402 int const index = lex.getInteger();
1404 docstring const temp_str = lex.getDocString();
1406 user_defined_bullet(index).setText(temp_str);
1407 temp_bullet(index).setText(temp_str);
1411 void BufferParams::readModules(Lexer & lex)
1413 if (!lex.eatLine()) {
1414 lyxerr << "Error (BufferParams::readModules):"
1415 "Unexpected end of input." << endl;
1419 string mod = lex.getString();
1420 if (mod == "\\end_modules")
1422 addLayoutModule(mod);
1428 string const BufferParams::paperSizeName() const
1430 char real_papersize = papersize;
1431 if (real_papersize == PAPER_DEFAULT)
1432 real_papersize = lyxrc.default_papersize;
1434 switch (real_papersize) {
1443 case PAPER_USEXECUTIVE:
1447 case PAPER_USLETTER:
1454 string const BufferParams::dvips_options() const
1459 && papersize == PAPER_CUSTOM
1460 && !lyxrc.print_paper_dimension_flag.empty()
1461 && !paperwidth.empty()
1462 && !paperheight.empty()) {
1463 // using a custom papersize
1464 result = lyxrc.print_paper_dimension_flag;
1465 result += ' ' + paperwidth;
1466 result += ',' + paperheight;
1468 string const paper_option = paperSizeName();
1469 if (paper_option != "letter" ||
1470 orientation != ORIENTATION_LANDSCAPE) {
1471 // dvips won't accept -t letter -t landscape.
1472 // In all other cases, include the paper size
1474 result = lyxrc.print_paper_flag;
1475 result += ' ' + paper_option;
1478 if (orientation == ORIENTATION_LANDSCAPE &&
1479 papersize != PAPER_CUSTOM)
1480 result += ' ' + lyxrc.print_landscape_flag;
1485 string const BufferParams::babelCall(string const & lang_opts) const
1487 string lang_pack = lyxrc.language_package;
1488 if (lang_pack != "\\usepackage{babel}")
1490 // suppress the babel call when there is no babel language defined
1491 // for the document language in the lib/languages file and if no
1492 // other languages are used (lang_opts is then empty)
1493 if (lang_opts.empty())
1495 if (!lyxrc.language_global_options)
1496 return "\\usepackage[" + lang_opts + "]{babel}";
1501 void BufferParams::writeEncodingPreamble(odocstream & os,
1502 LaTeXFeatures & features, TexRow & texrow) const
1504 if (inputenc == "auto") {
1505 string const doc_encoding =
1506 language->encoding()->latexName();
1507 Encoding::Package const package =
1508 language->encoding()->package();
1510 // Create a list with all the input encodings used
1512 std::set<string> encodings =
1513 features.getEncodingSet(doc_encoding);
1515 if (!encodings.empty() || package == Encoding::inputenc) {
1516 os << "\\usepackage[";
1517 std::set<string>::const_iterator it = encodings.begin();
1518 std::set<string>::const_iterator const end = encodings.end();
1520 os << from_ascii(*it);
1523 for (; it != end; ++it)
1524 os << ',' << from_ascii(*it);
1525 if (package == Encoding::inputenc) {
1526 if (!encodings.empty())
1528 os << from_ascii(doc_encoding);
1530 os << "]{inputenc}\n";
1533 if (package == Encoding::CJK) {
1534 os << "\\usepackage{CJK}\n";
1537 } else if (inputenc != "default") {
1538 switch (encoding().package()) {
1539 case Encoding::none:
1541 case Encoding::inputenc:
1542 os << "\\usepackage[" << from_ascii(inputenc)
1547 os << "\\usepackage{CJK}\n";
1553 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1554 // armscii8 is used for Armenian.
1555 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1556 os << "\\usepackage{armtex}\n";
1562 string const BufferParams::loadFonts(string const & rm,
1563 string const & sf, string const & tt,
1564 bool const & sc, bool const & osf,
1565 int const & sfscale, int const & ttscale) const
1567 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1568 several packages have been replaced by others, that might not
1569 be installed on every system. We have to take care for that
1570 (see psnfss.pdf). We try to support all psnfss fonts as well
1571 as the fonts that have become de facto standard in the LaTeX
1572 world (e.g. Latin Modern). We do not support obsolete fonts
1573 (like PSLatex). In general, it should be possible to mix any
1574 rm font with any sf or tt font, respectively. (JSpitzm)
1576 -- separate math fonts.
1579 if (rm == "default" && sf == "default" && tt == "default")
1586 // Computer Modern (must be explicitely selectable -- there might be classes
1587 // that define a different default font!
1589 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1590 // osf for Computer Modern needs eco.sty
1592 os << "\\usepackage{eco}\n";
1594 // Latin Modern Roman
1595 else if (rm == "lmodern")
1596 os << "\\usepackage{lmodern}\n";
1598 else if (rm == "ae") {
1599 // not needed when using OT1 font encoding.
1600 if (lyxrc.fontenc != "default")
1601 os << "\\usepackage{ae,aecompl}\n";
1604 else if (rm == "times") {
1605 // try to load the best available package
1606 if (LaTeXFeatures::isAvailable("mathptmx"))
1607 os << "\\usepackage{mathptmx}\n";
1608 else if (LaTeXFeatures::isAvailable("mathptm"))
1609 os << "\\usepackage{mathptm}\n";
1611 os << "\\usepackage{times}\n";
1614 else if (rm == "palatino") {
1615 // try to load the best available package
1616 if (LaTeXFeatures::isAvailable("mathpazo")) {
1617 os << "\\usepackage";
1623 // "osf" includes "sc"!
1627 os << "{mathpazo}\n";
1629 else if (LaTeXFeatures::isAvailable("mathpple"))
1630 os << "\\usepackage{mathpple}\n";
1632 os << "\\usepackage{palatino}\n";
1635 else if (rm == "utopia") {
1636 // fourier supersedes utopia.sty, but does
1637 // not work with OT1 encoding.
1638 if (LaTeXFeatures::isAvailable("fourier")
1639 && lyxrc.fontenc != "default") {
1640 os << "\\usepackage";
1651 os << "{fourier}\n";
1654 os << "\\usepackage{utopia}\n";
1656 // Bera (complete fontset)
1657 else if (rm == "bera" && sf == "default" && tt == "default")
1658 os << "\\usepackage{bera}\n";
1660 else if (rm != "default")
1661 os << "\\usepackage" << "{" << rm << "}\n";
1664 // Helvetica, Bera Sans
1665 if (sf == "helvet" || sf == "berasans") {
1667 os << "\\usepackage[scaled=" << float(sfscale) / 100
1668 << "]{" << sf << "}\n";
1670 os << "\\usepackage{" << sf << "}\n";
1673 else if (sf == "avant")
1674 os << "\\usepackage{" << sf << "}\n";
1675 // Computer Modern, Latin Modern, CM Bright
1676 else if (sf != "default")
1677 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1679 // monospaced/typewriter
1680 // Courier, LuxiMono
1681 if (tt == "luximono" || tt == "beramono") {
1683 os << "\\usepackage[scaled=" << float(ttscale) / 100
1684 << "]{" << tt << "}\n";
1686 os << "\\usepackage{" << tt << "}\n";
1689 else if (tt == "courier" )
1690 os << "\\usepackage{" << tt << "}\n";
1691 // Computer Modern, Latin Modern, CM Bright
1692 else if (tt != "default")
1693 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1699 Encoding const & BufferParams::encoding() const
1701 if (inputenc == "auto" || inputenc == "default")
1702 return *(language->encoding());
1703 Encoding const * const enc =
1704 encodings.getFromLaTeXName(inputenc);
1707 lyxerr << "Unknown inputenc value `" << inputenc
1708 << "'. Using `auto' instead." << endl;
1709 return *(language->encoding());
1713 biblio::CiteEngine BufferParams::getEngine() const
1715 // FIXME the class should provide the numerical/
1716 // authoryear choice
1717 if (getTextClass().provides("natbib")
1718 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1719 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1720 return cite_engine_;
1724 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1726 cite_engine_ = cite_engine;