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"
27 #include "LaTeXFeatures.h"
33 #include "TextClassList.h"
34 #include "OutputParams.h"
39 #include "frontends/alert.h"
40 #include "insets/InsetListingsParams.h"
42 #include "support/lyxalgo.h" // for lyx::count
43 #include "support/convert.h"
44 #include "support/Translator.h"
46 #include <boost/array.hpp>
52 using std::istringstream;
54 using std::ostringstream;
57 using lyx::support::bformat;
58 using lyx::support::rtrim;
59 using lyx::support::tokenPos;
62 static char const * const string_paragraph_separation[] = {
67 static char const * const string_quotes_language[] = {
68 "english", "swedish", "german", "polish", "french", "danish", ""
72 static char const * const string_papersize[] = {
73 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
74 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
78 static char const * const string_orientation[] = {
79 "portrait", "landscape", ""
83 static char const * const string_footnotekinds[] = {
84 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
88 static char const * const tex_graphics[] = {
89 "default", "dvips", "dvitops", "emtex",
90 "ln", "oztex", "textures", "none", ""
99 // Paragraph separation
100 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
103 ParSepTranslator const init_parseptranslator()
105 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
106 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
111 ParSepTranslator const & parseptranslator()
113 static ParSepTranslator translator = init_parseptranslator();
119 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
122 QuotesLangTranslator const init_quoteslangtranslator()
124 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
125 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
126 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
127 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
128 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
129 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
134 QuotesLangTranslator const & quoteslangtranslator()
136 static QuotesLangTranslator translator = init_quoteslangtranslator();
142 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
145 PaperSizeTranslator const init_papersizetranslator()
147 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
148 translator.addPair(string_papersize[1], PAPER_CUSTOM);
149 translator.addPair(string_papersize[2], PAPER_USLETTER);
150 translator.addPair(string_papersize[3], PAPER_USLEGAL);
151 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
152 translator.addPair(string_papersize[5], PAPER_A3);
153 translator.addPair(string_papersize[6], PAPER_A4);
154 translator.addPair(string_papersize[7], PAPER_A5);
155 translator.addPair(string_papersize[8], PAPER_B3);
156 translator.addPair(string_papersize[9], PAPER_B4);
157 translator.addPair(string_papersize[10], PAPER_B5);
162 PaperSizeTranslator const & papersizetranslator()
164 static PaperSizeTranslator translator = init_papersizetranslator();
170 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
173 PaperOrientationTranslator const init_paperorientationtranslator()
175 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
176 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
181 PaperOrientationTranslator const & paperorientationtranslator()
183 static PaperOrientationTranslator translator = init_paperorientationtranslator();
189 typedef Translator<int, TextClass::PageSides> SidesTranslator;
192 SidesTranslator const init_sidestranslator()
194 SidesTranslator translator(1, TextClass::OneSide);
195 translator.addPair(2, TextClass::TwoSides);
200 SidesTranslator const & sidestranslator()
202 static SidesTranslator translator = init_sidestranslator();
208 typedef Translator<int, BufferParams::Package> PackageTranslator;
211 PackageTranslator const init_packagetranslator()
213 PackageTranslator translator(0, BufferParams::package_off);
214 translator.addPair(1, BufferParams::package_auto);
215 translator.addPair(2, BufferParams::package_on);
220 PackageTranslator const & packagetranslator()
222 static PackageTranslator translator = init_packagetranslator();
228 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
231 CiteEngineTranslator const init_citeenginetranslator()
233 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
234 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
235 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
236 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
241 CiteEngineTranslator const & citeenginetranslator()
243 static CiteEngineTranslator translator = init_citeenginetranslator();
249 typedef Translator<string, Spacing::Space> SpaceTranslator;
252 SpaceTranslator const init_spacetranslator()
254 SpaceTranslator translator("default", Spacing::Default);
255 translator.addPair("single", Spacing::Single);
256 translator.addPair("onehalf", Spacing::Onehalf);
257 translator.addPair("double", Spacing::Double);
258 translator.addPair("other", Spacing::Other);
263 SpaceTranslator const & spacetranslator()
265 static SpaceTranslator translator = init_spacetranslator();
270 textclass_type defaultTextclass()
272 // Initialize textclass to point to article. if `first' is
273 // true in the returned pair, then `second' is the textclass
274 // number; if it is false, second is 0. In both cases, second
276 return textclasslist.numberOfClass("article").second;
282 class BufferParams::Impl
287 AuthorList authorlist;
288 BranchList branchlist;
289 boost::array<Bullet, 4> temp_bullets;
290 boost::array<Bullet, 4> user_defined_bullets;
292 /** This is the amount of space used for paragraph_separation "skip",
293 * and for detached paragraphs in "indented" documents.
299 BufferParams::Impl::Impl()
300 : defskip(VSpace::MEDSKIP)
302 // set initial author
304 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
309 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
313 return new BufferParams::Impl(*ptr);
317 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
323 BufferParams::BufferParams()
324 : textclass(defaultTextclass()), pimpl_(new Impl)
326 paragraph_separation = PARSEP_INDENT;
327 quotes_language = InsetQuotes::EnglishQ;
328 fontsize = "default";
331 papersize = PAPER_DEFAULT;
332 orientation = ORIENTATION_PORTRAIT;
333 use_geometry = false;
334 use_amsmath = package_auto;
335 use_esint = package_auto;
336 cite_engine_ = biblio::ENGINE_BASIC;
337 use_bibtopic = false;
338 trackChanges = false;
339 outputChanges = false;
342 language = default_language;
343 fontsRoman = "default";
344 fontsSans = "default";
345 fontsTypewriter = "default";
346 fontsDefaultFamily = "default";
349 fontsSansScale = 100;
350 fontsTypewriterScale = 100;
352 graphicsDriver = "default";
353 sides = TextClass::OneSide;
355 listings_params = string();
356 pagestyle = "default";
358 for (int iter = 0; iter < 4; ++iter) {
359 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
360 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
365 BufferParams::~BufferParams()
369 docstring const BufferParams::B_(string const & l10n) const
371 BOOST_ASSERT(language);
372 return getMessages(language->code()).get(l10n);
376 AuthorList & BufferParams::authors()
378 return pimpl_->authorlist;
382 AuthorList const & BufferParams::authors() const
384 return pimpl_->authorlist;
388 BranchList & BufferParams::branchlist()
390 return pimpl_->branchlist;
394 BranchList const & BufferParams::branchlist() const
396 return pimpl_->branchlist;
400 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
402 BOOST_ASSERT(index < 4);
403 return pimpl_->temp_bullets[index];
407 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
409 BOOST_ASSERT(index < 4);
410 return pimpl_->temp_bullets[index];
414 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
416 BOOST_ASSERT(index < 4);
417 return pimpl_->user_defined_bullets[index];
421 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
423 BOOST_ASSERT(index < 4);
424 return pimpl_->user_defined_bullets[index];
428 Spacing & BufferParams::spacing()
430 return pimpl_->spacing;
434 Spacing const & BufferParams::spacing() const
436 return pimpl_->spacing;
440 VSpace const & BufferParams::getDefSkip() const
442 return pimpl_->defskip;
446 void BufferParams::setDefSkip(VSpace const & vs)
448 pimpl_->defskip = vs;
452 string const BufferParams::readToken(Lexer & lex, string const & token)
454 if (token == "\\textclass") {
456 string const classname = lex.getString();
457 pair<bool, lyx::textclass_type> pp =
458 textclasslist.numberOfClass(classname);
460 textclass = pp.second;
462 // if text class does not exist, try to load it from filepath
463 pp = textclasslist.addTextClass(classname, filepath);
465 textclass = pp.second;
467 textclass = defaultTextclass();
471 // FIXME: isTeXClassAvailable will try to load the layout file, but will
472 // fail because of the lack of path info. Warnings will be given although
473 // the layout file will be correctly loaded later.
474 if (!getTextClass().isTeXClassAvailable()) {
475 docstring const msg =
476 bformat(_("The layout file requested by this document,\n"
478 "is not usable. This is probably because a LaTeX\n"
479 "class or style file required by it is not\n"
480 "available. See the Customization documentation\n"
481 "for more information.\n"), from_utf8(classname));
482 frontend::Alert::warning(_("Document class not available"),
483 msg + _("LyX will not be able to produce output."));
485 } else if (token == "\\begin_preamble") {
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;
644 void BufferParams::writeFile(ostream & os) const
646 // The top of the file is written by the buffer.
647 // Prints out the buffer info into the .lyx file given by file
650 os << "\\textclass " << textclasslist[textclass].name() << '\n';
653 if (!preamble.empty()) {
654 // remove '\n' from the end of preamble
655 string const tmppreamble = rtrim(preamble, "\n");
656 os << "\\begin_preamble\n"
658 << "\n\\end_preamble\n";
662 if (!options.empty()) {
663 os << "\\options " << options << '\n';
666 // then the text parameters
667 if (language != ignore_language)
668 os << "\\language " << language->lang() << '\n';
669 os << "\\inputencoding " << inputenc
670 << "\n\\font_roman " << fontsRoman
671 << "\n\\font_sans " << fontsSans
672 << "\n\\font_typewriter " << fontsTypewriter
673 << "\n\\font_default_family " << fontsDefaultFamily
674 << "\n\\font_sc " << convert<string>(fontsSC)
675 << "\n\\font_osf " << convert<string>(fontsOSF)
676 << "\n\\font_sf_scale " << fontsSansScale
677 << "\n\\font_tt_scale " << fontsTypewriterScale
678 << "\n\\graphics " << graphicsDriver << '\n';
680 if (!float_placement.empty()) {
681 os << "\\float_placement " << float_placement << '\n';
683 os << "\\paperfontsize " << fontsize << '\n';
685 spacing().writeFile(os);
687 os << "\\papersize " << string_papersize[papersize]
688 << "\n\\use_geometry " << convert<string>(use_geometry)
689 << "\n\\use_amsmath " << use_amsmath
690 << "\n\\use_esint " << use_esint
691 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
692 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
693 << "\n\\paperorientation " << string_orientation[orientation]
696 BranchList::const_iterator it = branchlist().begin();
697 BranchList::const_iterator end = branchlist().end();
698 for (; it != end; ++it) {
699 os << "\\branch " << to_utf8(it->getBranch())
700 << "\n\\selected " << it->getSelected()
701 << "\n\\color " << lyx::X11hexname(it->getColor())
706 if (!paperwidth.empty())
707 os << "\\paperwidth "
708 << VSpace(paperwidth).asLyXCommand() << '\n';
709 if (!paperheight.empty())
710 os << "\\paperheight "
711 << VSpace(paperheight).asLyXCommand() << '\n';
712 if (!leftmargin.empty())
713 os << "\\leftmargin "
714 << VSpace(leftmargin).asLyXCommand() << '\n';
715 if (!topmargin.empty())
717 << VSpace(topmargin).asLyXCommand() << '\n';
718 if (!rightmargin.empty())
719 os << "\\rightmargin "
720 << VSpace(rightmargin).asLyXCommand() << '\n';
721 if (!bottommargin.empty())
722 os << "\\bottommargin "
723 << VSpace(bottommargin).asLyXCommand() << '\n';
724 if (!headheight.empty())
725 os << "\\headheight "
726 << VSpace(headheight).asLyXCommand() << '\n';
727 if (!headsep.empty())
729 << VSpace(headsep).asLyXCommand() << '\n';
730 if (!footskip.empty())
732 << VSpace(footskip).asLyXCommand() << '\n';
733 os << "\\secnumdepth " << secnumdepth
734 << "\n\\tocdepth " << tocdepth
735 << "\n\\paragraph_separation "
736 << string_paragraph_separation[paragraph_separation]
737 << "\n\\defskip " << getDefSkip().asLyXCommand()
738 << "\n\\quotes_language "
739 << string_quotes_language[quotes_language]
740 << "\n\\papercolumns " << columns
741 << "\n\\papersides " << sides
742 << "\n\\paperpagestyle " << pagestyle << '\n';
743 if (!listings_params.empty())
744 os << "\\listings_params \"" <<
745 InsetListingsParams(listings_params).encodedString() << "\"\n";
746 for (int i = 0; i < 4; ++i) {
747 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
748 if (user_defined_bullet(i).getFont() != -1) {
749 os << "\\bullet " << i << " "
750 << user_defined_bullet(i).getFont() << " "
751 << user_defined_bullet(i).getCharacter() << " "
752 << user_defined_bullet(i).getSize() << "\n";
756 os << "\\bulletLaTeX " << i << " \""
757 << lyx::to_ascii(user_defined_bullet(i).getText())
763 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
764 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
766 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
767 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
768 for (; a_it != a_end; ++a_it) {
769 os << "\\author " << a_it->second << "\n";
774 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
775 TexRow & texrow) const
777 os << "\\documentclass";
779 TextClass const & tclass = getTextClass();
781 ostringstream clsoptions; // the document class options.
783 if (tokenPos(tclass.opt_fontsize(),
784 '|', fontsize) >= 0) {
785 // only write if existing in list (and not default)
786 clsoptions << fontsize << "pt,";
789 // custom, A3, B3 and B4 paper sizes need geometry
790 bool nonstandard_papersize = papersize == PAPER_B3
791 || papersize == PAPER_B4
792 || papersize == PAPER_A3
793 || papersize == PAPER_CUSTOM;
798 clsoptions << "a4paper,";
801 clsoptions << "letterpaper,";
804 clsoptions << "a5paper,";
807 clsoptions << "b5paper,";
809 case PAPER_USEXECUTIVE:
810 clsoptions << "executivepaper,";
813 clsoptions << "legalpaper,";
825 if (sides != tclass.sides()) {
827 case TextClass::OneSide:
828 clsoptions << "oneside,";
830 case TextClass::TwoSides:
831 clsoptions << "twoside,";
837 if (columns != tclass.columns()) {
839 clsoptions << "twocolumn,";
841 clsoptions << "onecolumn,";
845 && orientation == ORIENTATION_LANDSCAPE)
846 clsoptions << "landscape,";
848 // language should be a parameter to \documentclass
849 if (language->babel() == "hebrew"
850 && default_language->babel() != "hebrew")
851 // This seems necessary
852 features.useLanguage(default_language);
854 ostringstream language_options;
855 bool const use_babel = features.useBabel();
857 language_options << features.getLanguages();
858 if (!language->babel().empty()) {
859 if (!language_options.str().empty())
860 language_options << ',';
861 language_options << language->babel();
863 if (lyxrc.language_global_options && !language_options.str().empty())
864 clsoptions << language_options.str() << ',';
867 // the user-defined options
868 if (!options.empty()) {
869 clsoptions << options << ',';
872 string strOptions(clsoptions.str());
873 if (!strOptions.empty()) {
874 strOptions = rtrim(strOptions, ",");
876 os << '[' << from_utf8(strOptions) << ']';
879 os << '{' << from_ascii(tclass.latexname()) << "}\n";
881 // end of \documentclass defs
883 // font selection must be done before loading fontenc.sty
885 loadFonts(fontsRoman, fontsSans,
886 fontsTypewriter, fontsSC, fontsOSF,
887 fontsSansScale, fontsTypewriterScale);
888 if (!fonts.empty()) {
889 os << from_ascii(fonts);
892 if (fontsDefaultFamily != "default")
893 os << "\\renewcommand{\\familydefault}{\\"
894 << from_ascii(fontsDefaultFamily) << "}\n";
895 // this one is not per buffer
896 if (lyxrc.fontenc != "default") {
897 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
902 // handle inputenc etc.
903 writeEncodingPreamble(os, features, texrow);
905 if (!listings_params.empty()) {
906 os << "\\usepackage{listings}\n";
909 // do not test validity because listings_params is supposed to be valid
910 string par = InsetListingsParams(listings_params).separatedParams(true);
911 os << from_ascii(par);
912 // count the number of newlines
913 for (size_t i = 0; i < par.size(); ++i)
919 if (use_geometry || nonstandard_papersize) {
920 os << "\\usepackage{geometry}\n";
922 os << "\\geometry{verbose";
923 if (orientation == ORIENTATION_LANDSCAPE)
927 if (!paperwidth.empty())
929 << from_ascii(paperwidth);
930 if (!paperheight.empty())
931 os << ",paperheight="
932 << from_ascii(paperheight);
935 os << ",letterpaper";
940 case PAPER_USEXECUTIVE:
941 os << ",executivepaper";
962 // default papersize ie PAPER_DEFAULT
963 switch (lyxrc.default_papersize) {
964 case PAPER_DEFAULT: // keep compiler happy
966 os << ",letterpaper";
971 case PAPER_USEXECUTIVE:
972 os << ",executivepaper";
992 if (!topmargin.empty())
993 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
994 if (!bottommargin.empty())
995 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
996 if (!leftmargin.empty())
997 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
998 if (!rightmargin.empty())
999 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1000 if (!headheight.empty())
1001 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1002 if (!headsep.empty())
1003 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1004 if (!footskip.empty())
1005 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1010 if (tokenPos(tclass.opt_pagestyle(),
1011 '|', pagestyle) >= 0) {
1012 if (pagestyle == "fancy") {
1013 os << "\\usepackage{fancyhdr}\n";
1016 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1020 // Only if class has a ToC hierarchy
1021 if (tclass.hasTocLevels()) {
1022 if (secnumdepth != tclass.secnumdepth()) {
1023 os << "\\setcounter{secnumdepth}{"
1028 if (tocdepth != tclass.tocdepth()) {
1029 os << "\\setcounter{tocdepth}{"
1036 if (paragraph_separation) {
1037 switch (getDefSkip().kind()) {
1038 case VSpace::SMALLSKIP:
1039 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1041 case VSpace::MEDSKIP:
1042 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1044 case VSpace::BIGSKIP:
1045 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1047 case VSpace::LENGTH:
1048 os << "\\setlength{\\parskip}{"
1049 << from_utf8(getDefSkip().length().asLatexString())
1052 default: // should never happen // Then delete it.
1053 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1058 os << "\\setlength{\\parindent}{0pt}\n";
1062 // If we use jurabib, we have to call babel here.
1063 if (use_babel && features.isRequired("jurabib")) {
1064 os << from_ascii(babelCall(language_options.str()))
1066 << from_ascii(features.getBabelOptions());
1070 // Now insert the LyX specific LaTeX commands...
1072 // The optional packages;
1073 docstring lyxpreamble(from_ascii(features.getPackages()));
1075 // this might be useful...
1076 lyxpreamble += "\n\\makeatletter\n";
1078 // Some macros LyX will need
1079 docstring tmppreamble(from_ascii(features.getMacros()));
1081 if (!tmppreamble.empty()) {
1082 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1083 "LyX specific LaTeX commands.\n"
1084 + tmppreamble + '\n';
1087 // the text class specific preamble
1088 tmppreamble = features.getTClassPreamble();
1089 if (!tmppreamble.empty()) {
1090 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1091 "Textclass specific LaTeX commands.\n"
1092 + tmppreamble + '\n';
1095 /* the user-defined preamble */
1096 if (!preamble.empty()) {
1098 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1099 "User specified LaTeX commands.\n"
1100 + from_utf8(preamble) + '\n';
1103 // Itemize bullet settings need to be last in case the user
1104 // defines their own bullets that use a package included
1105 // in the user-defined preamble -- ARRae
1106 // Actually it has to be done much later than that
1107 // since some packages like frenchb make modifications
1108 // at \begin{document} time -- JMarc
1109 docstring bullets_def;
1110 for (int i = 0; i < 4; ++i) {
1111 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1112 if (bullets_def.empty())
1113 bullets_def += "\\AtBeginDocument{\n";
1114 bullets_def += " \\def\\labelitemi";
1116 // `i' is one less than the item to modify
1123 bullets_def += "ii";
1129 bullets_def += '{' +
1130 user_defined_bullet(i).getText()
1135 if (!bullets_def.empty())
1136 lyxpreamble += bullets_def + "}\n\n";
1138 // We try to load babel late, in case it interferes
1139 // with other packages.
1140 // Jurabib has to be called after babel, though.
1141 if (use_babel && !features.isRequired("jurabib")) {
1143 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1144 lyxpreamble += from_utf8(features.getBabelOptions());
1147 lyxpreamble += "\\makeatother\n";
1150 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1151 for (int j = 0; j != nlines; ++j) {
1160 void BufferParams::useClassDefaults()
1162 TextClass const & tclass = textclasslist[textclass];
1164 sides = tclass.sides();
1165 columns = tclass.columns();
1166 pagestyle = tclass.pagestyle();
1167 options = tclass.options();
1168 // Only if class has a ToC hierarchy
1169 if (tclass.hasTocLevels()) {
1170 secnumdepth = tclass.secnumdepth();
1171 tocdepth = tclass.tocdepth();
1176 bool BufferParams::hasClassDefaults() const
1178 TextClass const & tclass = textclasslist[textclass];
1180 return (sides == tclass.sides()
1181 && columns == tclass.columns()
1182 && pagestyle == tclass.pagestyle()
1183 && options == tclass.options()
1184 && secnumdepth == tclass.secnumdepth()
1185 && tocdepth == tclass.tocdepth());
1189 TextClass const & BufferParams::getTextClass() const
1191 return textclasslist[textclass];
1195 Font const BufferParams::getFont() const
1197 Font f = getTextClass().defaultfont();
1198 f.setLanguage(language);
1199 if (fontsDefaultFamily == "rmdefault")
1200 f.setFamily(Font::ROMAN_FAMILY);
1201 else if (fontsDefaultFamily == "sfdefault")
1202 f.setFamily(Font::SANS_FAMILY);
1203 else if (fontsDefaultFamily == "ttdefault")
1204 f.setFamily(Font::TYPEWRITER_FAMILY);
1209 void BufferParams::readPreamble(Lexer & lex)
1211 if (lex.getString() != "\\begin_preamble")
1212 lyxerr << "Error (BufferParams::readPreamble):"
1213 "consistency check failed." << endl;
1215 preamble = lex.getLongString("\\end_preamble");
1219 void BufferParams::readLanguage(Lexer & lex)
1221 if (!lex.next()) return;
1223 string const tmptok = lex.getString();
1225 // check if tmptok is part of tex_babel in tex-defs.h
1226 language = languages.getLanguage(tmptok);
1228 // Language tmptok was not found
1229 language = default_language;
1230 lyxerr << "Warning: Setting language `"
1231 << tmptok << "' to `" << language->lang()
1237 void BufferParams::readGraphicsDriver(Lexer & lex)
1239 if (!lex.next()) return;
1241 string const tmptok = lex.getString();
1242 // check if tmptok is part of tex_graphics in tex_defs.h
1245 string const test = tex_graphics[n++];
1247 if (test == tmptok) {
1248 graphicsDriver = tmptok;
1250 } else if (test == "") {
1252 "Warning: graphics driver `$$Token' not recognized!\n"
1253 " Setting graphics driver to `default'.\n");
1254 graphicsDriver = "default";
1261 void BufferParams::readBullets(Lexer & lex)
1263 if (!lex.next()) return;
1265 int const index = lex.getInteger();
1267 int temp_int = lex.getInteger();
1268 user_defined_bullet(index).setFont(temp_int);
1269 temp_bullet(index).setFont(temp_int);
1271 user_defined_bullet(index).setCharacter(temp_int);
1272 temp_bullet(index).setCharacter(temp_int);
1274 user_defined_bullet(index).setSize(temp_int);
1275 temp_bullet(index).setSize(temp_int);
1279 void BufferParams::readBulletsLaTeX(Lexer & lex)
1281 // The bullet class should be able to read this.
1282 if (!lex.next()) return;
1283 int const index = lex.getInteger();
1285 docstring const temp_str = lex.getDocString();
1287 user_defined_bullet(index).setText(temp_str);
1288 temp_bullet(index).setText(temp_str);
1292 string const BufferParams::paperSizeName() const
1294 char real_papersize = papersize;
1295 if (real_papersize == PAPER_DEFAULT)
1296 real_papersize = lyxrc.default_papersize;
1298 switch (real_papersize) {
1307 case PAPER_USEXECUTIVE:
1311 case PAPER_USLETTER:
1318 string const BufferParams::dvips_options() const
1323 && papersize == PAPER_CUSTOM
1324 && !lyxrc.print_paper_dimension_flag.empty()
1325 && !paperwidth.empty()
1326 && !paperheight.empty()) {
1327 // using a custom papersize
1328 result = lyxrc.print_paper_dimension_flag;
1329 result += ' ' + paperwidth;
1330 result += ',' + paperheight;
1332 string const paper_option = paperSizeName();
1333 if (paper_option != "letter" ||
1334 orientation != ORIENTATION_LANDSCAPE) {
1335 // dvips won't accept -t letter -t landscape.
1336 // In all other cases, include the paper size
1338 result = lyxrc.print_paper_flag;
1339 result += ' ' + paper_option;
1342 if (orientation == ORIENTATION_LANDSCAPE &&
1343 papersize != PAPER_CUSTOM)
1344 result += ' ' + lyxrc.print_landscape_flag;
1349 string const BufferParams::babelCall(string const & lang_opts) const
1351 string lang_pack = lyxrc.language_package;
1352 if (lang_pack != "\\usepackage{babel}")
1354 // suppress the babel call when there is no babel language defined
1355 // for the document language in the lib/languages file and if no
1356 // other languages are used (lang_opts is then empty)
1357 if (lang_opts.empty())
1359 if (!lyxrc.language_global_options)
1360 return "\\usepackage[" + lang_opts + "]{babel}";
1365 void BufferParams::writeEncodingPreamble(odocstream & os,
1366 LaTeXFeatures & features, TexRow & texrow) const
1368 if (inputenc == "auto") {
1369 string const doc_encoding =
1370 language->encoding()->latexName();
1371 Encoding::Package const package =
1372 language->encoding()->package();
1374 // Create a list with all the input encodings used
1376 std::set<string> encodings =
1377 features.getEncodingSet(doc_encoding);
1379 if (!encodings.empty() || package == Encoding::inputenc) {
1380 os << "\\usepackage[";
1381 std::set<string>::const_iterator it = encodings.begin();
1382 std::set<string>::const_iterator const end = encodings.end();
1384 os << from_ascii(*it);
1387 for (; it != end; ++it)
1388 os << ',' << from_ascii(*it);
1389 if (package == Encoding::inputenc) {
1390 if (!encodings.empty())
1392 os << from_ascii(doc_encoding);
1394 os << "]{inputenc}\n";
1397 if (package == Encoding::CJK) {
1398 os << "\\usepackage{CJK}\n";
1401 } else if (inputenc != "default") {
1402 switch (language->encoding()->package()) {
1403 case Encoding::none:
1405 case Encoding::inputenc:
1406 os << "\\usepackage[" << from_ascii(inputenc)
1411 os << "\\usepackage{CJK}\n";
1417 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1418 // armscii8 is used for Armenian.
1419 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1420 os << "\\usepackage{armtex}\n";
1426 string const BufferParams::loadFonts(string const & rm,
1427 string const & sf, string const & tt,
1428 bool const & sc, bool const & osf,
1429 int const & sfscale, int const & ttscale) const
1431 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1432 several packages have been replaced by others, that might not
1433 be installed on every system. We have to take care for that
1434 (see psnfss.pdf). We try to support all psnfss fonts as well
1435 as the fonts that have become de facto standard in the LaTeX
1436 world (e.g. Latin Modern). We do not support obsolete fonts
1437 (like PSLatex). In general, it should be possible to mix any
1438 rm font with any sf or tt font, respectively. (JSpitzm)
1440 -- separate math fonts.
1443 if (rm == "default" && sf == "default" && tt == "default")
1450 // Computer Modern (must be explicitely selectable -- there might be classes
1451 // that define a different default font!
1453 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1454 // osf for Computer Modern needs eco.sty
1456 os << "\\usepackage{eco}\n";
1458 // Latin Modern Roman
1459 else if (rm == "lmodern")
1460 os << "\\usepackage{lmodern}\n";
1462 else if (rm == "ae") {
1463 // not needed when using OT1 font encoding.
1464 if (lyxrc.fontenc != "default")
1465 os << "\\usepackage{ae,aecompl}\n";
1468 else if (rm == "times") {
1469 // try to load the best available package
1470 if (LaTeXFeatures::isAvailable("mathptmx"))
1471 os << "\\usepackage{mathptmx}\n";
1472 else if (LaTeXFeatures::isAvailable("mathptm"))
1473 os << "\\usepackage{mathptm}\n";
1475 os << "\\usepackage{times}\n";
1478 else if (rm == "palatino") {
1479 // try to load the best available package
1480 if (LaTeXFeatures::isAvailable("mathpazo")) {
1481 os << "\\usepackage";
1487 // "osf" includes "sc"!
1491 os << "{mathpazo}\n";
1493 else if (LaTeXFeatures::isAvailable("mathpple"))
1494 os << "\\usepackage{mathpple}\n";
1496 os << "\\usepackage{palatino}\n";
1499 else if (rm == "utopia") {
1500 // fourier supersedes utopia.sty, but does
1501 // not work with OT1 encoding.
1502 if (LaTeXFeatures::isAvailable("fourier")
1503 && lyxrc.fontenc != "default") {
1504 os << "\\usepackage";
1515 os << "{fourier}\n";
1518 os << "\\usepackage{utopia}\n";
1520 // Bera (complete fontset)
1521 else if (rm == "bera" && sf == "default" && tt == "default")
1522 os << "\\usepackage{bera}\n";
1524 else if (rm != "default")
1525 os << "\\usepackage" << "{" << rm << "}\n";
1528 // Helvetica, Bera Sans
1529 if (sf == "helvet" || sf == "berasans") {
1531 os << "\\usepackage[scaled=" << float(sfscale) / 100
1532 << "]{" << sf << "}\n";
1534 os << "\\usepackage{" << sf << "}\n";
1537 else if (sf == "avant")
1538 os << "\\usepackage{" << sf << "}\n";
1539 // Computer Modern, Latin Modern, CM Bright
1540 else if (sf != "default")
1541 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1543 // monospaced/typewriter
1544 // Courier, LuxiMono
1545 if (tt == "luximono" || tt == "beramono") {
1547 os << "\\usepackage[scaled=" << float(ttscale) / 100
1548 << "]{" << tt << "}\n";
1550 os << "\\usepackage{" << tt << "}\n";
1553 else if (tt == "courier" )
1554 os << "\\usepackage{" << tt << "}\n";
1555 // Computer Modern, Latin Modern, CM Bright
1556 else if (tt != "default")
1557 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1563 Encoding const & BufferParams::encoding() const
1565 if (inputenc == "auto" || inputenc == "default")
1566 return *(language->encoding());
1567 Encoding const * const enc =
1568 encodings.getFromLaTeXName(inputenc);
1571 lyxerr << "Unknown inputenc value `" << inputenc
1572 << "'. Using `auto' instead." << endl;
1573 return *(language->encoding());
1577 biblio::CiteEngine BufferParams::getEngine() const
1579 // FIXME the class should provide the numerical/
1580 // authoryear choice
1581 if (getTextClass().provides("natbib")
1582 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1583 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1584 return cite_engine_;
1588 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1590 cite_engine_ = cite_engine;