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 // temporarily enable embedding for testing. Will set to false
357 // when embedding GUI is added
359 for (int iter = 0; iter < 4; ++iter) {
360 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
361 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
366 BufferParams::~BufferParams()
370 docstring const BufferParams::B_(string const & l10n) const
372 BOOST_ASSERT(language);
373 return getMessages(language->code()).get(l10n);
377 AuthorList & BufferParams::authors()
379 return pimpl_->authorlist;
383 AuthorList const & BufferParams::authors() const
385 return pimpl_->authorlist;
389 BranchList & BufferParams::branchlist()
391 return pimpl_->branchlist;
395 BranchList const & BufferParams::branchlist() const
397 return pimpl_->branchlist;
401 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
403 BOOST_ASSERT(index < 4);
404 return pimpl_->temp_bullets[index];
408 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
410 BOOST_ASSERT(index < 4);
411 return pimpl_->temp_bullets[index];
415 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
417 BOOST_ASSERT(index < 4);
418 return pimpl_->user_defined_bullets[index];
422 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
424 BOOST_ASSERT(index < 4);
425 return pimpl_->user_defined_bullets[index];
429 Spacing & BufferParams::spacing()
431 return pimpl_->spacing;
435 Spacing const & BufferParams::spacing() const
437 return pimpl_->spacing;
441 VSpace const & BufferParams::getDefSkip() const
443 return pimpl_->defskip;
447 void BufferParams::setDefSkip(VSpace const & vs)
449 pimpl_->defskip = vs;
453 string const BufferParams::readToken(Lexer & lex, string const & token)
455 if (token == "\\textclass") {
457 string const classname = lex.getString();
458 pair<bool, lyx::textclass_type> pp =
459 textclasslist.numberOfClass(classname);
461 setBaseClass(pp.second);
463 // if text class does not exist, try to load it from filepath
464 pp = textclasslist.addTextClass(classname, filepath);
466 setBaseClass(pp.second);
468 setBaseClass(defaultTextclass());
472 if (!getTextClass().isTeXClassAvailable()) {
473 docstring const msg =
474 bformat(_("The layout file requested by this document,\n"
476 "is not usable. This is probably because a LaTeX\n"
477 "class or style file required by it is not\n"
478 "available. See the Customization documentation\n"
479 "for more information.\n"), from_utf8(classname));
480 frontend::Alert::warning(_("Document class not available"),
481 msg + _("LyX will not be able to produce output."));
484 } else if (token == "\\begin_preamble") {
486 } else if (token == "\\begin_modules") {
489 } else if (token == "\\options") {
491 options = lex.getString();
492 } else if (token == "\\language") {
494 } else if (token == "\\inputencoding") {
496 } else if (token == "\\graphics") {
497 readGraphicsDriver(lex);
498 } else if (token == "\\font_roman") {
500 } else if (token == "\\font_sans") {
502 } else if (token == "\\font_typewriter") {
503 lex >> fontsTypewriter;
504 } else if (token == "\\font_default_family") {
505 lex >> fontsDefaultFamily;
506 } else if (token == "\\font_sc") {
508 } else if (token == "\\font_osf") {
510 } else if (token == "\\font_sf_scale") {
511 lex >> fontsSansScale;
512 } else if (token == "\\font_tt_scale") {
513 lex >> fontsTypewriterScale;
514 } else if (token == "\\paragraph_separation") {
517 paragraph_separation = parseptranslator().find(parsep);
518 } else if (token == "\\defskip") {
520 pimpl_->defskip = VSpace(lex.getString());
521 } else if (token == "\\quotes_language") {
524 quotes_language = quoteslangtranslator().find(quotes_lang);
525 } else if (token == "\\papersize") {
528 papersize = papersizetranslator().find(ppsize);
529 } else if (token == "\\use_geometry") {
531 } else if (token == "\\use_amsmath") {
534 use_amsmath = packagetranslator().find(use_ams);
535 } else if (token == "\\use_esint") {
538 use_esint = packagetranslator().find(useesint);
539 } else if (token == "\\cite_engine") {
542 cite_engine_ = citeenginetranslator().find(engine);
543 } else if (token == "\\use_bibtopic") {
545 } else if (token == "\\tracking_changes") {
547 } else if (token == "\\output_changes") {
548 lex >> outputChanges;
549 } else if (token == "\\branch") {
551 docstring branch = lex.getDocString();
552 branchlist().add(branch);
555 string const tok = lex.getString();
556 if (tok == "\\end_branch")
558 Branch * branch_ptr = branchlist().find(branch);
559 if (tok == "\\selected") {
562 branch_ptr->setSelected(lex.getInteger());
564 // not yet operational
565 if (tok == "\\color") {
567 string color = lex.getString();
569 branch_ptr->setColor(color);
570 // Update also the Color table:
572 color = lcolor.getX11Name(Color::background);
574 lcolor.setColor(to_utf8(branch), color);
578 } else if (token == "\\author") {
580 istringstream ss(lex.getString());
583 author_map.push_back(pimpl_->authorlist.record(a));
584 } else if (token == "\\paperorientation") {
587 orientation = paperorientationtranslator().find(orient);
588 } else if (token == "\\paperwidth") {
590 } else if (token == "\\paperheight") {
592 } else if (token == "\\leftmargin") {
594 } else if (token == "\\topmargin") {
596 } else if (token == "\\rightmargin") {
598 } else if (token == "\\bottommargin") {
600 } else if (token == "\\headheight") {
602 } else if (token == "\\headsep") {
604 } else if (token == "\\footskip") {
606 } else if (token == "\\paperfontsize") {
608 } else if (token == "\\papercolumns") {
610 } else if (token == "\\listings_params") {
613 listings_params = InsetListingsParams(par).params();
614 } else if (token == "\\papersides") {
617 sides = sidestranslator().find(psides);
618 } else if (token == "\\paperpagestyle") {
620 } else if (token == "\\bullet") {
622 } else if (token == "\\bulletLaTeX") {
623 readBulletsLaTeX(lex);
624 } else if (token == "\\secnumdepth") {
626 } else if (token == "\\tocdepth") {
628 } else if (token == "\\spacing") {
632 if (nspacing == "other") {
635 spacing().set(spacetranslator().find(nspacing), tmp_val);
636 } else if (token == "\\float_placement") {
637 lex >> float_placement;
639 lyxerr << "BufferParams::readToken(): Unknown token: " <<
648 void BufferParams::writeFile(ostream & os) const
650 // The top of the file is written by the buffer.
651 // Prints out the buffer info into the .lyx file given by file
654 os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
657 if (!preamble.empty()) {
658 // remove '\n' from the end of preamble
659 string const tmppreamble = rtrim(preamble, "\n");
660 os << "\\begin_preamble\n"
662 << "\n\\end_preamble\n";
666 if (!options.empty()) {
667 os << "\\options " << options << '\n';
671 if (!layoutModules_.empty()) {
672 os << "\\begin_modules" << '\n';
673 LayoutModuleList::const_iterator it = layoutModules_.begin();
674 for (; it != layoutModules_.end(); it++)
676 os << "\\end_modules" << '\n';
679 // then the text parameters
680 if (language != ignore_language)
681 os << "\\language " << language->lang() << '\n';
682 os << "\\inputencoding " << inputenc
683 << "\n\\font_roman " << fontsRoman
684 << "\n\\font_sans " << fontsSans
685 << "\n\\font_typewriter " << fontsTypewriter
686 << "\n\\font_default_family " << fontsDefaultFamily
687 << "\n\\font_sc " << convert<string>(fontsSC)
688 << "\n\\font_osf " << convert<string>(fontsOSF)
689 << "\n\\font_sf_scale " << fontsSansScale
690 << "\n\\font_tt_scale " << fontsTypewriterScale
691 << "\n\\graphics " << graphicsDriver << '\n';
693 if (!float_placement.empty()) {
694 os << "\\float_placement " << float_placement << '\n';
696 os << "\\paperfontsize " << fontsize << '\n';
698 spacing().writeFile(os);
700 os << "\\papersize " << string_papersize[papersize]
701 << "\n\\use_geometry " << convert<string>(use_geometry)
702 << "\n\\use_amsmath " << use_amsmath
703 << "\n\\use_esint " << use_esint
704 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
705 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
706 << "\n\\paperorientation " << string_orientation[orientation]
709 BranchList::const_iterator it = branchlist().begin();
710 BranchList::const_iterator end = branchlist().end();
711 for (; it != end; ++it) {
712 os << "\\branch " << to_utf8(it->getBranch())
713 << "\n\\selected " << it->getSelected()
714 << "\n\\color " << lyx::X11hexname(it->getColor())
719 if (!paperwidth.empty())
720 os << "\\paperwidth "
721 << VSpace(paperwidth).asLyXCommand() << '\n';
722 if (!paperheight.empty())
723 os << "\\paperheight "
724 << VSpace(paperheight).asLyXCommand() << '\n';
725 if (!leftmargin.empty())
726 os << "\\leftmargin "
727 << VSpace(leftmargin).asLyXCommand() << '\n';
728 if (!topmargin.empty())
730 << VSpace(topmargin).asLyXCommand() << '\n';
731 if (!rightmargin.empty())
732 os << "\\rightmargin "
733 << VSpace(rightmargin).asLyXCommand() << '\n';
734 if (!bottommargin.empty())
735 os << "\\bottommargin "
736 << VSpace(bottommargin).asLyXCommand() << '\n';
737 if (!headheight.empty())
738 os << "\\headheight "
739 << VSpace(headheight).asLyXCommand() << '\n';
740 if (!headsep.empty())
742 << VSpace(headsep).asLyXCommand() << '\n';
743 if (!footskip.empty())
745 << VSpace(footskip).asLyXCommand() << '\n';
746 os << "\\secnumdepth " << secnumdepth
747 << "\n\\tocdepth " << tocdepth
748 << "\n\\paragraph_separation "
749 << string_paragraph_separation[paragraph_separation]
750 << "\n\\defskip " << getDefSkip().asLyXCommand()
751 << "\n\\quotes_language "
752 << string_quotes_language[quotes_language]
753 << "\n\\papercolumns " << columns
754 << "\n\\papersides " << sides
755 << "\n\\paperpagestyle " << pagestyle << '\n';
756 if (!listings_params.empty())
757 os << "\\listings_params \"" <<
758 InsetListingsParams(listings_params).encodedString() << "\"\n";
759 for (int i = 0; i < 4; ++i) {
760 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
761 if (user_defined_bullet(i).getFont() != -1) {
762 os << "\\bullet " << i << " "
763 << user_defined_bullet(i).getFont() << " "
764 << user_defined_bullet(i).getCharacter() << " "
765 << user_defined_bullet(i).getSize() << "\n";
769 os << "\\bulletLaTeX " << i << " \""
770 << lyx::to_ascii(user_defined_bullet(i).getText())
776 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
777 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
779 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
780 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
781 for (; a_it != a_end; ++a_it) {
782 if (a_it->second.used())
783 os << "\\author " << a_it->second << "\n";
785 os << "\\author " << Author() << "\n";
790 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
791 TexRow & texrow) const
793 os << "\\documentclass";
795 TextClass const & tclass = getTextClass();
797 ostringstream clsoptions; // the document class options.
799 if (tokenPos(tclass.opt_fontsize(),
800 '|', fontsize) >= 0) {
801 // only write if existing in list (and not default)
802 clsoptions << fontsize << "pt,";
805 // custom, A3, B3 and B4 paper sizes need geometry
806 bool nonstandard_papersize = papersize == PAPER_B3
807 || papersize == PAPER_B4
808 || papersize == PAPER_A3
809 || papersize == PAPER_CUSTOM;
814 clsoptions << "a4paper,";
817 clsoptions << "letterpaper,";
820 clsoptions << "a5paper,";
823 clsoptions << "b5paper,";
825 case PAPER_USEXECUTIVE:
826 clsoptions << "executivepaper,";
829 clsoptions << "legalpaper,";
841 if (sides != tclass.sides()) {
843 case TextClass::OneSide:
844 clsoptions << "oneside,";
846 case TextClass::TwoSides:
847 clsoptions << "twoside,";
853 if (columns != tclass.columns()) {
855 clsoptions << "twocolumn,";
857 clsoptions << "onecolumn,";
861 && orientation == ORIENTATION_LANDSCAPE)
862 clsoptions << "landscape,";
864 // language should be a parameter to \documentclass
865 if (language->babel() == "hebrew"
866 && default_language->babel() != "hebrew")
867 // This seems necessary
868 features.useLanguage(default_language);
870 ostringstream language_options;
871 bool const use_babel = features.useBabel();
873 language_options << features.getLanguages();
874 if (!language->babel().empty()) {
875 if (!language_options.str().empty())
876 language_options << ',';
877 language_options << language->babel();
879 if (lyxrc.language_global_options && !language_options.str().empty())
880 clsoptions << language_options.str() << ',';
883 // the user-defined options
884 if (!options.empty()) {
885 clsoptions << options << ',';
888 string strOptions(clsoptions.str());
889 if (!strOptions.empty()) {
890 strOptions = rtrim(strOptions, ",");
892 os << '[' << from_utf8(strOptions) << ']';
895 os << '{' << from_ascii(tclass.latexname()) << "}\n";
897 // end of \documentclass defs
899 // font selection must be done before loading fontenc.sty
901 loadFonts(fontsRoman, fontsSans,
902 fontsTypewriter, fontsSC, fontsOSF,
903 fontsSansScale, fontsTypewriterScale);
904 if (!fonts.empty()) {
905 os << from_ascii(fonts);
908 if (fontsDefaultFamily != "default")
909 os << "\\renewcommand{\\familydefault}{\\"
910 << from_ascii(fontsDefaultFamily) << "}\n";
913 // this one is not per buffer
914 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
915 if (lyxrc.fontenc != "default") {
916 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
917 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
918 << ",LFE,LAE]{fontenc}\n";
921 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
927 // handle inputenc etc.
928 writeEncodingPreamble(os, features, texrow);
930 if (!listings_params.empty()) {
931 os << "\\usepackage{listings}\n";
934 // do not test validity because listings_params is supposed to be valid
935 string par = InsetListingsParams(listings_params).separatedParams(true);
936 os << from_ascii(par);
937 // count the number of newlines
938 for (size_t i = 0; i < par.size(); ++i)
944 if (use_geometry || nonstandard_papersize) {
945 os << "\\usepackage{geometry}\n";
947 os << "\\geometry{verbose";
948 if (orientation == ORIENTATION_LANDSCAPE)
952 if (!paperwidth.empty())
954 << from_ascii(paperwidth);
955 if (!paperheight.empty())
956 os << ",paperheight="
957 << from_ascii(paperheight);
960 os << ",letterpaper";
965 case PAPER_USEXECUTIVE:
966 os << ",executivepaper";
987 // default papersize ie PAPER_DEFAULT
988 switch (lyxrc.default_papersize) {
989 case PAPER_DEFAULT: // keep compiler happy
991 os << ",letterpaper";
996 case PAPER_USEXECUTIVE:
997 os << ",executivepaper";
1017 if (!topmargin.empty())
1018 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1019 if (!bottommargin.empty())
1020 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1021 if (!leftmargin.empty())
1022 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1023 if (!rightmargin.empty())
1024 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1025 if (!headheight.empty())
1026 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1027 if (!headsep.empty())
1028 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1029 if (!footskip.empty())
1030 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1035 if (tokenPos(tclass.opt_pagestyle(),
1036 '|', pagestyle) >= 0) {
1037 if (pagestyle == "fancy") {
1038 os << "\\usepackage{fancyhdr}\n";
1041 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1045 // Only if class has a ToC hierarchy
1046 if (tclass.hasTocLevels()) {
1047 if (secnumdepth != tclass.secnumdepth()) {
1048 os << "\\setcounter{secnumdepth}{"
1053 if (tocdepth != tclass.tocdepth()) {
1054 os << "\\setcounter{tocdepth}{"
1061 if (paragraph_separation) {
1062 switch (getDefSkip().kind()) {
1063 case VSpace::SMALLSKIP:
1064 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1066 case VSpace::MEDSKIP:
1067 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1069 case VSpace::BIGSKIP:
1070 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1072 case VSpace::LENGTH:
1073 os << "\\setlength{\\parskip}{"
1074 << from_utf8(getDefSkip().length().asLatexString())
1077 default: // should never happen // Then delete it.
1078 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1083 os << "\\setlength{\\parindent}{0pt}\n";
1087 // If we use jurabib, we have to call babel here.
1088 if (use_babel && features.isRequired("jurabib")) {
1089 os << from_ascii(babelCall(language_options.str()))
1091 << from_ascii(features.getBabelOptions());
1095 // Now insert the LyX specific LaTeX commands...
1097 // The optional packages;
1098 docstring lyxpreamble(from_ascii(features.getPackages()));
1100 // this might be useful...
1101 lyxpreamble += "\n\\makeatletter\n";
1103 // Some macros LyX will need
1104 docstring tmppreamble(from_ascii(features.getMacros()));
1106 if (!tmppreamble.empty()) {
1107 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1108 "LyX specific LaTeX commands.\n"
1109 + tmppreamble + '\n';
1112 // the text class specific preamble
1113 tmppreamble = features.getTClassPreamble();
1114 if (!tmppreamble.empty()) {
1115 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1116 "Textclass specific LaTeX commands.\n"
1117 + tmppreamble + '\n';
1120 /* the user-defined preamble */
1121 if (!preamble.empty()) {
1123 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1124 "User specified LaTeX commands.\n"
1125 + from_utf8(preamble) + '\n';
1128 // Itemize bullet settings need to be last in case the user
1129 // defines their own bullets that use a package included
1130 // in the user-defined preamble -- ARRae
1131 // Actually it has to be done much later than that
1132 // since some packages like frenchb make modifications
1133 // at \begin{document} time -- JMarc
1134 docstring bullets_def;
1135 for (int i = 0; i < 4; ++i) {
1136 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1137 if (bullets_def.empty())
1138 bullets_def += "\\AtBeginDocument{\n";
1139 bullets_def += " \\def\\labelitemi";
1141 // `i' is one less than the item to modify
1148 bullets_def += "ii";
1154 bullets_def += '{' +
1155 user_defined_bullet(i).getText()
1160 if (!bullets_def.empty())
1161 lyxpreamble += bullets_def + "}\n\n";
1163 // We try to load babel late, in case it interferes
1164 // with other packages.
1165 // Jurabib has to be called after babel, though.
1166 if (use_babel && !features.isRequired("jurabib")) {
1168 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1169 lyxpreamble += from_utf8(features.getBabelOptions());
1172 lyxpreamble += "\\makeatother\n\n";
1175 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1176 for (int j = 0; j != nlines; ++j) {
1185 void BufferParams::useClassDefaults()
1187 TextClass const & tclass = textclasslist[baseClass_];
1189 sides = tclass.sides();
1190 columns = tclass.columns();
1191 pagestyle = tclass.pagestyle();
1192 options = tclass.options();
1193 // Only if class has a ToC hierarchy
1194 if (tclass.hasTocLevels()) {
1195 secnumdepth = tclass.secnumdepth();
1196 tocdepth = tclass.tocdepth();
1201 bool BufferParams::hasClassDefaults() const
1203 TextClass const & tclass = textclasslist[baseClass_];
1205 return (sides == tclass.sides()
1206 && columns == tclass.columns()
1207 && pagestyle == tclass.pagestyle()
1208 && options == tclass.options()
1209 && secnumdepth == tclass.secnumdepth()
1210 && tocdepth == tclass.tocdepth());
1214 TextClass const & BufferParams::getTextClass() const
1220 TextClass_ptr BufferParams::getTextClass_ptr() const {
1225 void BufferParams::setTextClass(TextClass_ptr tc) {
1230 void BufferParams::setBaseClass(textclass_type tc)
1237 void BufferParams::setJustBaseClass(textclass_type tc)
1243 textclass_type BufferParams::getBaseClass() const
1249 void BufferParams::makeTextClass()
1251 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1252 //FIXME It might be worth loading the children's modules here,
1253 //instead of just doing a check in InsetInclude.
1254 LayoutModuleList::const_iterator it = layoutModules_.begin();
1255 for (; it != layoutModules_.end(); it++) {
1256 string const modName = *it;
1257 LyXModule * lm = moduleList[modName];
1259 docstring const msg =
1260 bformat(_("The module %1$s has been requested by\n"
1261 "this document but has not been found in the list of\n"
1262 "available modules. If you recently installed it, you\n"
1263 "probalby need to reconfigure LyX.\n"), from_utf8(modName));
1264 frontend::Alert::warning(_("Module not available"),
1265 msg + _("Some layouts may not be available."));
1266 lyxerr << "BufferParams::makeTextClass(): Module " <<
1267 modName << " requested but not found in module list." <<
1271 FileName layout_file = libFileSearch("layouts", lm->filename);
1272 textClass_->read(layout_file, TextClass::MODULE);
1277 std::vector<string> const & BufferParams::getModules() const {
1278 return layoutModules_;
1283 bool BufferParams::addLayoutModule(string modName, bool makeClass) {
1284 LayoutModuleList::const_iterator it = layoutModules_.begin();
1285 LayoutModuleList::const_iterator end = layoutModules_.end();
1286 for (; it != end; it++) {
1290 if (it != layoutModules_.end())
1292 layoutModules_.push_back(modName);
1299 bool BufferParams::addLayoutModules(std::vector<string>modNames)
1302 std::vector<string>::const_iterator it = modNames.begin();
1303 std::vector<string>::const_iterator end = modNames.end();
1304 for (; it != end; ++it)
1305 retval &= addLayoutModule(*it, false);
1311 void BufferParams::clearLayoutModules() {
1312 layoutModules_.clear();
1317 Font const BufferParams::getFont() const
1319 Font f = getTextClass().defaultfont();
1320 f.setLanguage(language);
1321 if (fontsDefaultFamily == "rmdefault")
1322 f.setFamily(Font::ROMAN_FAMILY);
1323 else if (fontsDefaultFamily == "sfdefault")
1324 f.setFamily(Font::SANS_FAMILY);
1325 else if (fontsDefaultFamily == "ttdefault")
1326 f.setFamily(Font::TYPEWRITER_FAMILY);
1331 void BufferParams::readPreamble(Lexer & lex)
1333 if (lex.getString() != "\\begin_preamble")
1334 lyxerr << "Error (BufferParams::readPreamble):"
1335 "consistency check failed." << endl;
1337 preamble = lex.getLongString("\\end_preamble");
1341 void BufferParams::readLanguage(Lexer & lex)
1343 if (!lex.next()) return;
1345 string const tmptok = lex.getString();
1347 // check if tmptok is part of tex_babel in tex-defs.h
1348 language = languages.getLanguage(tmptok);
1350 // Language tmptok was not found
1351 language = default_language;
1352 lyxerr << "Warning: Setting language `"
1353 << tmptok << "' to `" << language->lang()
1359 void BufferParams::readGraphicsDriver(Lexer & lex)
1361 if (!lex.next()) return;
1363 string const tmptok = lex.getString();
1364 // check if tmptok is part of tex_graphics in tex_defs.h
1367 string const test = tex_graphics[n++];
1369 if (test == tmptok) {
1370 graphicsDriver = tmptok;
1372 } else if (test == "") {
1374 "Warning: graphics driver `$$Token' not recognized!\n"
1375 " Setting graphics driver to `default'.\n");
1376 graphicsDriver = "default";
1383 void BufferParams::readBullets(Lexer & lex)
1385 if (!lex.next()) return;
1387 int const index = lex.getInteger();
1389 int temp_int = lex.getInteger();
1390 user_defined_bullet(index).setFont(temp_int);
1391 temp_bullet(index).setFont(temp_int);
1393 user_defined_bullet(index).setCharacter(temp_int);
1394 temp_bullet(index).setCharacter(temp_int);
1396 user_defined_bullet(index).setSize(temp_int);
1397 temp_bullet(index).setSize(temp_int);
1401 void BufferParams::readBulletsLaTeX(Lexer & lex)
1403 // The bullet class should be able to read this.
1404 if (!lex.next()) return;
1405 int const index = lex.getInteger();
1407 docstring const temp_str = lex.getDocString();
1409 user_defined_bullet(index).setText(temp_str);
1410 temp_bullet(index).setText(temp_str);
1414 void BufferParams::readModules(Lexer & lex)
1416 if (!lex.eatLine()) {
1417 lyxerr << "Error (BufferParams::readModules):"
1418 "Unexpected end of input." << endl;
1422 string mod = lex.getString();
1423 if (mod == "\\end_modules")
1425 addLayoutModule(mod);
1431 string const BufferParams::paperSizeName() const
1433 char real_papersize = papersize;
1434 if (real_papersize == PAPER_DEFAULT)
1435 real_papersize = lyxrc.default_papersize;
1437 switch (real_papersize) {
1446 case PAPER_USEXECUTIVE:
1450 case PAPER_USLETTER:
1457 string const BufferParams::dvips_options() const
1462 && papersize == PAPER_CUSTOM
1463 && !lyxrc.print_paper_dimension_flag.empty()
1464 && !paperwidth.empty()
1465 && !paperheight.empty()) {
1466 // using a custom papersize
1467 result = lyxrc.print_paper_dimension_flag;
1468 result += ' ' + paperwidth;
1469 result += ',' + paperheight;
1471 string const paper_option = paperSizeName();
1472 if (paper_option != "letter" ||
1473 orientation != ORIENTATION_LANDSCAPE) {
1474 // dvips won't accept -t letter -t landscape.
1475 // In all other cases, include the paper size
1477 result = lyxrc.print_paper_flag;
1478 result += ' ' + paper_option;
1481 if (orientation == ORIENTATION_LANDSCAPE &&
1482 papersize != PAPER_CUSTOM)
1483 result += ' ' + lyxrc.print_landscape_flag;
1488 string const BufferParams::babelCall(string const & lang_opts) const
1490 string lang_pack = lyxrc.language_package;
1491 if (lang_pack != "\\usepackage{babel}")
1493 // suppress the babel call when there is no babel language defined
1494 // for the document language in the lib/languages file and if no
1495 // other languages are used (lang_opts is then empty)
1496 if (lang_opts.empty())
1498 if (!lyxrc.language_global_options)
1499 return "\\usepackage[" + lang_opts + "]{babel}";
1504 void BufferParams::writeEncodingPreamble(odocstream & os,
1505 LaTeXFeatures & features, TexRow & texrow) const
1507 if (inputenc == "auto") {
1508 string const doc_encoding =
1509 language->encoding()->latexName();
1510 Encoding::Package const package =
1511 language->encoding()->package();
1513 // Create a list with all the input encodings used
1515 std::set<string> encodings =
1516 features.getEncodingSet(doc_encoding);
1518 if (!encodings.empty() || package == Encoding::inputenc) {
1519 os << "\\usepackage[";
1520 std::set<string>::const_iterator it = encodings.begin();
1521 std::set<string>::const_iterator const end = encodings.end();
1523 os << from_ascii(*it);
1526 for (; it != end; ++it)
1527 os << ',' << from_ascii(*it);
1528 if (package == Encoding::inputenc) {
1529 if (!encodings.empty())
1531 os << from_ascii(doc_encoding);
1533 os << "]{inputenc}\n";
1536 if (package == Encoding::CJK) {
1537 os << "\\usepackage{CJK}\n";
1540 } else if (inputenc != "default") {
1541 switch (encoding().package()) {
1542 case Encoding::none:
1544 case Encoding::inputenc:
1545 os << "\\usepackage[" << from_ascii(inputenc)
1550 os << "\\usepackage{CJK}\n";
1556 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1557 // armscii8 is used for Armenian.
1558 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1559 os << "\\usepackage{armtex}\n";
1565 string const BufferParams::loadFonts(string const & rm,
1566 string const & sf, string const & tt,
1567 bool const & sc, bool const & osf,
1568 int const & sfscale, int const & ttscale) const
1570 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1571 several packages have been replaced by others, that might not
1572 be installed on every system. We have to take care for that
1573 (see psnfss.pdf). We try to support all psnfss fonts as well
1574 as the fonts that have become de facto standard in the LaTeX
1575 world (e.g. Latin Modern). We do not support obsolete fonts
1576 (like PSLatex). In general, it should be possible to mix any
1577 rm font with any sf or tt font, respectively. (JSpitzm)
1579 -- separate math fonts.
1582 if (rm == "default" && sf == "default" && tt == "default")
1589 // Computer Modern (must be explicitely selectable -- there might be classes
1590 // that define a different default font!
1592 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1593 // osf for Computer Modern needs eco.sty
1595 os << "\\usepackage{eco}\n";
1597 // Latin Modern Roman
1598 else if (rm == "lmodern")
1599 os << "\\usepackage{lmodern}\n";
1601 else if (rm == "ae") {
1602 // not needed when using OT1 font encoding.
1603 if (lyxrc.fontenc != "default")
1604 os << "\\usepackage{ae,aecompl}\n";
1607 else if (rm == "times") {
1608 // try to load the best available package
1609 if (LaTeXFeatures::isAvailable("mathptmx"))
1610 os << "\\usepackage{mathptmx}\n";
1611 else if (LaTeXFeatures::isAvailable("mathptm"))
1612 os << "\\usepackage{mathptm}\n";
1614 os << "\\usepackage{times}\n";
1617 else if (rm == "palatino") {
1618 // try to load the best available package
1619 if (LaTeXFeatures::isAvailable("mathpazo")) {
1620 os << "\\usepackage";
1626 // "osf" includes "sc"!
1630 os << "{mathpazo}\n";
1632 else if (LaTeXFeatures::isAvailable("mathpple"))
1633 os << "\\usepackage{mathpple}\n";
1635 os << "\\usepackage{palatino}\n";
1638 else if (rm == "utopia") {
1639 // fourier supersedes utopia.sty, but does
1640 // not work with OT1 encoding.
1641 if (LaTeXFeatures::isAvailable("fourier")
1642 && lyxrc.fontenc != "default") {
1643 os << "\\usepackage";
1654 os << "{fourier}\n";
1657 os << "\\usepackage{utopia}\n";
1659 // Bera (complete fontset)
1660 else if (rm == "bera" && sf == "default" && tt == "default")
1661 os << "\\usepackage{bera}\n";
1663 else if (rm != "default")
1664 os << "\\usepackage" << "{" << rm << "}\n";
1667 // Helvetica, Bera Sans
1668 if (sf == "helvet" || sf == "berasans") {
1670 os << "\\usepackage[scaled=" << float(sfscale) / 100
1671 << "]{" << sf << "}\n";
1673 os << "\\usepackage{" << sf << "}\n";
1676 else if (sf == "avant")
1677 os << "\\usepackage{" << sf << "}\n";
1678 // Computer Modern, Latin Modern, CM Bright
1679 else if (sf != "default")
1680 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1682 // monospaced/typewriter
1683 // Courier, LuxiMono
1684 if (tt == "luximono" || tt == "beramono") {
1686 os << "\\usepackage[scaled=" << float(ttscale) / 100
1687 << "]{" << tt << "}\n";
1689 os << "\\usepackage{" << tt << "}\n";
1692 else if (tt == "courier" )
1693 os << "\\usepackage{" << tt << "}\n";
1694 // Computer Modern, Latin Modern, CM Bright
1695 else if (tt != "default")
1696 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1702 Encoding const & BufferParams::encoding() const
1704 if (inputenc == "auto" || inputenc == "default")
1705 return *(language->encoding());
1706 Encoding const * const enc =
1707 encodings.getFromLaTeXName(inputenc);
1710 lyxerr << "Unknown inputenc value `" << inputenc
1711 << "'. Using `auto' instead." << endl;
1712 return *(language->encoding());
1716 biblio::CiteEngine BufferParams::getEngine() const
1718 // FIXME the class should provide the numerical/
1719 // authoryear choice
1720 if (getTextClass().provides("natbib")
1721 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1722 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1723 return cite_engine_;
1727 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1729 cite_engine_ = cite_engine;