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"
41 #include "support/lyxalgo.h" // for lyx::count
42 #include "support/convert.h"
43 #include "support/Translator.h"
45 #include <boost/array.hpp>
51 using std::istringstream;
53 using std::ostringstream;
56 using lyx::support::bformat;
57 using lyx::support::rtrim;
58 using lyx::support::tokenPos;
61 static char const * const string_paragraph_separation[] = {
66 static char const * const string_quotes_language[] = {
67 "english", "swedish", "german", "polish", "french", "danish", ""
71 static char const * const string_papersize[] = {
72 "default", "custom", "letterpaper", "executivepaper", "legalpaper",
73 "a3paper", "a4paper", "a5paper", "b3paper", "b4paper", "b5paper", ""
77 static char const * const string_orientation[] = {
78 "portrait", "landscape", ""
82 static char const * const string_footnotekinds[] = {
83 "footnote", "margin", "fig", "tab", "alg", "wide-fig", "wide-tab", ""
87 static char const * const tex_graphics[] = {
88 "default", "dvips", "dvitops", "emtex",
89 "ln", "oztex", "textures", "none", ""
98 // Paragraph separation
99 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
102 ParSepTranslator const init_parseptranslator()
104 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
105 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
110 ParSepTranslator const & parseptranslator()
112 static ParSepTranslator translator = init_parseptranslator();
118 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
121 QuotesLangTranslator const init_quoteslangtranslator()
123 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
124 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
125 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
126 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
127 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
128 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
133 QuotesLangTranslator const & quoteslangtranslator()
135 static QuotesLangTranslator translator = init_quoteslangtranslator();
141 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
144 PaperSizeTranslator const init_papersizetranslator()
146 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
147 translator.addPair(string_papersize[1], PAPER_CUSTOM);
148 translator.addPair(string_papersize[2], PAPER_USLETTER);
149 translator.addPair(string_papersize[3], PAPER_USLEGAL);
150 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
151 translator.addPair(string_papersize[5], PAPER_A3);
152 translator.addPair(string_papersize[6], PAPER_A4);
153 translator.addPair(string_papersize[7], PAPER_A5);
154 translator.addPair(string_papersize[8], PAPER_B3);
155 translator.addPair(string_papersize[9], PAPER_B4);
156 translator.addPair(string_papersize[10], PAPER_B5);
161 PaperSizeTranslator const & papersizetranslator()
163 static PaperSizeTranslator translator = init_papersizetranslator();
169 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
172 PaperOrientationTranslator const init_paperorientationtranslator()
174 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
175 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
180 PaperOrientationTranslator const & paperorientationtranslator()
182 static PaperOrientationTranslator translator = init_paperorientationtranslator();
188 typedef Translator<int, TextClass::PageSides> SidesTranslator;
191 SidesTranslator const init_sidestranslator()
193 SidesTranslator translator(1, TextClass::OneSide);
194 translator.addPair(2, TextClass::TwoSides);
199 SidesTranslator const & sidestranslator()
201 static SidesTranslator translator = init_sidestranslator();
207 typedef Translator<int, BufferParams::Package> PackageTranslator;
210 PackageTranslator const init_packagetranslator()
212 PackageTranslator translator(0, BufferParams::package_off);
213 translator.addPair(1, BufferParams::package_auto);
214 translator.addPair(2, BufferParams::package_on);
219 PackageTranslator const & packagetranslator()
221 static PackageTranslator translator = init_packagetranslator();
227 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
230 CiteEngineTranslator const init_citeenginetranslator()
232 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
233 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
234 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
235 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
240 CiteEngineTranslator const & citeenginetranslator()
242 static CiteEngineTranslator translator = init_citeenginetranslator();
248 typedef Translator<string, Spacing::Space> SpaceTranslator;
251 SpaceTranslator const init_spacetranslator()
253 SpaceTranslator translator("default", Spacing::Default);
254 translator.addPair("single", Spacing::Single);
255 translator.addPair("onehalf", Spacing::Onehalf);
256 translator.addPair("double", Spacing::Double);
257 translator.addPair("other", Spacing::Other);
262 SpaceTranslator const & spacetranslator()
264 static SpaceTranslator translator = init_spacetranslator();
269 textclass_type defaultTextclass()
271 // Initialize textclass to point to article. if `first' is
272 // true in the returned pair, then `second' is the textclass
273 // number; if it is false, second is 0. In both cases, second
275 return textclasslist.numberOfClass("article").second;
281 class BufferParams::Impl
286 AuthorList authorlist;
287 BranchList branchlist;
288 boost::array<Bullet, 4> temp_bullets;
289 boost::array<Bullet, 4> user_defined_bullets;
291 /** This is the amount of space used for paragraph_separation "skip",
292 * and for detached paragraphs in "indented" documents.
298 BufferParams::Impl::Impl()
299 : defskip(VSpace::MEDSKIP)
301 // set initial author
303 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
308 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
312 return new BufferParams::Impl(*ptr);
316 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
322 BufferParams::BufferParams()
323 : textclass(defaultTextclass()), pimpl_(new Impl)
325 paragraph_separation = PARSEP_INDENT;
326 quotes_language = InsetQuotes::EnglishQ;
327 fontsize = "default";
330 papersize = PAPER_DEFAULT;
331 orientation = ORIENTATION_PORTRAIT;
332 use_geometry = false;
333 use_amsmath = package_auto;
334 use_esint = package_auto;
335 cite_engine_ = biblio::ENGINE_BASIC;
336 use_bibtopic = false;
337 trackChanges = false;
338 outputChanges = false;
341 language = default_language;
342 fontsRoman = "default";
343 fontsSans = "default";
344 fontsTypewriter = "default";
345 fontsDefaultFamily = "default";
348 fontsSansScale = 100;
349 fontsTypewriterScale = 100;
351 graphicsDriver = "default";
352 sides = TextClass::OneSide;
354 pagestyle = "default";
356 for (int iter = 0; iter < 4; ++iter) {
357 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
358 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
363 BufferParams::~BufferParams()
367 docstring const BufferParams::B_(string const & l10n) const
369 BOOST_ASSERT(language);
370 return getMessages(language->code()).get(l10n);
374 AuthorList & BufferParams::authors()
376 return pimpl_->authorlist;
380 AuthorList const & BufferParams::authors() const
382 return pimpl_->authorlist;
386 BranchList & BufferParams::branchlist()
388 return pimpl_->branchlist;
392 BranchList const & BufferParams::branchlist() const
394 return pimpl_->branchlist;
398 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
400 BOOST_ASSERT(index < 4);
401 return pimpl_->temp_bullets[index];
405 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
407 BOOST_ASSERT(index < 4);
408 return pimpl_->temp_bullets[index];
412 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
414 BOOST_ASSERT(index < 4);
415 return pimpl_->user_defined_bullets[index];
419 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
421 BOOST_ASSERT(index < 4);
422 return pimpl_->user_defined_bullets[index];
426 Spacing & BufferParams::spacing()
428 return pimpl_->spacing;
432 Spacing const & BufferParams::spacing() const
434 return pimpl_->spacing;
438 VSpace const & BufferParams::getDefSkip() const
440 return pimpl_->defskip;
444 void BufferParams::setDefSkip(VSpace const & vs)
446 pimpl_->defskip = vs;
450 string const BufferParams::readToken(Lexer & lex, string const & token)
452 if (token == "\\textclass") {
454 string const classname = lex.getString();
455 pair<bool, lyx::textclass_type> pp =
456 textclasslist.numberOfClass(classname);
458 textclass = pp.second;
460 // if text class does not exist, try to load it from filepath
461 pp = textclasslist.addTextClass(classname, filepath);
463 textclass = pp.second;
465 textclass = defaultTextclass();
469 // FIXME: isTeXClassAvailable will try to load the layout file, but will
470 // fail because of the lack of path info. Warnings will be given although
471 // the layout file will be correctly loaded later.
472 if (!getTextClass().isTeXClassAvailable()) {
473 docstring const msg =
474 bformat(_("The layout file requested by this document,\n"
476 "is not usable. This is probably because a LaTeX\n"
477 "class or style file required by it is not\n"
478 "available. See the Customization documentation\n"
479 "for more information.\n"), from_utf8(classname));
480 frontend::Alert::warning(_("Document class not available"),
481 msg + _("LyX will not be able to produce output."));
483 } else if (token == "\\begin_preamble") {
485 } else if (token == "\\options") {
487 options = lex.getString();
488 } else if (token == "\\language") {
490 } else if (token == "\\inputencoding") {
492 } else if (token == "\\graphics") {
493 readGraphicsDriver(lex);
494 } else if (token == "\\font_roman") {
496 } else if (token == "\\font_sans") {
498 } else if (token == "\\font_typewriter") {
499 lex >> fontsTypewriter;
500 } else if (token == "\\font_default_family") {
501 lex >> fontsDefaultFamily;
502 } else if (token == "\\font_sc") {
504 } else if (token == "\\font_osf") {
506 } else if (token == "\\font_sf_scale") {
507 lex >> fontsSansScale;
508 } else if (token == "\\font_tt_scale") {
509 lex >> fontsTypewriterScale;
510 } else if (token == "\\paragraph_separation") {
513 paragraph_separation = parseptranslator().find(parsep);
514 } else if (token == "\\defskip") {
516 pimpl_->defskip = VSpace(lex.getString());
517 } else if (token == "\\quotes_language") {
520 quotes_language = quoteslangtranslator().find(quotes_lang);
521 } else if (token == "\\papersize") {
524 papersize = papersizetranslator().find(ppsize);
525 } else if (token == "\\use_geometry") {
527 } else if (token == "\\use_amsmath") {
530 use_amsmath = packagetranslator().find(use_ams);
531 } else if (token == "\\use_esint") {
534 use_esint = packagetranslator().find(useesint);
535 } else if (token == "\\cite_engine") {
538 cite_engine_ = citeenginetranslator().find(engine);
539 } else if (token == "\\use_bibtopic") {
541 } else if (token == "\\tracking_changes") {
543 } else if (token == "\\output_changes") {
544 lex >> outputChanges;
545 } else if (token == "\\branch") {
547 docstring branch = lex.getDocString();
548 branchlist().add(branch);
551 string const tok = lex.getString();
552 if (tok == "\\end_branch")
554 Branch * branch_ptr = branchlist().find(branch);
555 if (tok == "\\selected") {
558 branch_ptr->setSelected(lex.getInteger());
560 // not yet operational
561 if (tok == "\\color") {
563 string color = lex.getString();
565 branch_ptr->setColor(color);
566 // Update also the Color table:
568 color = lcolor.getX11Name(Color::background);
570 lcolor.setColor(to_utf8(branch), color);
574 } else if (token == "\\author") {
576 istringstream ss(lex.getString());
579 author_map.push_back(pimpl_->authorlist.record(a));
580 } else if (token == "\\paperorientation") {
583 orientation = paperorientationtranslator().find(orient);
584 } else if (token == "\\paperwidth") {
586 } else if (token == "\\paperheight") {
588 } else if (token == "\\leftmargin") {
590 } else if (token == "\\topmargin") {
592 } else if (token == "\\rightmargin") {
594 } else if (token == "\\bottommargin") {
596 } else if (token == "\\headheight") {
598 } else if (token == "\\headsep") {
600 } else if (token == "\\footskip") {
602 } else if (token == "\\paperfontsize") {
604 } else if (token == "\\papercolumns") {
606 } else if (token == "\\papersides") {
609 sides = sidestranslator().find(psides);
610 } else if (token == "\\paperpagestyle") {
612 } else if (token == "\\bullet") {
614 } else if (token == "\\bulletLaTeX") {
615 readBulletsLaTeX(lex);
616 } else if (token == "\\secnumdepth") {
618 } else if (token == "\\tocdepth") {
620 } else if (token == "\\spacing") {
624 if (nspacing == "other") {
627 spacing().set(spacetranslator().find(nspacing), tmp_val);
628 } else if (token == "\\float_placement") {
629 lex >> float_placement;
638 void BufferParams::writeFile(ostream & os) const
640 // The top of the file is written by the buffer.
641 // Prints out the buffer info into the .lyx file given by file
644 os << "\\textclass " << textclasslist[textclass].name() << '\n';
647 if (!preamble.empty()) {
648 // remove '\n' from the end of preamble
649 string const tmppreamble = rtrim(preamble, "\n");
650 os << "\\begin_preamble\n"
652 << "\n\\end_preamble\n";
656 if (!options.empty()) {
657 os << "\\options " << options << '\n';
660 // then the text parameters
661 if (language != ignore_language)
662 os << "\\language " << language->lang() << '\n';
663 os << "\\inputencoding " << inputenc
664 << "\n\\font_roman " << fontsRoman
665 << "\n\\font_sans " << fontsSans
666 << "\n\\font_typewriter " << fontsTypewriter
667 << "\n\\font_default_family " << fontsDefaultFamily
668 << "\n\\font_sc " << convert<string>(fontsSC)
669 << "\n\\font_osf " << convert<string>(fontsOSF)
670 << "\n\\font_sf_scale " << fontsSansScale
671 << "\n\\font_tt_scale " << fontsTypewriterScale
672 << "\n\\graphics " << graphicsDriver << '\n';
674 if (!float_placement.empty()) {
675 os << "\\float_placement " << float_placement << '\n';
677 os << "\\paperfontsize " << fontsize << '\n';
679 spacing().writeFile(os);
681 os << "\\papersize " << string_papersize[papersize]
682 << "\n\\use_geometry " << convert<string>(use_geometry)
683 << "\n\\use_amsmath " << use_amsmath
684 << "\n\\use_esint " << use_esint
685 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
686 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
687 << "\n\\paperorientation " << string_orientation[orientation]
690 BranchList::const_iterator it = branchlist().begin();
691 BranchList::const_iterator end = branchlist().end();
692 for (; it != end; ++it) {
693 os << "\\branch " << to_utf8(it->getBranch())
694 << "\n\\selected " << it->getSelected()
695 << "\n\\color " << lyx::X11hexname(it->getColor())
700 if (!paperwidth.empty())
701 os << "\\paperwidth "
702 << VSpace(paperwidth).asLyXCommand() << '\n';
703 if (!paperheight.empty())
704 os << "\\paperheight "
705 << VSpace(paperheight).asLyXCommand() << '\n';
706 if (!leftmargin.empty())
707 os << "\\leftmargin "
708 << VSpace(leftmargin).asLyXCommand() << '\n';
709 if (!topmargin.empty())
711 << VSpace(topmargin).asLyXCommand() << '\n';
712 if (!rightmargin.empty())
713 os << "\\rightmargin "
714 << VSpace(rightmargin).asLyXCommand() << '\n';
715 if (!bottommargin.empty())
716 os << "\\bottommargin "
717 << VSpace(bottommargin).asLyXCommand() << '\n';
718 if (!headheight.empty())
719 os << "\\headheight "
720 << VSpace(headheight).asLyXCommand() << '\n';
721 if (!headsep.empty())
723 << VSpace(headsep).asLyXCommand() << '\n';
724 if (!footskip.empty())
726 << VSpace(footskip).asLyXCommand() << '\n';
727 os << "\\secnumdepth " << secnumdepth
728 << "\n\\tocdepth " << tocdepth
729 << "\n\\paragraph_separation "
730 << string_paragraph_separation[paragraph_separation]
731 << "\n\\defskip " << getDefSkip().asLyXCommand()
732 << "\n\\quotes_language "
733 << string_quotes_language[quotes_language]
734 << "\n\\papercolumns " << columns
735 << "\n\\papersides " << sides
736 << "\n\\paperpagestyle " << pagestyle << '\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 os << "\\author " << a_it->second << "\n";
765 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
766 TexRow & texrow) const
768 os << "\\documentclass";
770 TextClass const & tclass = getTextClass();
772 ostringstream clsoptions; // the document class options.
774 if (tokenPos(tclass.opt_fontsize(),
775 '|', fontsize) >= 0) {
776 // only write if existing in list (and not default)
777 clsoptions << fontsize << "pt,";
780 // custom, A3, B3 and B4 paper sizes need geometry
781 bool nonstandard_papersize = papersize == PAPER_B3
782 || papersize == PAPER_B4
783 || papersize == PAPER_A3
784 || papersize == PAPER_CUSTOM;
789 clsoptions << "a4paper,";
792 clsoptions << "letterpaper,";
795 clsoptions << "a5paper,";
798 clsoptions << "b5paper,";
800 case PAPER_USEXECUTIVE:
801 clsoptions << "executivepaper,";
804 clsoptions << "legalpaper,";
816 if (sides != tclass.sides()) {
818 case TextClass::OneSide:
819 clsoptions << "oneside,";
821 case TextClass::TwoSides:
822 clsoptions << "twoside,";
828 if (columns != tclass.columns()) {
830 clsoptions << "twocolumn,";
832 clsoptions << "onecolumn,";
836 && orientation == ORIENTATION_LANDSCAPE)
837 clsoptions << "landscape,";
839 // language should be a parameter to \documentclass
840 if (language->babel() == "hebrew"
841 && default_language->babel() != "hebrew")
842 // This seems necessary
843 features.useLanguage(default_language);
845 ostringstream language_options;
846 bool const use_babel = features.useBabel();
848 language_options << features.getLanguages();
849 if (!language->babel().empty()) {
850 if (!language_options.str().empty())
851 language_options << ',';
852 language_options << language->babel();
854 if (lyxrc.language_global_options)
855 clsoptions << language_options.str() << ',';
858 // the user-defined options
859 if (!options.empty()) {
860 clsoptions << options << ',';
863 string strOptions(clsoptions.str());
864 if (!strOptions.empty()) {
865 strOptions = rtrim(strOptions, ",");
867 os << '[' << from_utf8(strOptions) << ']';
870 os << '{' << from_ascii(tclass.latexname()) << "}\n";
872 // end of \documentclass defs
874 // font selection must be done before loading fontenc.sty
876 loadFonts(fontsRoman, fontsSans,
877 fontsTypewriter, fontsSC, fontsOSF,
878 fontsSansScale, fontsTypewriterScale);
879 if (!fonts.empty()) {
880 os << from_ascii(fonts);
883 if (fontsDefaultFamily != "default")
884 os << "\\renewcommand{\\familydefault}{\\"
885 << from_ascii(fontsDefaultFamily) << "}\n";
886 // this one is not per buffer
887 if (lyxrc.fontenc != "default") {
888 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
893 if (inputenc == "auto") {
894 string const doc_encoding =
895 language->encoding()->latexName();
897 // Create a list with all the input encodings used
899 std::set<string> encodings =
900 features.getEncodingSet(doc_encoding);
902 // thailatex does not use the inputenc package, but sets up
903 // babel directly for tis620-0 encoding, therefore we must
904 // not request inputenc for tis620-0 encoding
905 if (!encodings.empty() && doc_encoding != "tis620-0") {
906 os << "\\usepackage[";
907 std::set<string>::const_iterator it = encodings.begin();
908 std::set<string>::const_iterator const end = encodings.end();
910 os << from_ascii(*it);
913 for (; it != end; ++it)
914 os << ',' << from_ascii(*it);
915 if (doc_encoding != "tis620-0") {
916 if (!encodings.empty())
918 os << from_ascii(doc_encoding);
920 os << "]{inputenc}\n";
923 // utf8-plain is for XeTeX users (inputenc not desired)
924 } else if (inputenc != "default" && inputenc != "tis620-0" &&
925 inputenc != "ascii" && inputenc != "utf8-plain") {
926 os << "\\usepackage[" << from_ascii(inputenc)
931 // The encoding "armscii8" is only available when the package "armtex" is loaded.
932 // armscii8 is used for Armenian.
933 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
934 os << "\\usepackage{armtex}\n";
938 if (use_geometry || nonstandard_papersize) {
939 os << "\\usepackage{geometry}\n";
941 os << "\\geometry{verbose";
942 if (orientation == ORIENTATION_LANDSCAPE)
946 if (!paperwidth.empty())
948 << from_ascii(paperwidth);
949 if (!paperheight.empty())
950 os << ",paperheight="
951 << from_ascii(paperheight);
954 os << ",letterpaper";
959 case PAPER_USEXECUTIVE:
960 os << ",executivepaper";
981 // default papersize ie PAPER_DEFAULT
982 switch (lyxrc.default_papersize) {
983 case PAPER_DEFAULT: // keep compiler happy
985 os << ",letterpaper";
990 case PAPER_USEXECUTIVE:
991 os << ",executivepaper";
1011 if (!topmargin.empty())
1012 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1013 if (!bottommargin.empty())
1014 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1015 if (!leftmargin.empty())
1016 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1017 if (!rightmargin.empty())
1018 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1019 if (!headheight.empty())
1020 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1021 if (!headsep.empty())
1022 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1023 if (!footskip.empty())
1024 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1029 if (tokenPos(tclass.opt_pagestyle(),
1030 '|', pagestyle) >= 0) {
1031 if (pagestyle == "fancy") {
1032 os << "\\usepackage{fancyhdr}\n";
1035 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1039 // Only if class has a ToC hierarchy
1040 if (tclass.hasTocLevels()) {
1041 if (secnumdepth != tclass.secnumdepth()) {
1042 os << "\\setcounter{secnumdepth}{"
1047 if (tocdepth != tclass.tocdepth()) {
1048 os << "\\setcounter{tocdepth}{"
1055 if (paragraph_separation) {
1056 switch (getDefSkip().kind()) {
1057 case VSpace::SMALLSKIP:
1058 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1060 case VSpace::MEDSKIP:
1061 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1063 case VSpace::BIGSKIP:
1064 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1066 case VSpace::LENGTH:
1067 os << "\\setlength{\\parskip}{"
1068 << from_utf8(getDefSkip().length().asLatexString())
1071 default: // should never happen // Then delete it.
1072 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1077 os << "\\setlength{\\parindent}{0pt}\n";
1081 // If we use jurabib, we have to call babel here.
1082 if (use_babel && features.isRequired("jurabib")) {
1083 os << from_ascii(babelCall(language_options.str()))
1085 << from_ascii(features.getBabelOptions());
1089 // Now insert the LyX specific LaTeX commands...
1091 // The optional packages;
1092 docstring lyxpreamble(from_ascii(features.getPackages()));
1094 // this might be useful...
1095 lyxpreamble += "\n\\makeatletter\n";
1097 // Some macros LyX will need
1098 docstring tmppreamble(from_ascii(features.getMacros()));
1100 if (!tmppreamble.empty()) {
1101 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1102 "LyX specific LaTeX commands.\n"
1103 + tmppreamble + '\n';
1106 // the text class specific preamble
1107 tmppreamble = features.getTClassPreamble();
1108 if (!tmppreamble.empty()) {
1109 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1110 "Textclass specific LaTeX commands.\n"
1111 + tmppreamble + '\n';
1114 /* the user-defined preamble */
1115 if (!preamble.empty()) {
1117 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1118 "User specified LaTeX commands.\n"
1119 + from_utf8(preamble) + '\n';
1122 // Itemize bullet settings need to be last in case the user
1123 // defines their own bullets that use a package included
1124 // in the user-defined preamble -- ARRae
1125 // Actually it has to be done much later than that
1126 // since some packages like frenchb make modifications
1127 // at \begin{document} time -- JMarc
1128 docstring bullets_def;
1129 for (int i = 0; i < 4; ++i) {
1130 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1131 if (bullets_def.empty())
1132 bullets_def += "\\AtBeginDocument{\n";
1133 bullets_def += " \\def\\labelitemi";
1135 // `i' is one less than the item to modify
1142 bullets_def += "ii";
1148 bullets_def += '{' +
1149 user_defined_bullet(i).getText()
1154 if (!bullets_def.empty())
1155 lyxpreamble += bullets_def + "}\n\n";
1157 // We try to load babel late, in case it interferes
1158 // with other packages.
1159 // Jurabib has to be called after babel, though.
1160 if (use_babel && !features.isRequired("jurabib")) {
1162 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1163 lyxpreamble += from_utf8(features.getBabelOptions());
1166 lyxpreamble += "\\makeatother\n";
1168 // dvipost settings come after everything else
1169 if (features.isAvailable("dvipost") && outputChanges) {
1172 "\\dvipost{osstart color push Red}\n"
1173 "\\dvipost{osend color pop}\n"
1174 "\\dvipost{cbstart color push Blue}\n"
1175 "\\dvipost{cbend color pop}\n";
1179 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1180 for (int j = 0; j != nlines; ++j) {
1189 void BufferParams::useClassDefaults()
1191 TextClass const & tclass = textclasslist[textclass];
1193 sides = tclass.sides();
1194 columns = tclass.columns();
1195 pagestyle = tclass.pagestyle();
1196 options = tclass.options();
1197 // Only if class has a ToC hierarchy
1198 if (tclass.hasTocLevels()) {
1199 secnumdepth = tclass.secnumdepth();
1200 tocdepth = tclass.tocdepth();
1205 bool BufferParams::hasClassDefaults() const
1207 TextClass const & tclass = textclasslist[textclass];
1209 return (sides == tclass.sides()
1210 && columns == tclass.columns()
1211 && pagestyle == tclass.pagestyle()
1212 && options == tclass.options()
1213 && secnumdepth == tclass.secnumdepth()
1214 && tocdepth == tclass.tocdepth());
1218 TextClass const & BufferParams::getTextClass() const
1220 return textclasslist[textclass];
1224 Font const BufferParams::getFont() const
1226 Font f = getTextClass().defaultfont();
1227 f.setLanguage(language);
1228 if (fontsDefaultFamily == "rmdefault")
1229 f.setFamily(Font::ROMAN_FAMILY);
1230 else if (fontsDefaultFamily == "sfdefault")
1231 f.setFamily(Font::SANS_FAMILY);
1232 else if (fontsDefaultFamily == "ttdefault")
1233 f.setFamily(Font::TYPEWRITER_FAMILY);
1238 void BufferParams::readPreamble(Lexer & lex)
1240 if (lex.getString() != "\\begin_preamble")
1241 lyxerr << "Error (BufferParams::readPreamble):"
1242 "consistency check failed." << endl;
1244 preamble = lex.getLongString("\\end_preamble");
1248 void BufferParams::readLanguage(Lexer & lex)
1250 if (!lex.next()) return;
1252 string const tmptok = lex.getString();
1254 // check if tmptok is part of tex_babel in tex-defs.h
1255 language = languages.getLanguage(tmptok);
1257 // Language tmptok was not found
1258 language = default_language;
1259 lyxerr << "Warning: Setting language `"
1260 << tmptok << "' to `" << language->lang()
1266 void BufferParams::readGraphicsDriver(Lexer & lex)
1268 if (!lex.next()) return;
1270 string const tmptok = lex.getString();
1271 // check if tmptok is part of tex_graphics in tex_defs.h
1274 string const test = tex_graphics[n++];
1276 if (test == tmptok) {
1277 graphicsDriver = tmptok;
1279 } else if (test == "") {
1281 "Warning: graphics driver `$$Token' not recognized!\n"
1282 " Setting graphics driver to `default'.\n");
1283 graphicsDriver = "default";
1290 void BufferParams::readBullets(Lexer & lex)
1292 if (!lex.next()) return;
1294 int const index = lex.getInteger();
1296 int temp_int = lex.getInteger();
1297 user_defined_bullet(index).setFont(temp_int);
1298 temp_bullet(index).setFont(temp_int);
1300 user_defined_bullet(index).setCharacter(temp_int);
1301 temp_bullet(index).setCharacter(temp_int);
1303 user_defined_bullet(index).setSize(temp_int);
1304 temp_bullet(index).setSize(temp_int);
1308 void BufferParams::readBulletsLaTeX(Lexer & lex)
1310 // The bullet class should be able to read this.
1311 if (!lex.next()) return;
1312 int const index = lex.getInteger();
1314 docstring const temp_str = lex.getDocString();
1316 user_defined_bullet(index).setText(temp_str);
1317 temp_bullet(index).setText(temp_str);
1321 string const BufferParams::paperSizeName() const
1323 char real_papersize = papersize;
1324 if (real_papersize == PAPER_DEFAULT)
1325 real_papersize = lyxrc.default_papersize;
1327 switch (real_papersize) {
1336 case PAPER_USEXECUTIVE:
1340 case PAPER_USLETTER:
1347 string const BufferParams::dvips_options() const
1352 && papersize == PAPER_CUSTOM
1353 && !lyxrc.print_paper_dimension_flag.empty()
1354 && !paperwidth.empty()
1355 && !paperheight.empty()) {
1356 // using a custom papersize
1357 result = lyxrc.print_paper_dimension_flag;
1358 result += ' ' + paperwidth;
1359 result += ',' + paperheight;
1361 string const paper_option = paperSizeName();
1362 if (paper_option != "letter" ||
1363 orientation != ORIENTATION_LANDSCAPE) {
1364 // dvips won't accept -t letter -t landscape.
1365 // In all other cases, include the paper size
1367 result = lyxrc.print_paper_flag;
1368 result += ' ' + paper_option;
1371 if (orientation == ORIENTATION_LANDSCAPE &&
1372 papersize != PAPER_CUSTOM)
1373 result += ' ' + lyxrc.print_landscape_flag;
1378 string const BufferParams::babelCall(string const & lang_opts) const
1380 string tmp = lyxrc.language_package;
1381 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1382 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1387 string const BufferParams::loadFonts(string const & rm,
1388 string const & sf, string const & tt,
1389 bool const & sc, bool const & osf,
1390 int const & sfscale, int const & ttscale) const
1392 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1393 several packages have been replaced by others, that might not
1394 be installed on every system. We have to take care for that
1395 (see psnfss.pdf). We try to support all psnfss fonts as well
1396 as the fonts that have become de facto standard in the LaTeX
1397 world (e.g. Latin Modern). We do not support obsolete fonts
1398 (like PSLatex). In general, it should be possible to mix any
1399 rm font with any sf or tt font, respectively. (JSpitzm)
1401 -- separate math fonts.
1404 if (rm == "default" && sf == "default" && tt == "default")
1411 // Computer Modern (must be explicitely selectable -- there might be classes
1412 // that define a different default font!
1414 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1415 // osf for Computer Modern needs eco.sty
1417 os << "\\usepackage{eco}\n";
1419 // Latin Modern Roman
1420 else if (rm == "lmodern")
1421 os << "\\usepackage{lmodern}\n";
1423 else if (rm == "ae") {
1424 // not needed when using OT1 font encoding.
1425 if (lyxrc.fontenc != "default")
1426 os << "\\usepackage{ae,aecompl}\n";
1429 else if (rm == "times") {
1430 // try to load the best available package
1431 if (LaTeXFeatures::isAvailable("mathptmx"))
1432 os << "\\usepackage{mathptmx}\n";
1433 else if (LaTeXFeatures::isAvailable("mathptm"))
1434 os << "\\usepackage{mathptm}\n";
1436 os << "\\usepackage{times}\n";
1439 else if (rm == "palatino") {
1440 // try to load the best available package
1441 if (LaTeXFeatures::isAvailable("mathpazo")) {
1442 os << "\\usepackage";
1448 // "osf" includes "sc"!
1452 os << "{mathpazo}\n";
1454 else if (LaTeXFeatures::isAvailable("mathpple"))
1455 os << "\\usepackage{mathpple}\n";
1457 os << "\\usepackage{palatino}\n";
1460 else if (rm == "utopia") {
1461 // fourier supersedes utopia.sty, but does
1462 // not work with OT1 encoding.
1463 if (LaTeXFeatures::isAvailable("fourier")
1464 && lyxrc.fontenc != "default") {
1465 os << "\\usepackage";
1476 os << "{fourier}\n";
1479 os << "\\usepackage{utopia}\n";
1481 // Bera (complete fontset)
1482 else if (rm == "bera" && sf == "default" && tt == "default")
1483 os << "\\usepackage{bera}\n";
1485 else if (rm != "default")
1486 os << "\\usepackage" << "{" << rm << "}\n";
1489 // Helvetica, Bera Sans
1490 if (sf == "helvet" || sf == "berasans") {
1492 os << "\\usepackage[scaled=" << float(sfscale) / 100
1493 << "]{" << sf << "}\n";
1495 os << "\\usepackage{" << sf << "}\n";
1498 else if (sf == "avant")
1499 os << "\\usepackage{" << sf << "}\n";
1500 // Computer Modern, Latin Modern, CM Bright
1501 else if (sf != "default")
1502 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1504 // monospaced/typewriter
1505 // Courier, LuxiMono
1506 if (tt == "luximono" || tt == "beramono") {
1508 os << "\\usepackage[scaled=" << float(ttscale) / 100
1509 << "]{" << tt << "}\n";
1511 os << "\\usepackage{" << tt << "}\n";
1514 else if (tt == "courier" )
1515 os << "\\usepackage{" << tt << "}\n";
1516 // Computer Modern, Latin Modern, CM Bright
1517 else if (tt != "default")
1518 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1524 Encoding const & BufferParams::encoding() const
1526 if (inputenc == "auto" || inputenc == "default")
1527 return *(language->encoding());
1528 Encoding const * const enc =
1529 encodings.getFromLaTeXName(inputenc);
1532 lyxerr << "Unknown inputenc value `" << inputenc
1533 << "'. Using `auto' instead." << endl;
1534 return *(language->encoding());
1538 biblio::CiteEngine BufferParams::getEngine() const
1540 // FIXME the class should provide the numerical/
1541 // authoryear choice
1542 if (getTextClass().provides("natbib")
1543 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1544 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1545 return cite_engine_;
1549 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1551 cite_engine_ = cite_engine;