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 language_options << language->babel();
850 if (lyxrc.language_global_options)
851 clsoptions << language_options.str() << ',';
854 // the user-defined options
855 if (!options.empty()) {
856 clsoptions << options << ',';
859 string strOptions(clsoptions.str());
860 if (!strOptions.empty()) {
861 strOptions = rtrim(strOptions, ",");
863 os << '[' << from_utf8(strOptions) << ']';
866 os << '{' << from_ascii(tclass.latexname()) << "}\n";
868 // end of \documentclass defs
870 // font selection must be done before loading fontenc.sty
872 loadFonts(fontsRoman, fontsSans,
873 fontsTypewriter, fontsSC, fontsOSF,
874 fontsSansScale, fontsTypewriterScale);
875 if (!fonts.empty()) {
876 os << from_ascii(fonts);
879 if (fontsDefaultFamily != "default")
880 os << "\\renewcommand{\\familydefault}{\\"
881 << from_ascii(fontsDefaultFamily) << "}\n";
882 // this one is not per buffer
883 if (lyxrc.fontenc != "default") {
884 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
889 if (inputenc == "auto") {
890 string const doc_encoding =
891 language->encoding()->latexName();
893 // Create a list with all the input encodings used
895 std::set<string> encodings =
896 features.getEncodingSet(doc_encoding);
898 // thailatex does not use the inputenc package, but sets up
899 // babel directly for tis620-0 encoding, therefore we must
900 // not request inputenc for tis620-0 encoding
901 if (!encodings.empty() && doc_encoding != "tis620-0") {
902 os << "\\usepackage[";
903 std::set<string>::const_iterator it = encodings.begin();
904 std::set<string>::const_iterator const end = encodings.end();
906 os << from_ascii(*it);
909 for (; it != end; ++it)
910 os << ',' << from_ascii(*it);
911 if (doc_encoding != "tis620-0") {
912 if (!encodings.empty())
914 os << from_ascii(doc_encoding);
916 os << "]{inputenc}\n";
919 // utf8-plain is for XeTeX users (inputenc not desired)
920 } else if (inputenc != "default" && inputenc != "tis620-0" &&
921 inputenc != "ascii" && inputenc != "utf8-plain") {
922 os << "\\usepackage[" << from_ascii(inputenc)
927 // The encoding "armscii8" is only available when the package "armtex" is loaded.
928 // armscii8 is used for Armenian.
929 if (language->encoding()->latexName() == "armscii8" || inputenc == "armscii8") {
930 os << "\\usepackage{armtex}\n";
934 if (use_geometry || nonstandard_papersize) {
935 os << "\\usepackage{geometry}\n";
937 os << "\\geometry{verbose";
938 if (orientation == ORIENTATION_LANDSCAPE)
942 if (!paperwidth.empty())
944 << from_ascii(paperwidth);
945 if (!paperheight.empty())
946 os << ",paperheight="
947 << from_ascii(paperheight);
950 os << ",letterpaper";
955 case PAPER_USEXECUTIVE:
956 os << ",executivepaper";
977 // default papersize ie PAPER_DEFAULT
978 switch (lyxrc.default_papersize) {
979 case PAPER_DEFAULT: // keep compiler happy
981 os << ",letterpaper";
986 case PAPER_USEXECUTIVE:
987 os << ",executivepaper";
1007 if (!topmargin.empty())
1008 os << ",tmargin=" << from_ascii(Length(topmargin).asLatexString());
1009 if (!bottommargin.empty())
1010 os << ",bmargin=" << from_ascii(Length(bottommargin).asLatexString());
1011 if (!leftmargin.empty())
1012 os << ",lmargin=" << from_ascii(Length(leftmargin).asLatexString());
1013 if (!rightmargin.empty())
1014 os << ",rmargin=" << from_ascii(Length(rightmargin).asLatexString());
1015 if (!headheight.empty())
1016 os << ",headheight=" << from_ascii(Length(headheight).asLatexString());
1017 if (!headsep.empty())
1018 os << ",headsep=" << from_ascii(Length(headsep).asLatexString());
1019 if (!footskip.empty())
1020 os << ",footskip=" << from_ascii(Length(footskip).asLatexString());
1025 if (tokenPos(tclass.opt_pagestyle(),
1026 '|', pagestyle) >= 0) {
1027 if (pagestyle == "fancy") {
1028 os << "\\usepackage{fancyhdr}\n";
1031 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
1035 // Only if class has a ToC hierarchy
1036 if (tclass.hasTocLevels()) {
1037 if (secnumdepth != tclass.secnumdepth()) {
1038 os << "\\setcounter{secnumdepth}{"
1043 if (tocdepth != tclass.tocdepth()) {
1044 os << "\\setcounter{tocdepth}{"
1051 if (paragraph_separation) {
1052 switch (getDefSkip().kind()) {
1053 case VSpace::SMALLSKIP:
1054 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1056 case VSpace::MEDSKIP:
1057 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1059 case VSpace::BIGSKIP:
1060 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1062 case VSpace::LENGTH:
1063 os << "\\setlength{\\parskip}{"
1064 << from_utf8(getDefSkip().length().asLatexString())
1067 default: // should never happen // Then delete it.
1068 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1073 os << "\\setlength{\\parindent}{0pt}\n";
1077 // If we use jurabib, we have to call babel here.
1078 if (use_babel && features.isRequired("jurabib")) {
1079 os << from_ascii(babelCall(language_options.str()))
1081 << from_ascii(features.getBabelOptions());
1085 // Now insert the LyX specific LaTeX commands...
1087 // The optional packages;
1088 docstring lyxpreamble(from_ascii(features.getPackages()));
1090 // this might be useful...
1091 lyxpreamble += "\n\\makeatletter\n";
1093 // Some macros LyX will need
1094 docstring tmppreamble(from_ascii(features.getMacros()));
1096 if (!tmppreamble.empty()) {
1097 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1098 "LyX specific LaTeX commands.\n"
1099 + tmppreamble + '\n';
1102 // the text class specific preamble
1103 tmppreamble = features.getTClassPreamble();
1104 if (!tmppreamble.empty()) {
1105 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1106 "Textclass specific LaTeX commands.\n"
1107 + tmppreamble + '\n';
1110 /* the user-defined preamble */
1111 if (!preamble.empty()) {
1113 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1114 "User specified LaTeX commands.\n"
1115 + from_utf8(preamble) + '\n';
1118 // Itemize bullet settings need to be last in case the user
1119 // defines their own bullets that use a package included
1120 // in the user-defined preamble -- ARRae
1121 // Actually it has to be done much later than that
1122 // since some packages like frenchb make modifications
1123 // at \begin{document} time -- JMarc
1124 docstring bullets_def;
1125 for (int i = 0; i < 4; ++i) {
1126 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1127 if (bullets_def.empty())
1128 bullets_def += "\\AtBeginDocument{\n";
1129 bullets_def += " \\def\\labelitemi";
1131 // `i' is one less than the item to modify
1138 bullets_def += "ii";
1144 bullets_def += '{' +
1145 user_defined_bullet(i).getText()
1150 if (!bullets_def.empty())
1151 lyxpreamble += bullets_def + "}\n\n";
1153 // We try to load babel late, in case it interferes
1154 // with other packages.
1155 // Jurabib has to be called after babel, though.
1156 if (use_babel && !features.isRequired("jurabib")) {
1158 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1159 lyxpreamble += from_utf8(features.getBabelOptions());
1162 lyxpreamble += "\\makeatother\n";
1164 // dvipost settings come after everything else
1165 if (features.isAvailable("dvipost") && outputChanges) {
1168 "\\dvipost{osstart color push Red}\n"
1169 "\\dvipost{osend color pop}\n"
1170 "\\dvipost{cbstart color push Blue}\n"
1171 "\\dvipost{cbend color pop}\n";
1175 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1176 for (int j = 0; j != nlines; ++j) {
1185 void BufferParams::useClassDefaults()
1187 TextClass const & tclass = textclasslist[textclass];
1189 sides = tclass.sides();
1190 columns = tclass.columns();
1191 pagestyle = tclass.pagestyle();
1192 options = tclass.options();
1193 // Only if class has a ToC hierarchy
1194 if (tclass.hasTocLevels()) {
1195 secnumdepth = tclass.secnumdepth();
1196 tocdepth = tclass.tocdepth();
1201 bool BufferParams::hasClassDefaults() const
1203 TextClass const & tclass = textclasslist[textclass];
1205 return (sides == tclass.sides()
1206 && columns == tclass.columns()
1207 && pagestyle == tclass.pagestyle()
1208 && options == tclass.options()
1209 && secnumdepth == tclass.secnumdepth()
1210 && tocdepth == tclass.tocdepth());
1214 TextClass const & BufferParams::getTextClass() const
1216 return textclasslist[textclass];
1220 Font const BufferParams::getFont() const
1222 Font f = getTextClass().defaultfont();
1223 f.setLanguage(language);
1224 if (fontsDefaultFamily == "rmdefault")
1225 f.setFamily(Font::ROMAN_FAMILY);
1226 else if (fontsDefaultFamily == "sfdefault")
1227 f.setFamily(Font::SANS_FAMILY);
1228 else if (fontsDefaultFamily == "ttdefault")
1229 f.setFamily(Font::TYPEWRITER_FAMILY);
1234 void BufferParams::readPreamble(Lexer & lex)
1236 if (lex.getString() != "\\begin_preamble")
1237 lyxerr << "Error (BufferParams::readPreamble):"
1238 "consistency check failed." << endl;
1240 preamble = lex.getLongString("\\end_preamble");
1244 void BufferParams::readLanguage(Lexer & lex)
1246 if (!lex.next()) return;
1248 string const tmptok = lex.getString();
1250 // check if tmptok is part of tex_babel in tex-defs.h
1251 language = languages.getLanguage(tmptok);
1253 // Language tmptok was not found
1254 language = default_language;
1255 lyxerr << "Warning: Setting language `"
1256 << tmptok << "' to `" << language->lang()
1262 void BufferParams::readGraphicsDriver(Lexer & lex)
1264 if (!lex.next()) return;
1266 string const tmptok = lex.getString();
1267 // check if tmptok is part of tex_graphics in tex_defs.h
1270 string const test = tex_graphics[n++];
1272 if (test == tmptok) {
1273 graphicsDriver = tmptok;
1275 } else if (test == "") {
1277 "Warning: graphics driver `$$Token' not recognized!\n"
1278 " Setting graphics driver to `default'.\n");
1279 graphicsDriver = "default";
1286 void BufferParams::readBullets(Lexer & lex)
1288 if (!lex.next()) return;
1290 int const index = lex.getInteger();
1292 int temp_int = lex.getInteger();
1293 user_defined_bullet(index).setFont(temp_int);
1294 temp_bullet(index).setFont(temp_int);
1296 user_defined_bullet(index).setCharacter(temp_int);
1297 temp_bullet(index).setCharacter(temp_int);
1299 user_defined_bullet(index).setSize(temp_int);
1300 temp_bullet(index).setSize(temp_int);
1304 void BufferParams::readBulletsLaTeX(Lexer & lex)
1306 // The bullet class should be able to read this.
1307 if (!lex.next()) return;
1308 int const index = lex.getInteger();
1310 docstring const temp_str = lex.getDocString();
1312 user_defined_bullet(index).setText(temp_str);
1313 temp_bullet(index).setText(temp_str);
1317 string const BufferParams::paperSizeName() const
1319 char real_papersize = papersize;
1320 if (real_papersize == PAPER_DEFAULT)
1321 real_papersize = lyxrc.default_papersize;
1323 switch (real_papersize) {
1332 case PAPER_USEXECUTIVE:
1336 case PAPER_USLETTER:
1343 string const BufferParams::dvips_options() const
1348 && papersize == PAPER_CUSTOM
1349 && !lyxrc.print_paper_dimension_flag.empty()
1350 && !paperwidth.empty()
1351 && !paperheight.empty()) {
1352 // using a custom papersize
1353 result = lyxrc.print_paper_dimension_flag;
1354 result += ' ' + paperwidth;
1355 result += ',' + paperheight;
1357 string const paper_option = paperSizeName();
1358 if (paper_option != "letter" ||
1359 orientation != ORIENTATION_LANDSCAPE) {
1360 // dvips won't accept -t letter -t landscape.
1361 // In all other cases, include the paper size
1363 result = lyxrc.print_paper_flag;
1364 result += ' ' + paper_option;
1367 if (orientation == ORIENTATION_LANDSCAPE &&
1368 papersize != PAPER_CUSTOM)
1369 result += ' ' + lyxrc.print_landscape_flag;
1374 string const BufferParams::babelCall(string const & lang_opts) const
1376 string tmp = lyxrc.language_package;
1377 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1378 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1383 string const BufferParams::loadFonts(string const & rm,
1384 string const & sf, string const & tt,
1385 bool const & sc, bool const & osf,
1386 int const & sfscale, int const & ttscale) const
1388 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1389 several packages have been replaced by others, that might not
1390 be installed on every system. We have to take care for that
1391 (see psnfss.pdf). We try to support all psnfss fonts as well
1392 as the fonts that have become de facto standard in the LaTeX
1393 world (e.g. Latin Modern). We do not support obsolete fonts
1394 (like PSLatex). In general, it should be possible to mix any
1395 rm font with any sf or tt font, respectively. (JSpitzm)
1397 -- separate math fonts.
1400 if (rm == "default" && sf == "default" && tt == "default")
1407 // Computer Modern (must be explicitely selectable -- there might be classes
1408 // that define a different default font!
1410 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1411 // osf for Computer Modern needs eco.sty
1413 os << "\\usepackage{eco}\n";
1415 // Latin Modern Roman
1416 else if (rm == "lmodern")
1417 os << "\\usepackage{lmodern}\n";
1419 else if (rm == "ae") {
1420 // not needed when using OT1 font encoding.
1421 if (lyxrc.fontenc != "default")
1422 os << "\\usepackage{ae,aecompl}\n";
1425 else if (rm == "times") {
1426 // try to load the best available package
1427 if (LaTeXFeatures::isAvailable("mathptmx"))
1428 os << "\\usepackage{mathptmx}\n";
1429 else if (LaTeXFeatures::isAvailable("mathptm"))
1430 os << "\\usepackage{mathptm}\n";
1432 os << "\\usepackage{times}\n";
1435 else if (rm == "palatino") {
1436 // try to load the best available package
1437 if (LaTeXFeatures::isAvailable("mathpazo")) {
1438 os << "\\usepackage";
1444 // "osf" includes "sc"!
1448 os << "{mathpazo}\n";
1450 else if (LaTeXFeatures::isAvailable("mathpple"))
1451 os << "\\usepackage{mathpple}\n";
1453 os << "\\usepackage{palatino}\n";
1456 else if (rm == "utopia") {
1457 // fourier supersedes utopia.sty, but does
1458 // not work with OT1 encoding.
1459 if (LaTeXFeatures::isAvailable("fourier")
1460 && lyxrc.fontenc != "default") {
1461 os << "\\usepackage";
1472 os << "{fourier}\n";
1475 os << "\\usepackage{utopia}\n";
1477 // Bera (complete fontset)
1478 else if (rm == "bera" && sf == "default" && tt == "default")
1479 os << "\\usepackage{bera}\n";
1481 else if (rm != "default")
1482 os << "\\usepackage" << "{" << rm << "}\n";
1485 // Helvetica, Bera Sans
1486 if (sf == "helvet" || sf == "berasans") {
1488 os << "\\usepackage[scaled=" << float(sfscale) / 100
1489 << "]{" << sf << "}\n";
1491 os << "\\usepackage{" << sf << "}\n";
1494 else if (sf == "avant")
1495 os << "\\usepackage{" << sf << "}\n";
1496 // Computer Modern, Latin Modern, CM Bright
1497 else if (sf != "default")
1498 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1500 // monospaced/typewriter
1501 // Courier, LuxiMono
1502 if (tt == "luximono" || tt == "beramono") {
1504 os << "\\usepackage[scaled=" << float(ttscale) / 100
1505 << "]{" << tt << "}\n";
1507 os << "\\usepackage{" << tt << "}\n";
1510 else if (tt == "courier" )
1511 os << "\\usepackage{" << tt << "}\n";
1512 // Computer Modern, Latin Modern, CM Bright
1513 else if (tt != "default")
1514 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1520 Encoding const & BufferParams::encoding() const
1522 if (inputenc == "auto" || inputenc == "default")
1523 return *(language->encoding());
1524 Encoding const * const enc =
1525 encodings.getFromLaTeXName(inputenc);
1528 lyxerr << "Unknown inputenc value `" << inputenc
1529 << "'. Using `auto' instead." << endl;
1530 return *(language->encoding());
1534 biblio::CiteEngine BufferParams::getEngine() const
1536 // FIXME the class should provide the numerical/
1537 // authoryear choice
1538 if (getTextClass().provides("natbib")
1539 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1540 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1541 return cite_engine_;
1545 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1547 cite_engine_ = cite_engine;