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"
34 #include "TextClassList.h"
35 #include "OutputParams.h"
40 #include "frontends/alert.h"
41 #include "insets/InsetListingsParams.h"
43 #include "support/convert.h"
44 #include "support/Translator.h"
46 #include <boost/array.hpp>
54 using std::istringstream;
56 using std::ostringstream;
59 using lyx::support::bformat;
60 using lyx::support::rtrim;
61 using lyx::support::tokenPos;
64 static char const * const string_paragraph_separation[] = {
69 static char const * const string_quotes_language[] = {
70 "english", "swedish", "german", "polish", "french", "danish", ""
74 static char const * const string_papersize[] = {
75 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
76 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
80 static char const * const string_orientation[] = {
81 "portrait", "landscape", ""
85 static char const * const string_footnotekinds[] = {
86 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
90 static char const * const tex_graphics[] = {
91 "default", "dvips", "dvitops", "emtex",
92 "ln", "oztex", "textures", "none", ""
101 // Paragraph separation
102 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
105 ParSepTranslator const init_parseptranslator()
107 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
108 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
113 ParSepTranslator const & parseptranslator()
115 static ParSepTranslator translator = init_parseptranslator();
121 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
124 QuotesLangTranslator const init_quoteslangtranslator()
126 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
127 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
128 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
129 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
130 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
131 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
136 QuotesLangTranslator const & quoteslangtranslator()
138 static QuotesLangTranslator translator = init_quoteslangtranslator();
144 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
147 PaperSizeTranslator const init_papersizetranslator()
149 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
150 translator.addPair(string_papersize[1], PAPER_CUSTOM);
151 translator.addPair(string_papersize[2], PAPER_USLETTER);
152 translator.addPair(string_papersize[3], PAPER_USLEGAL);
153 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
154 translator.addPair(string_papersize[5], PAPER_A3);
155 translator.addPair(string_papersize[6], PAPER_A4);
156 translator.addPair(string_papersize[7], PAPER_A5);
157 translator.addPair(string_papersize[8], PAPER_B3);
158 translator.addPair(string_papersize[9], PAPER_B4);
159 translator.addPair(string_papersize[10], PAPER_B5);
164 PaperSizeTranslator const & papersizetranslator()
166 static PaperSizeTranslator translator = init_papersizetranslator();
172 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
175 PaperOrientationTranslator const init_paperorientationtranslator()
177 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
178 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
183 PaperOrientationTranslator const & paperorientationtranslator()
185 static PaperOrientationTranslator translator = init_paperorientationtranslator();
191 typedef Translator<int, TextClass::PageSides> SidesTranslator;
194 SidesTranslator const init_sidestranslator()
196 SidesTranslator translator(1, TextClass::OneSide);
197 translator.addPair(2, TextClass::TwoSides);
202 SidesTranslator const & sidestranslator()
204 static SidesTranslator translator = init_sidestranslator();
210 typedef Translator<int, BufferParams::Package> PackageTranslator;
213 PackageTranslator const init_packagetranslator()
215 PackageTranslator translator(0, BufferParams::package_off);
216 translator.addPair(1, BufferParams::package_auto);
217 translator.addPair(2, BufferParams::package_on);
222 PackageTranslator const & packagetranslator()
224 static PackageTranslator translator = init_packagetranslator();
230 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
233 CiteEngineTranslator const init_citeenginetranslator()
235 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
236 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
237 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
238 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
243 CiteEngineTranslator const & citeenginetranslator()
245 static CiteEngineTranslator translator = init_citeenginetranslator();
251 typedef Translator<string, Spacing::Space> SpaceTranslator;
254 SpaceTranslator const init_spacetranslator()
256 SpaceTranslator translator("default", Spacing::Default);
257 translator.addPair("single", Spacing::Single);
258 translator.addPair("onehalf", Spacing::Onehalf);
259 translator.addPair("double", Spacing::Double);
260 translator.addPair("other", Spacing::Other);
265 SpaceTranslator const & spacetranslator()
267 static SpaceTranslator translator = init_spacetranslator();
275 class BufferParams::Impl
280 AuthorList authorlist;
281 BranchList branchlist;
282 boost::array<Bullet, 4> temp_bullets;
283 boost::array<Bullet, 4> user_defined_bullets;
285 /** This is the amount of space used for paragraph_separation "skip",
286 * and for detached paragraphs in "indented" documents.
292 BufferParams::Impl::Impl()
293 : defskip(VSpace::MEDSKIP)
295 // set initial author
297 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
302 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
306 return new BufferParams::Impl(*ptr);
310 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
316 BufferParams::BufferParams()
319 setBaseClass(defaultTextclass());
320 paragraph_separation = PARSEP_INDENT;
321 quotes_language = InsetQuotes::EnglishQ;
322 fontsize = "default";
325 papersize = PAPER_DEFAULT;
326 orientation = ORIENTATION_PORTRAIT;
327 use_geometry = false;
328 use_amsmath = package_auto;
329 use_esint = package_auto;
330 cite_engine_ = biblio::ENGINE_BASIC;
331 use_bibtopic = false;
332 trackChanges = false;
333 outputChanges = false;
336 language = default_language;
337 fontsRoman = "default";
338 fontsSans = "default";
339 fontsTypewriter = "default";
340 fontsDefaultFamily = "default";
343 fontsSansScale = 100;
344 fontsTypewriterScale = 100;
346 graphicsDriver = "default";
347 sides = TextClass::OneSide;
349 listings_params = string();
350 pagestyle = "default";
352 for (int iter = 0; iter < 4; ++iter) {
353 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
354 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
359 BufferParams::~BufferParams()
363 docstring const BufferParams::B_(string const & l10n) const
365 BOOST_ASSERT(language);
366 return getMessages(language->code()).get(l10n);
370 AuthorList & BufferParams::authors()
372 return pimpl_->authorlist;
376 AuthorList const & BufferParams::authors() const
378 return pimpl_->authorlist;
382 BranchList & BufferParams::branchlist()
384 return pimpl_->branchlist;
388 BranchList const & BufferParams::branchlist() const
390 return pimpl_->branchlist;
394 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
396 BOOST_ASSERT(index < 4);
397 return pimpl_->temp_bullets[index];
401 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
403 BOOST_ASSERT(index < 4);
404 return pimpl_->temp_bullets[index];
408 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
410 BOOST_ASSERT(index < 4);
411 return pimpl_->user_defined_bullets[index];
415 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
417 BOOST_ASSERT(index < 4);
418 return pimpl_->user_defined_bullets[index];
422 Spacing & BufferParams::spacing()
424 return pimpl_->spacing;
428 Spacing const & BufferParams::spacing() const
430 return pimpl_->spacing;
434 VSpace const & BufferParams::getDefSkip() const
436 return pimpl_->defskip;
440 void BufferParams::setDefSkip(VSpace const & vs)
442 pimpl_->defskip = vs;
446 string const BufferParams::readToken(Lexer & lex, string const & token)
448 if (token == "\\textclass") {
450 string const classname = lex.getString();
451 pair<bool, lyx::textclass_type> pp =
452 textclasslist.numberOfClass(classname);
454 setBaseClass(pp.second);
456 // if text class does not exist, try to load it from filepath
457 pp = textclasslist.addTextClass(classname, filepath);
459 setBaseClass(pp.second);
461 setBaseClass(defaultTextclass());
465 if (!getTextClass().isTeXClassAvailable()) {
466 docstring const msg =
467 bformat(_("The layout file requested by this document,\n"
469 "is not usable. This is probably because a LaTeX\n"
470 "class or style file required by it is not\n"
471 "available. See the Customization documentation\n"
472 "for more information.\n"), from_utf8(classname));
473 frontend::Alert::warning(_("Document class not available"),
474 msg + _("LyX will not be able to produce output."));
476 } else if (token == "\\begin_preamble") {
478 } else if (token == "\\options") {
480 options = lex.getString();
481 } else if (token == "\\language") {
483 } else if (token == "\\inputencoding") {
485 } else if (token == "\\graphics") {
486 readGraphicsDriver(lex);
487 } else if (token == "\\font_roman") {
489 } else if (token == "\\font_sans") {
491 } else if (token == "\\font_typewriter") {
492 lex >> fontsTypewriter;
493 } else if (token == "\\font_default_family") {
494 lex >> fontsDefaultFamily;
495 } else if (token == "\\font_sc") {
497 } else if (token == "\\font_osf") {
499 } else if (token == "\\font_sf_scale") {
500 lex >> fontsSansScale;
501 } else if (token == "\\font_tt_scale") {
502 lex >> fontsTypewriterScale;
503 } else if (token == "\\paragraph_separation") {
506 paragraph_separation = parseptranslator().find(parsep);
507 } else if (token == "\\defskip") {
509 pimpl_->defskip = VSpace(lex.getString());
510 } else if (token == "\\quotes_language") {
513 quotes_language = quoteslangtranslator().find(quotes_lang);
514 } else if (token == "\\papersize") {
517 papersize = papersizetranslator().find(ppsize);
518 } else if (token == "\\use_geometry") {
520 } else if (token == "\\use_amsmath") {
523 use_amsmath = packagetranslator().find(use_ams);
524 } else if (token == "\\use_esint") {
527 use_esint = packagetranslator().find(useesint);
528 } else if (token == "\\cite_engine") {
531 cite_engine_ = citeenginetranslator().find(engine);
532 } else if (token == "\\use_bibtopic") {
534 } else if (token == "\\tracking_changes") {
536 } else if (token == "\\output_changes") {
537 lex >> outputChanges;
538 } else if (token == "\\branch") {
540 docstring branch = lex.getDocString();
541 branchlist().add(branch);
544 string const tok = lex.getString();
545 if (tok == "\\end_branch")
547 Branch * branch_ptr = branchlist().find(branch);
548 if (tok == "\\selected") {
551 branch_ptr->setSelected(lex.getInteger());
553 // not yet operational
554 if (tok == "\\color") {
556 string color = lex.getString();
558 branch_ptr->setColor(color);
559 // Update also the Color table:
561 color = lcolor.getX11Name(Color::background);
563 lcolor.setColor(to_utf8(branch), color);
567 } else if (token == "\\author") {
569 istringstream ss(lex.getString());
572 author_map.push_back(pimpl_->authorlist.record(a));
573 } else if (token == "\\paperorientation") {
576 orientation = paperorientationtranslator().find(orient);
577 } else if (token == "\\paperwidth") {
579 } else if (token == "\\paperheight") {
581 } else if (token == "\\leftmargin") {
583 } else if (token == "\\topmargin") {
585 } else if (token == "\\rightmargin") {
587 } else if (token == "\\bottommargin") {
589 } else if (token == "\\headheight") {
591 } else if (token == "\\headsep") {
593 } else if (token == "\\footskip") {
595 } else if (token == "\\paperfontsize") {
597 } else if (token == "\\papercolumns") {
599 } else if (token == "\\listings_params") {
602 listings_params = InsetListingsParams(par).params();
603 } else if (token == "\\papersides") {
606 sides = sidestranslator().find(psides);
607 } else if (token == "\\paperpagestyle") {
609 } else if (token == "\\bullet") {
611 } else if (token == "\\bulletLaTeX") {
612 readBulletsLaTeX(lex);
613 } else if (token == "\\secnumdepth") {
615 } else if (token == "\\tocdepth") {
617 } else if (token == "\\spacing") {
621 if (nspacing == "other") {
624 spacing().set(spacetranslator().find(nspacing), tmp_val);
625 } else if (token == "\\float_placement") {
626 lex >> float_placement;
635 void BufferParams::writeFile(ostream & os) const
637 // The top of the file is written by the buffer.
638 // Prints out the buffer info into the .lyx file given by file
641 os << "\\textclass " << textclasslist[baseClass_].name() << '\n';
644 if (!preamble.empty()) {
645 // remove '\n' from the end of preamble
646 string const tmppreamble = rtrim(preamble, "\n");
647 os << "\\begin_preamble\n"
649 << "\n\\end_preamble\n";
653 if (!options.empty()) {
654 os << "\\options " << options << '\n';
657 // then the text parameters
658 if (language != ignore_language)
659 os << "\\language " << language->lang() << '\n';
660 os << "\\inputencoding " << inputenc
661 << "\n\\font_roman " << fontsRoman
662 << "\n\\font_sans " << fontsSans
663 << "\n\\font_typewriter " << fontsTypewriter
664 << "\n\\font_default_family " << fontsDefaultFamily
665 << "\n\\font_sc " << convert<string>(fontsSC)
666 << "\n\\font_osf " << convert<string>(fontsOSF)
667 << "\n\\font_sf_scale " << fontsSansScale
668 << "\n\\font_tt_scale " << fontsTypewriterScale
669 << "\n\\graphics " << graphicsDriver << '\n';
671 if (!float_placement.empty()) {
672 os << "\\float_placement " << float_placement << '\n';
674 os << "\\paperfontsize " << fontsize << '\n';
676 spacing().writeFile(os);
678 os << "\\papersize " << string_papersize[papersize]
679 << "\n\\use_geometry " << convert<string>(use_geometry)
680 << "\n\\use_amsmath " << use_amsmath
681 << "\n\\use_esint " << use_esint
682 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
683 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
684 << "\n\\paperorientation " << string_orientation[orientation]
687 BranchList::const_iterator it = branchlist().begin();
688 BranchList::const_iterator end = branchlist().end();
689 for (; it != end; ++it) {
690 os << "\\branch " << to_utf8(it->getBranch())
691 << "\n\\selected " << it->getSelected()
692 << "\n\\color " << lyx::X11hexname(it->getColor())
697 if (!paperwidth.empty())
698 os << "\\paperwidth "
699 << VSpace(paperwidth).asLyXCommand() << '\n';
700 if (!paperheight.empty())
701 os << "\\paperheight "
702 << VSpace(paperheight).asLyXCommand() << '\n';
703 if (!leftmargin.empty())
704 os << "\\leftmargin "
705 << VSpace(leftmargin).asLyXCommand() << '\n';
706 if (!topmargin.empty())
708 << VSpace(topmargin).asLyXCommand() << '\n';
709 if (!rightmargin.empty())
710 os << "\\rightmargin "
711 << VSpace(rightmargin).asLyXCommand() << '\n';
712 if (!bottommargin.empty())
713 os << "\\bottommargin "
714 << VSpace(bottommargin).asLyXCommand() << '\n';
715 if (!headheight.empty())
716 os << "\\headheight "
717 << VSpace(headheight).asLyXCommand() << '\n';
718 if (!headsep.empty())
720 << VSpace(headsep).asLyXCommand() << '\n';
721 if (!footskip.empty())
723 << VSpace(footskip).asLyXCommand() << '\n';
724 os << "\\secnumdepth " << secnumdepth
725 << "\n\\tocdepth " << tocdepth
726 << "\n\\paragraph_separation "
727 << string_paragraph_separation[paragraph_separation]
728 << "\n\\defskip " << getDefSkip().asLyXCommand()
729 << "\n\\quotes_language "
730 << string_quotes_language[quotes_language]
731 << "\n\\papercolumns " << columns
732 << "\n\\papersides " << sides
733 << "\n\\paperpagestyle " << pagestyle << '\n';
734 if (!listings_params.empty())
735 os << "\\listings_params \"" <<
736 InsetListingsParams(listings_params).encodedString() << "\"\n";
737 for (int i = 0; i < 4; ++i) {
738 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
739 if (user_defined_bullet(i).getFont() != -1) {
740 os << "\\bullet " << i << " "
741 << user_defined_bullet(i).getFont() << " "
742 << user_defined_bullet(i).getCharacter() << " "
743 << user_defined_bullet(i).getSize() << "\n";
747 os << "\\bulletLaTeX " << i << " \""
748 << lyx::to_ascii(user_defined_bullet(i).getText())
754 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
755 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
757 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
758 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
759 for (; a_it != a_end; ++a_it) {
760 if (a_it->second.used())
761 os << "\\author " << a_it->second << "\n";
763 os << "\\author " << Author() << "\n";
768 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
769 TexRow & texrow) const
771 os << "\\documentclass";
773 TextClass const & tclass = getTextClass();
775 ostringstream clsoptions; // the document class options.
777 if (tokenPos(tclass.opt_fontsize(),
778 '|', fontsize) >= 0) {
779 // only write if existing in list (and not default)
780 clsoptions << fontsize << "pt,";
783 // custom, A3, B3 and B4 paper sizes need geometry
784 bool nonstandard_papersize = papersize == PAPER_B3
785 || papersize == PAPER_B4
786 || papersize == PAPER_A3
787 || papersize == PAPER_CUSTOM;
792 clsoptions << "a4paper,";
795 clsoptions << "letterpaper,";
798 clsoptions << "a5paper,";
801 clsoptions << "b5paper,";
803 case PAPER_USEXECUTIVE:
804 clsoptions << "executivepaper,";
807 clsoptions << "legalpaper,";
819 if (sides != tclass.sides()) {
821 case TextClass::OneSide:
822 clsoptions << "oneside,";
824 case TextClass::TwoSides:
825 clsoptions << "twoside,";
831 if (columns != tclass.columns()) {
833 clsoptions << "twocolumn,";
835 clsoptions << "onecolumn,";
839 && orientation == ORIENTATION_LANDSCAPE)
840 clsoptions << "landscape,";
842 // language should be a parameter to \documentclass
843 if (language->babel() == "hebrew"
844 && default_language->babel() != "hebrew")
845 // This seems necessary
846 features.useLanguage(default_language);
848 ostringstream language_options;
849 bool const use_babel = features.useBabel();
851 language_options << features.getLanguages();
852 if (!language->babel().empty()) {
853 if (!language_options.str().empty())
854 language_options << ',';
855 language_options << language->babel();
857 if (lyxrc.language_global_options && !language_options.str().empty())
858 clsoptions << language_options.str() << ',';
861 // the user-defined options
862 if (!options.empty()) {
863 clsoptions << options << ',';
866 string strOptions(clsoptions.str());
867 if (!strOptions.empty()) {
868 strOptions = rtrim(strOptions, ",");
870 os << '[' << from_utf8(strOptions) << ']';
873 os << '{' << from_ascii(tclass.latexname()) << "}\n";
875 // end of \documentclass defs
877 // font selection must be done before loading fontenc.sty
879 loadFonts(fontsRoman, fontsSans,
880 fontsTypewriter, fontsSC, fontsOSF,
881 fontsSansScale, fontsTypewriterScale);
882 if (!fonts.empty()) {
883 os << from_ascii(fonts);
886 if (fontsDefaultFamily != "default")
887 os << "\\renewcommand{\\familydefault}{\\"
888 << from_ascii(fontsDefaultFamily) << "}\n";
891 // this one is not per buffer
892 // for arabic_arabi and farsi we also need to load the LAE and LFE encoding
893 if (lyxrc.fontenc != "default") {
894 if (language->lang() == "arabic_arabi" || language->lang() == "farsi") {
895 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
896 << ",LFE,LAE]{fontenc}\n";
899 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
905 // handle inputenc etc.
906 writeEncodingPreamble(os, features, texrow);
908 if (!listings_params.empty()) {
909 os << "\\usepackage{listings}\n";
912 // do not test validity because listings_params is supposed to be valid
913 string par = InsetListingsParams(listings_params).separatedParams(true);
914 os << from_ascii(par);
915 // count the number of newlines
916 for (size_t i = 0; i < par.size(); ++i)
922 if (use_geometry || nonstandard_papersize) {
923 os << "\\usepackage{geometry}\n";
925 os << "\\geometry{verbose";
926 if (orientation == ORIENTATION_LANDSCAPE)
930 if (!paperwidth.empty())
932 << from_ascii(paperwidth);
933 if (!paperheight.empty())
934 os << ",paperheight="
935 << from_ascii(paperheight);
938 os << ",letterpaper";
943 case PAPER_USEXECUTIVE:
944 os << ",executivepaper";
965 // default papersize ie PAPER_DEFAULT
966 switch (lyxrc.default_papersize) {
967 case PAPER_DEFAULT: // keep compiler happy
969 os << ",letterpaper";
974 case PAPER_USEXECUTIVE:
975 os << ",executivepaper";
995 if (!topmargin.empty())
996 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
997 if (!bottommargin.empty())
998 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
999 if (!leftmargin.empty())
1000 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1001 if (!rightmargin.empty())
1002 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1003 if (!headheight.empty())
1004 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1005 if (!headsep.empty())
1006 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1007 if (!footskip.empty())
1008 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1013 if (tokenPos(tclass.opt_pagestyle(),
1014 '|', pagestyle) >= 0) {
1015 if (pagestyle == "fancy") {
1016 os << "\\usepackage{fancyhdr}\n";
1019 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1023 // Only if class has a ToC hierarchy
1024 if (tclass.hasTocLevels()) {
1025 if (secnumdepth != tclass.secnumdepth()) {
1026 os << "\\setcounter{secnumdepth}{"
1031 if (tocdepth != tclass.tocdepth()) {
1032 os << "\\setcounter{tocdepth}{"
1039 if (paragraph_separation) {
1040 switch (getDefSkip().kind()) {
1041 case VSpace::SMALLSKIP:
1042 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1044 case VSpace::MEDSKIP:
1045 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1047 case VSpace::BIGSKIP:
1048 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1050 case VSpace::LENGTH:
1051 os << "\\setlength{\\parskip}{"
1052 << from_utf8(getDefSkip().length().asLatexString())
1055 default: // should never happen // Then delete it.
1056 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1061 os << "\\setlength{\\parindent}{0pt}\n";
1065 // If we use jurabib, we have to call babel here.
1066 if (use_babel && features.isRequired("jurabib")) {
1067 os << from_ascii(babelCall(language_options.str()))
1069 << from_ascii(features.getBabelOptions());
1073 // Now insert the LyX specific LaTeX commands...
1075 // The optional packages;
1076 docstring lyxpreamble(from_ascii(features.getPackages()));
1078 // this might be useful...
1079 lyxpreamble += "\n\\makeatletter\n";
1081 // Some macros LyX will need
1082 docstring tmppreamble(from_ascii(features.getMacros()));
1084 if (!tmppreamble.empty()) {
1085 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1086 "LyX specific LaTeX commands.\n"
1087 + tmppreamble + '\n';
1090 // the text class specific preamble
1091 tmppreamble = features.getTClassPreamble();
1092 if (!tmppreamble.empty()) {
1093 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1094 "Textclass specific LaTeX commands.\n"
1095 + tmppreamble + '\n';
1098 /* the user-defined preamble */
1099 if (!preamble.empty()) {
1101 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1102 "User specified LaTeX commands.\n"
1103 + from_utf8(preamble) + '\n';
1106 // Itemize bullet settings need to be last in case the user
1107 // defines their own bullets that use a package included
1108 // in the user-defined preamble -- ARRae
1109 // Actually it has to be done much later than that
1110 // since some packages like frenchb make modifications
1111 // at \begin{document} time -- JMarc
1112 docstring bullets_def;
1113 for (int i = 0; i < 4; ++i) {
1114 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1115 if (bullets_def.empty())
1116 bullets_def += "\\AtBeginDocument{\n";
1117 bullets_def += " \\def\\labelitemi";
1119 // `i' is one less than the item to modify
1126 bullets_def += "ii";
1132 bullets_def += '{' +
1133 user_defined_bullet(i).getText()
1138 if (!bullets_def.empty())
1139 lyxpreamble += bullets_def + "}\n\n";
1141 // We try to load babel late, in case it interferes
1142 // with other packages.
1143 // Jurabib has to be called after babel, though.
1144 if (use_babel && !features.isRequired("jurabib")) {
1146 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1147 lyxpreamble += from_utf8(features.getBabelOptions());
1150 lyxpreamble += "\\makeatother\n\n";
1153 int(count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1154 for (int j = 0; j != nlines; ++j) {
1163 void BufferParams::useClassDefaults()
1165 TextClass const & tclass = textclasslist[baseClass_];
1167 sides = tclass.sides();
1168 columns = tclass.columns();
1169 pagestyle = tclass.pagestyle();
1170 options = tclass.options();
1171 // Only if class has a ToC hierarchy
1172 if (tclass.hasTocLevels()) {
1173 secnumdepth = tclass.secnumdepth();
1174 tocdepth = tclass.tocdepth();
1179 bool BufferParams::hasClassDefaults() const
1181 TextClass const & tclass = textclasslist[baseClass_];
1183 return (sides == tclass.sides()
1184 && columns == tclass.columns()
1185 && pagestyle == tclass.pagestyle()
1186 && options == tclass.options()
1187 && secnumdepth == tclass.secnumdepth()
1188 && tocdepth == tclass.tocdepth());
1192 TextClass const & BufferParams::getTextClass() const
1198 TextClass_ptr BufferParams::getTextClass_ptr() const {
1203 void BufferParams::setTextClass(TextClass_ptr tc) {
1208 void BufferParams::setBaseClass(textclass_type tc)
1215 void BufferParams::setJustBaseClass(textclass_type tc)
1221 textclass_type BufferParams::getBaseClass() const
1227 void BufferParams::makeTextClass()
1229 textClass_.reset(new TextClass(textclasslist[getBaseClass()]));
1233 Font const BufferParams::getFont() const
1235 Font f = getTextClass().defaultfont();
1236 f.setLanguage(language);
1237 if (fontsDefaultFamily == "rmdefault")
1238 f.setFamily(Font::ROMAN_FAMILY);
1239 else if (fontsDefaultFamily == "sfdefault")
1240 f.setFamily(Font::SANS_FAMILY);
1241 else if (fontsDefaultFamily == "ttdefault")
1242 f.setFamily(Font::TYPEWRITER_FAMILY);
1247 void BufferParams::readPreamble(Lexer & lex)
1249 if (lex.getString() != "\\begin_preamble")
1250 lyxerr << "Error (BufferParams::readPreamble):"
1251 "consistency check failed." << endl;
1253 preamble = lex.getLongString("\\end_preamble");
1257 void BufferParams::readLanguage(Lexer & lex)
1259 if (!lex.next()) return;
1261 string const tmptok = lex.getString();
1263 // check if tmptok is part of tex_babel in tex-defs.h
1264 language = languages.getLanguage(tmptok);
1266 // Language tmptok was not found
1267 language = default_language;
1268 lyxerr << "Warning: Setting language `"
1269 << tmptok << "' to `" << language->lang()
1275 void BufferParams::readGraphicsDriver(Lexer & lex)
1277 if (!lex.next()) return;
1279 string const tmptok = lex.getString();
1280 // check if tmptok is part of tex_graphics in tex_defs.h
1283 string const test = tex_graphics[n++];
1285 if (test == tmptok) {
1286 graphicsDriver = tmptok;
1288 } else if (test == "") {
1290 "Warning: graphics driver `$$Token' not recognized!\n"
1291 " Setting graphics driver to `default'.\n");
1292 graphicsDriver = "default";
1299 void BufferParams::readBullets(Lexer & lex)
1301 if (!lex.next()) return;
1303 int const index = lex.getInteger();
1305 int temp_int = lex.getInteger();
1306 user_defined_bullet(index).setFont(temp_int);
1307 temp_bullet(index).setFont(temp_int);
1309 user_defined_bullet(index).setCharacter(temp_int);
1310 temp_bullet(index).setCharacter(temp_int);
1312 user_defined_bullet(index).setSize(temp_int);
1313 temp_bullet(index).setSize(temp_int);
1317 void BufferParams::readBulletsLaTeX(Lexer & lex)
1319 // The bullet class should be able to read this.
1320 if (!lex.next()) return;
1321 int const index = lex.getInteger();
1323 docstring const temp_str = lex.getDocString();
1325 user_defined_bullet(index).setText(temp_str);
1326 temp_bullet(index).setText(temp_str);
1330 string const BufferParams::paperSizeName() const
1332 char real_papersize = papersize;
1333 if (real_papersize == PAPER_DEFAULT)
1334 real_papersize = lyxrc.default_papersize;
1336 switch (real_papersize) {
1345 case PAPER_USEXECUTIVE:
1349 case PAPER_USLETTER:
1356 string const BufferParams::dvips_options() const
1361 && papersize == PAPER_CUSTOM
1362 && !lyxrc.print_paper_dimension_flag.empty()
1363 && !paperwidth.empty()
1364 && !paperheight.empty()) {
1365 // using a custom papersize
1366 result = lyxrc.print_paper_dimension_flag;
1367 result += ' ' + paperwidth;
1368 result += ',' + paperheight;
1370 string const paper_option = paperSizeName();
1371 if (paper_option != "letter" ||
1372 orientation != ORIENTATION_LANDSCAPE) {
1373 // dvips won't accept -t letter -t landscape.
1374 // In all other cases, include the paper size
1376 result = lyxrc.print_paper_flag;
1377 result += ' ' + paper_option;
1380 if (orientation == ORIENTATION_LANDSCAPE &&
1381 papersize != PAPER_CUSTOM)
1382 result += ' ' + lyxrc.print_landscape_flag;
1387 string const BufferParams::babelCall(string const & lang_opts) const
1389 string lang_pack = lyxrc.language_package;
1390 if (lang_pack != "\\usepackage{babel}")
1392 // suppress the babel call when there is no babel language defined
1393 // for the document language in the lib/languages file and if no
1394 // other languages are used (lang_opts is then empty)
1395 if (lang_opts.empty())
1397 if (!lyxrc.language_global_options)
1398 return "\\usepackage[" + lang_opts + "]{babel}";
1403 void BufferParams::writeEncodingPreamble(odocstream & os,
1404 LaTeXFeatures & features, TexRow & texrow) const
1406 if (inputenc == "auto") {
1407 string const doc_encoding =
1408 language->encoding()->latexName();
1409 Encoding::Package const package =
1410 language->encoding()->package();
1412 // Create a list with all the input encodings used
1414 std::set<string> encodings =
1415 features.getEncodingSet(doc_encoding);
1417 if (!encodings.empty() || package == Encoding::inputenc) {
1418 os << "\\usepackage[";
1419 std::set<string>::const_iterator it = encodings.begin();
1420 std::set<string>::const_iterator const end = encodings.end();
1422 os << from_ascii(*it);
1425 for (; it != end; ++it)
1426 os << ',' << from_ascii(*it);
1427 if (package == Encoding::inputenc) {
1428 if (!encodings.empty())
1430 os << from_ascii(doc_encoding);
1432 os << "]{inputenc}\n";
1435 if (package == Encoding::CJK) {
1436 os << "\\usepackage{CJK}\n";
1439 } else if (inputenc != "default") {
1440 switch (encoding().package()) {
1441 case Encoding::none:
1443 case Encoding::inputenc:
1444 os << "\\usepackage[" << from_ascii(inputenc)
1449 os << "\\usepackage{CJK}\n";
1455 // The encoding "armscii8" is only available when the package "armtex" is loaded.
1456 // armscii8 is used for Armenian.
1457 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
1458 os << "\\usepackage{armtex}\n";
1464 string const BufferParams::loadFonts(string const & rm,
1465 string const & sf, string const & tt,
1466 bool const & sc, bool const & osf,
1467 int const & sfscale, int const & ttscale) const
1469 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1470 several packages have been replaced by others, that might not
1471 be installed on every system. We have to take care for that
1472 (see psnfss.pdf). We try to support all psnfss fonts as well
1473 as the fonts that have become de facto standard in the LaTeX
1474 world (e.g. Latin Modern). We do not support obsolete fonts
1475 (like PSLatex). In general, it should be possible to mix any
1476 rm font with any sf or tt font, respectively. (JSpitzm)
1478 -- separate math fonts.
1481 if (rm == "default" && sf == "default" && tt == "default")
1488 // Computer Modern (must be explicitely selectable -- there might be classes
1489 // that define a different default font!
1491 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1492 // osf for Computer Modern needs eco.sty
1494 os << "\\usepackage{eco}\n";
1496 // Latin Modern Roman
1497 else if (rm == "lmodern")
1498 os << "\\usepackage{lmodern}\n";
1500 else if (rm == "ae") {
1501 // not needed when using OT1 font encoding.
1502 if (lyxrc.fontenc != "default")
1503 os << "\\usepackage{ae,aecompl}\n";
1506 else if (rm == "times") {
1507 // try to load the best available package
1508 if (LaTeXFeatures::isAvailable("mathptmx"))
1509 os << "\\usepackage{mathptmx}\n";
1510 else if (LaTeXFeatures::isAvailable("mathptm"))
1511 os << "\\usepackage{mathptm}\n";
1513 os << "\\usepackage{times}\n";
1516 else if (rm == "palatino") {
1517 // try to load the best available package
1518 if (LaTeXFeatures::isAvailable("mathpazo")) {
1519 os << "\\usepackage";
1525 // "osf" includes "sc"!
1529 os << "{mathpazo}\n";
1531 else if (LaTeXFeatures::isAvailable("mathpple"))
1532 os << "\\usepackage{mathpple}\n";
1534 os << "\\usepackage{palatino}\n";
1537 else if (rm == "utopia") {
1538 // fourier supersedes utopia.sty, but does
1539 // not work with OT1 encoding.
1540 if (LaTeXFeatures::isAvailable("fourier")
1541 && lyxrc.fontenc != "default") {
1542 os << "\\usepackage";
1553 os << "{fourier}\n";
1556 os << "\\usepackage{utopia}\n";
1558 // Bera (complete fontset)
1559 else if (rm == "bera" && sf == "default" && tt == "default")
1560 os << "\\usepackage{bera}\n";
1562 else if (rm != "default")
1563 os << "\\usepackage" << "{" << rm << "}\n";
1566 // Helvetica, Bera Sans
1567 if (sf == "helvet" || sf == "berasans") {
1569 os << "\\usepackage[scaled=" << float(sfscale) / 100
1570 << "]{" << sf << "}\n";
1572 os << "\\usepackage{" << sf << "}\n";
1575 else if (sf == "avant")
1576 os << "\\usepackage{" << sf << "}\n";
1577 // Computer Modern, Latin Modern, CM Bright
1578 else if (sf != "default")
1579 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1581 // monospaced/typewriter
1582 // Courier, LuxiMono
1583 if (tt == "luximono" || tt == "beramono") {
1585 os << "\\usepackage[scaled=" << float(ttscale) / 100
1586 << "]{" << tt << "}\n";
1588 os << "\\usepackage{" << tt << "}\n";
1591 else if (tt == "courier" )
1592 os << "\\usepackage{" << tt << "}\n";
1593 // Computer Modern, Latin Modern, CM Bright
1594 else if (tt != "default")
1595 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1601 Encoding const & BufferParams::encoding() const
1603 if (inputenc == "auto" || inputenc == "default")
1604 return *(language->encoding());
1605 Encoding const * const enc =
1606 encodings.getFromLaTeXName(inputenc);
1609 lyxerr << "Unknown inputenc value `" << inputenc
1610 << "'. Using `auto' instead." << endl;
1611 return *(language->encoding());
1615 biblio::CiteEngine BufferParams::getEngine() const
1617 // FIXME the class should provide the numerical/
1618 // authoryear choice
1619 if (getTextClass().provides("natbib")
1620 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1621 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1622 return cite_engine_;
1626 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1628 cite_engine_ = cite_engine;