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";
897 // this one is not per buffer
898 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
899 if (lyxrc.fontenc != "default") {
900 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
901 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
902 << ",LFE,LAE]{fontenc}\n";
905 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
911 // handle inputenc etc.
912 writeEncodingPreamble(os, features, texrow);
914 if (!listings_params.empty()) {
915 os << "\\usepackage{listings}\n";
918 // do not test validity because listings_params is supposed to be valid
919 string par = InsetListingsParams(listings_params).separatedParams(true);
920 os << from_ascii(par);
921 // count the number of newlines
922 for (size_t i = 0; i < par.size(); ++i)
928 if (use_geometry || nonstandard_papersize) {
929 os << "\\usepackage{geometry}\n";
931 os << "\\geometry{verbose";
932 if (orientation == ORIENTATION_LANDSCAPE)
936 if (!paperwidth.empty())
938 << from_ascii(paperwidth);
939 if (!paperheight.empty())
940 os << ",paperheight="
941 << from_ascii(paperheight);
944 os << ",letterpaper";
949 case PAPER_USEXECUTIVE:
950 os << ",executivepaper";
971 // default papersize ie PAPER_DEFAULT
972 switch (lyxrc.default_papersize) {
973 case PAPER_DEFAULT: // keep compiler happy
975 os << ",letterpaper";
980 case PAPER_USEXECUTIVE:
981 os << ",executivepaper";
1001 if (!topmargin.empty())
1002 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1003 if (!bottommargin.empty())
1004 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1005 if (!leftmargin.empty())
1006 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1007 if (!rightmargin.empty())
1008 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1009 if (!headheight.empty())
1010 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1011 if (!headsep.empty())
1012 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1013 if (!footskip.empty())
1014 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1019 if (tokenPos(tclass.opt_pagestyle(),
1020 '|', pagestyle) >= 0) {
1021 if (pagestyle == "fancy") {
1022 os << "\\usepackage{fancyhdr}\n";
1025 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1029 // Only if class has a ToC hierarchy
1030 if (tclass.hasTocLevels()) {
1031 if (secnumdepth != tclass.secnumdepth()) {
1032 os << "\\setcounter{secnumdepth}{"
1037 if (tocdepth != tclass.tocdepth()) {
1038 os << "\\setcounter{tocdepth}{"
1045 if (paragraph_separation) {
1046 switch (getDefSkip().kind()) {
1047 case VSpace::SMALLSKIP:
1048 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1050 case VSpace::MEDSKIP:
1051 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1053 case VSpace::BIGSKIP:
1054 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1056 case VSpace::LENGTH:
1057 os << "\\setlength{\\parskip}{"
1058 << from_utf8(getDefSkip().length().asLatexString())
1061 default: // should never happen // Then delete it.
1062 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1067 os << "\\setlength{\\parindent}{0pt}\n";
1071 // If we use jurabib, we have to call babel here.
1072 if (use_babel && features.isRequired("jurabib")) {
1073 os << from_ascii(babelCall(language_options.str()))
1075 << from_ascii(features.getBabelOptions());
1079 // Now insert the LyX specific LaTeX commands...
1081 // The optional packages;
1082 docstring lyxpreamble(from_ascii(features.getPackages()));
1084 // this might be useful...
1085 lyxpreamble += "\n\\makeatletter\n";
1087 // Some macros LyX will need
1088 docstring tmppreamble(from_ascii(features.getMacros()));
1090 if (!tmppreamble.empty()) {
1091 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1092 "LyX specific LaTeX commands.\n"
1093 + tmppreamble + '\n';
1096 // the text class specific preamble
1097 tmppreamble = features.getTClassPreamble();
1098 if (!tmppreamble.empty()) {
1099 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1100 "Textclass specific LaTeX commands.\n"
1101 + tmppreamble + '\n';
1104 /* the user-defined preamble */
1105 if (!preamble.empty()) {
1107 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1108 "User specified LaTeX commands.\n"
1109 + from_utf8(preamble) + '\n';
1112 // Itemize bullet settings need to be last in case the user
1113 // defines their own bullets that use a package included
1114 // in the user-defined preamble -- ARRae
1115 // Actually it has to be done much later than that
1116 // since some packages like frenchb make modifications
1117 // at \begin{document} time -- JMarc
1118 docstring bullets_def;
1119 for (int i = 0; i < 4; ++i) {
1120 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1121 if (bullets_def.empty())
1122 bullets_def += "\\AtBeginDocument{\n";
1123 bullets_def += " \\def\\labelitemi";
1125 // `i' is one less than the item to modify
1132 bullets_def += "ii";
1138 bullets_def += '{' +
1139 user_defined_bullet(i).getText()
1144 if (!bullets_def.empty())
1145 lyxpreamble += bullets_def + "}\n\n";
1147 // We try to load babel late, in case it interferes
1148 // with other packages.
1149 // Jurabib has to be called after babel, though.
1150 if (use_babel && !features.isRequired("jurabib")) {
1152 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1153 lyxpreamble += from_utf8(features.getBabelOptions());
1156 lyxpreamble += "\\makeatother\n\n";
1159 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1160 for (int j = 0; j != nlines; ++j) {
1169 void BufferParams::useClassDefaults()
1171 TextClass const & tclass = textclasslist[textclass];
1173 sides = tclass.sides();
1174 columns = tclass.columns();
1175 pagestyle = tclass.pagestyle();
1176 options = tclass.options();
1177 // Only if class has a ToC hierarchy
1178 if (tclass.hasTocLevels()) {
1179 secnumdepth = tclass.secnumdepth();
1180 tocdepth = tclass.tocdepth();
1185 bool BufferParams::hasClassDefaults() const
1187 TextClass const & tclass = textclasslist[textclass];
1189 return (sides == tclass.sides()
1190 && columns == tclass.columns()
1191 && pagestyle == tclass.pagestyle()
1192 && options == tclass.options()
1193 && secnumdepth == tclass.secnumdepth()
1194 && tocdepth == tclass.tocdepth());
1198 TextClass const & BufferParams::getTextClass() const
1200 return textclasslist[textclass];
1204 Font const BufferParams::getFont() const
1206 Font f = getTextClass().defaultfont();
1207 f.setLanguage(language);
1208 if (fontsDefaultFamily == "rmdefault")
1209 f.setFamily(Font::ROMAN_FAMILY);
1210 else if (fontsDefaultFamily == "sfdefault")
1211 f.setFamily(Font::SANS_FAMILY);
1212 else if (fontsDefaultFamily == "ttdefault")
1213 f.setFamily(Font::TYPEWRITER_FAMILY);
1218 void BufferParams::readPreamble(Lexer & lex)
1220 if (lex.getString() != "\\begin_preamble")
1221 lyxerr << "Error (BufferParams::readPreamble):"
1222 "consistency check failed." << endl;
1224 preamble = lex.getLongString("\\end_preamble");
1228 void BufferParams::readLanguage(Lexer & lex)
1230 if (!lex.next()) return;
1232 string const tmptok = lex.getString();
1234 // check if tmptok is part of tex_babel in tex-defs.h
1235 language = languages.getLanguage(tmptok);
1237 // Language tmptok was not found
1238 language = default_language;
1239 lyxerr << "Warning: Setting language `"
1240 << tmptok << "' to `" << language->lang()
1246 void BufferParams::readGraphicsDriver(Lexer & lex)
1248 if (!lex.next()) return;
1250 string const tmptok = lex.getString();
1251 // check if tmptok is part of tex_graphics in tex_defs.h
1254 string const test = tex_graphics[n++];
1256 if (test == tmptok) {
1257 graphicsDriver = tmptok;
1259 } else if (test == "") {
1261 "Warning: graphics driver `$$Token' not recognized!\n"
1262 " Setting graphics driver to `default'.\n");
1263 graphicsDriver = "default";
1270 void BufferParams::readBullets(Lexer & lex)
1272 if (!lex.next()) return;
1274 int const index = lex.getInteger();
1276 int temp_int = lex.getInteger();
1277 user_defined_bullet(index).setFont(temp_int);
1278 temp_bullet(index).setFont(temp_int);
1280 user_defined_bullet(index).setCharacter(temp_int);
1281 temp_bullet(index).setCharacter(temp_int);
1283 user_defined_bullet(index).setSize(temp_int);
1284 temp_bullet(index).setSize(temp_int);
1288 void BufferParams::readBulletsLaTeX(Lexer & lex)
1290 // The bullet class should be able to read this.
1291 if (!lex.next()) return;
1292 int const index = lex.getInteger();
1294 docstring const temp_str = lex.getDocString();
1296 user_defined_bullet(index).setText(temp_str);
1297 temp_bullet(index).setText(temp_str);
1301 string const BufferParams::paperSizeName() const
1303 char real_papersize = papersize;
1304 if (real_papersize == PAPER_DEFAULT)
1305 real_papersize = lyxrc.default_papersize;
1307 switch (real_papersize) {
1316 case PAPER_USEXECUTIVE:
1320 case PAPER_USLETTER:
1327 string const BufferParams::dvips_options() const
1332 && papersize == PAPER_CUSTOM
1333 && !lyxrc.print_paper_dimension_flag.empty()
1334 && !paperwidth.empty()
1335 && !paperheight.empty()) {
1336 // using a custom papersize
1337 result = lyxrc.print_paper_dimension_flag;
1338 result += ' ' + paperwidth;
1339 result += ',' + paperheight;
1341 string const paper_option = paperSizeName();
1342 if (paper_option != "letter" ||
1343 orientation != ORIENTATION_LANDSCAPE) {
1344 // dvips won't accept -t letter -t landscape.
1345 // In all other cases, include the paper size
1347 result = lyxrc.print_paper_flag;
1348 result += ' ' + paper_option;
1351 if (orientation == ORIENTATION_LANDSCAPE &&
1352 papersize != PAPER_CUSTOM)
1353 result += ' ' + lyxrc.print_landscape_flag;
1358 string const BufferParams::babelCall(string const & lang_opts) const
1360 string lang_pack = lyxrc.language_package;
1361 if (lang_pack != "\\usepackage{babel}")
1363 // suppress the babel call when there is no babel language defined
1364 // for the document language in the lib/languages file and if no
1365 // other languages are used (lang_opts is then empty)
1366 if (lang_opts.empty())
1368 if (!lyxrc.language_global_options)
1369 return "\\usepackage[" + lang_opts + "]{babel}";
1374 void BufferParams::writeEncodingPreamble(odocstream & os,
1375 LaTeXFeatures & features, TexRow & texrow) const
1377 if (inputenc == "auto") {
1378 string const doc_encoding =
1379 language->encoding()->latexName();
1380 Encoding::Package const package =
1381 language->encoding()->package();
1383 // Create a list with all the input encodings used
1385 std::set<string> encodings =
1386 features.getEncodingSet(doc_encoding);
1388 if (!encodings.empty() || package == Encoding::inputenc) {
1389 os << "\\usepackage[";
1390 std::set<string>::const_iterator it = encodings.begin();
1391 std::set<string>::const_iterator const end = encodings.end();
1393 os << from_ascii(*it);
1396 for (; it != end; ++it)
1397 os << ',' << from_ascii(*it);
1398 if (package == Encoding::inputenc) {
1399 if (!encodings.empty())
1401 os << from_ascii(doc_encoding);
1403 os << "]{inputenc}\n";
1406 if (package == Encoding::CJK) {
1407 os << "\\usepackage{CJK}\n";
1410 } else if (inputenc != "default") {
1411 switch (language->encoding()->package()) {
1412 case Encoding::none:
1414 case Encoding::inputenc:
1415 os << "\\usepackage[" << from_ascii(inputenc)
1420 os << "\\usepackage{CJK}\n";
1426 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1427 // armscii8 is used for Armenian.
1428 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1429 os << "\\usepackage{armtex}\n";
1435 string const BufferParams::loadFonts(string const & rm,
1436 string const & sf, string const & tt,
1437 bool const & sc, bool const & osf,
1438 int const & sfscale, int const & ttscale) const
1440 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1441 several packages have been replaced by others, that might not
1442 be installed on every system. We have to take care for that
1443 (see psnfss.pdf). We try to support all psnfss fonts as well
1444 as the fonts that have become de facto standard in the LaTeX
1445 world (e.g. Latin Modern). We do not support obsolete fonts
1446 (like PSLatex). In general, it should be possible to mix any
1447 rm font with any sf or tt font, respectively. (JSpitzm)
1449 -- separate math fonts.
1452 if (rm == "default" && sf == "default" && tt == "default")
1459 // Computer Modern (must be explicitely selectable -- there might be classes
1460 // that define a different default font!
1462 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1463 // osf for Computer Modern needs eco.sty
1465 os << "\\usepackage{eco}\n";
1467 // Latin Modern Roman
1468 else if (rm == "lmodern")
1469 os << "\\usepackage{lmodern}\n";
1471 else if (rm == "ae") {
1472 // not needed when using OT1 font encoding.
1473 if (lyxrc.fontenc != "default")
1474 os << "\\usepackage{ae,aecompl}\n";
1477 else if (rm == "times") {
1478 // try to load the best available package
1479 if (LaTeXFeatures::isAvailable("mathptmx"))
1480 os << "\\usepackage{mathptmx}\n";
1481 else if (LaTeXFeatures::isAvailable("mathptm"))
1482 os << "\\usepackage{mathptm}\n";
1484 os << "\\usepackage{times}\n";
1487 else if (rm == "palatino") {
1488 // try to load the best available package
1489 if (LaTeXFeatures::isAvailable("mathpazo")) {
1490 os << "\\usepackage";
1496 // "osf" includes "sc"!
1500 os << "{mathpazo}\n";
1502 else if (LaTeXFeatures::isAvailable("mathpple"))
1503 os << "\\usepackage{mathpple}\n";
1505 os << "\\usepackage{palatino}\n";
1508 else if (rm == "utopia") {
1509 // fourier supersedes utopia.sty, but does
1510 // not work with OT1 encoding.
1511 if (LaTeXFeatures::isAvailable("fourier")
1512 && lyxrc.fontenc != "default") {
1513 os << "\\usepackage";
1524 os << "{fourier}\n";
1527 os << "\\usepackage{utopia}\n";
1529 // Bera (complete fontset)
1530 else if (rm == "bera" && sf == "default" && tt == "default")
1531 os << "\\usepackage{bera}\n";
1533 else if (rm != "default")
1534 os << "\\usepackage" << "{" << rm << "}\n";
1537 // Helvetica, Bera Sans
1538 if (sf == "helvet" || sf == "berasans") {
1540 os << "\\usepackage[scaled=" << float(sfscale) / 100
1541 << "]{" << sf << "}\n";
1543 os << "\\usepackage{" << sf << "}\n";
1546 else if (sf == "avant")
1547 os << "\\usepackage{" << sf << "}\n";
1548 // Computer Modern, Latin Modern, CM Bright
1549 else if (sf != "default")
1550 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1552 // monospaced/typewriter
1553 // Courier, LuxiMono
1554 if (tt == "luximono" || tt == "beramono") {
1556 os << "\\usepackage[scaled=" << float(ttscale) / 100
1557 << "]{" << tt << "}\n";
1559 os << "\\usepackage{" << tt << "}\n";
1562 else if (tt == "courier" )
1563 os << "\\usepackage{" << tt << "}\n";
1564 // Computer Modern, Latin Modern, CM Bright
1565 else if (tt != "default")
1566 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1572 Encoding const & BufferParams::encoding() const
1574 if (inputenc == "auto" || inputenc == "default")
1575 return *(language->encoding());
1576 Encoding const * const enc =
1577 encodings.getFromLaTeXName(inputenc);
1580 lyxerr << "Unknown inputenc value `" << inputenc
1581 << "'. Using `auto' instead." << endl;
1582 return *(language->encoding());
1586 biblio::CiteEngine BufferParams::getEngine() const
1588 // FIXME the class should provide the numerical/
1589 // authoryear choice
1590 if (getTextClass().provides("natbib")
1591 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1592 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1593 return cite_engine_;
1597 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1599 cite_engine_ = cite_engine;