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"
32 #include "LyXTextClassList.h"
33 #include "OutputParams.h"
34 #include "tex-strings.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>
52 using support::bformat;
54 using support::tokenPos;
58 using std::istringstream;
60 using std::ostringstream;
63 namespace Alert = lyx::frontend::Alert;
69 // Paragraph separation
70 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
73 ParSepTranslator const init_parseptranslator()
75 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
76 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
81 ParSepTranslator const & parseptranslator()
83 static ParSepTranslator translator = init_parseptranslator();
89 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
92 QuotesLangTranslator const init_quoteslangtranslator()
94 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
95 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
96 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
97 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
98 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
99 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
104 QuotesLangTranslator const & quoteslangtranslator()
106 static QuotesLangTranslator translator = init_quoteslangtranslator();
112 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
115 PaperSizeTranslator const init_papersizetranslator()
117 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
118 translator.addPair(string_papersize[1], PAPER_CUSTOM);
119 translator.addPair(string_papersize[2], PAPER_USLETTER);
120 translator.addPair(string_papersize[3], PAPER_USLEGAL);
121 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
122 translator.addPair(string_papersize[5], PAPER_A3);
123 translator.addPair(string_papersize[6], PAPER_A4);
124 translator.addPair(string_papersize[7], PAPER_A5);
125 translator.addPair(string_papersize[8], PAPER_B3);
126 translator.addPair(string_papersize[9], PAPER_B4);
127 translator.addPair(string_papersize[10], PAPER_B5);
132 PaperSizeTranslator const & papersizetranslator()
134 static PaperSizeTranslator translator = init_papersizetranslator();
140 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
143 PaperOrientationTranslator const init_paperorientationtranslator()
145 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
146 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
151 PaperOrientationTranslator const & paperorientationtranslator()
153 static PaperOrientationTranslator translator = init_paperorientationtranslator();
159 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
162 SidesTranslator const init_sidestranslator()
164 SidesTranslator translator(1, LyXTextClass::OneSide);
165 translator.addPair(2, LyXTextClass::TwoSides);
170 SidesTranslator const & sidestranslator()
172 static SidesTranslator translator = init_sidestranslator();
178 typedef Translator<int, BufferParams::Package> PackageTranslator;
181 PackageTranslator const init_packagetranslator()
183 PackageTranslator translator(0, BufferParams::package_off);
184 translator.addPair(1, BufferParams::package_auto);
185 translator.addPair(2, BufferParams::package_on);
190 PackageTranslator const & packagetranslator()
192 static PackageTranslator translator = init_packagetranslator();
198 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
201 CiteEngineTranslator const init_citeenginetranslator()
203 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
204 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
205 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
206 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
211 CiteEngineTranslator const & citeenginetranslator()
213 static CiteEngineTranslator translator = init_citeenginetranslator();
219 typedef Translator<string, Spacing::Space> SpaceTranslator;
222 SpaceTranslator const init_spacetranslator()
224 SpaceTranslator translator("default", Spacing::Default);
225 translator.addPair("single", Spacing::Single);
226 translator.addPair("onehalf", Spacing::Onehalf);
227 translator.addPair("double", Spacing::Double);
228 translator.addPair("other", Spacing::Other);
233 SpaceTranslator const & spacetranslator()
235 static SpaceTranslator translator = init_spacetranslator();
240 textclass_type defaultTextclass()
242 // Initialize textclass to point to article. if `first' is
243 // true in the returned pair, then `second' is the textclass
244 // number; if it is false, second is 0. In both cases, second
246 return textclasslist.numberOfClass("article").second;
252 class BufferParams::Impl
257 AuthorList authorlist;
258 BranchList branchlist;
259 boost::array<Bullet, 4> temp_bullets;
260 boost::array<Bullet, 4> user_defined_bullets;
262 /** This is the amount of space used for paragraph_separation "skip",
263 * and for detached paragraphs in "indented" documents.
269 BufferParams::Impl::Impl()
270 : defskip(VSpace::MEDSKIP)
272 // set initial author
274 authorlist.record(Author(from_utf8(lyxrc.user_name), from_utf8(lyxrc.user_email)));
279 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
283 return new BufferParams::Impl(*ptr);
287 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
293 BufferParams::BufferParams()
294 : textclass(defaultTextclass()), pimpl_(new Impl)
296 paragraph_separation = PARSEP_INDENT;
297 quotes_language = InsetQuotes::EnglishQ;
298 fontsize = "default";
301 papersize = PAPER_DEFAULT;
302 orientation = ORIENTATION_PORTRAIT;
303 use_geometry = false;
304 use_amsmath = package_auto;
305 use_esint = package_auto;
306 cite_engine_ = biblio::ENGINE_BASIC;
307 use_bibtopic = false;
308 trackChanges = false;
309 outputChanges = false;
312 language = default_language;
313 fontsRoman = "default";
314 fontsSans = "default";
315 fontsTypewriter = "default";
316 fontsDefaultFamily = "default";
319 fontsSansScale = 100;
320 fontsTypewriterScale = 100;
322 graphicsDriver = "default";
323 sides = LyXTextClass::OneSide;
325 pagestyle = "default";
327 for (int iter = 0; iter < 4; ++iter) {
328 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
329 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
334 BufferParams::~BufferParams()
338 AuthorList & BufferParams::authors()
340 return pimpl_->authorlist;
344 AuthorList const & BufferParams::authors() const
346 return pimpl_->authorlist;
350 BranchList & BufferParams::branchlist()
352 return pimpl_->branchlist;
356 BranchList const & BufferParams::branchlist() const
358 return pimpl_->branchlist;
362 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
364 BOOST_ASSERT(index < 4);
365 return pimpl_->temp_bullets[index];
369 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
371 BOOST_ASSERT(index < 4);
372 return pimpl_->temp_bullets[index];
376 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
378 BOOST_ASSERT(index < 4);
379 return pimpl_->user_defined_bullets[index];
383 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
385 BOOST_ASSERT(index < 4);
386 return pimpl_->user_defined_bullets[index];
390 Spacing & BufferParams::spacing()
392 return pimpl_->spacing;
396 Spacing const & BufferParams::spacing() const
398 return pimpl_->spacing;
402 VSpace const & BufferParams::getDefSkip() const
404 return pimpl_->defskip;
408 void BufferParams::setDefSkip(VSpace const & vs)
410 pimpl_->defskip = vs;
414 string const BufferParams::readToken(Lexer & lex, string const & token)
416 if (token == "\\textclass") {
418 string const classname = lex.getString();
419 pair<bool, lyx::textclass_type> pp =
420 textclasslist.numberOfClass(classname);
422 textclass = pp.second;
424 // if text class does not exist, try to load it from filepath
425 pp = textclasslist.addTextClass(classname, filepath);
427 textclass = pp.second;
429 textclass = defaultTextclass();
433 // FIXME: isTeXClassAvailable will try to load the layout file, but will
434 // fail because of the lack of path info. Warnings will be given although
435 // the layout file will be correctly loaded later.
436 if (!getLyXTextClass().isTeXClassAvailable()) {
437 docstring const msg =
438 bformat(_("The layout file requested by this document,\n"
440 "is not usable. This is probably because a LaTeX\n"
441 "class or style file required by it is not\n"
442 "available. See the Customization documentation\n"
443 "for more information.\n"), from_utf8(classname));
444 Alert::warning(_("Document class not available"),
445 msg + _("LyX will not be able to produce output."));
447 } else if (token == "\\begin_preamble") {
449 } else if (token == "\\options") {
451 options = lex.getString();
452 } else if (token == "\\language") {
454 } else if (token == "\\inputencoding") {
456 } else if (token == "\\graphics") {
457 readGraphicsDriver(lex);
458 } else if (token == "\\font_roman") {
460 } else if (token == "\\font_sans") {
462 } else if (token == "\\font_typewriter") {
463 lex >> fontsTypewriter;
464 } else if (token == "\\font_default_family") {
465 lex >> fontsDefaultFamily;
466 } else if (token == "\\font_sc") {
468 } else if (token == "\\font_osf") {
470 } else if (token == "\\font_sf_scale") {
471 lex >> fontsSansScale;
472 } else if (token == "\\font_tt_scale") {
473 lex >> fontsTypewriterScale;
474 } else if (token == "\\paragraph_separation") {
477 paragraph_separation = parseptranslator().find(parsep);
478 } else if (token == "\\defskip") {
480 pimpl_->defskip = VSpace(lex.getString());
481 } else if (token == "\\quotes_language") {
484 quotes_language = quoteslangtranslator().find(quotes_lang);
485 } else if (token == "\\papersize") {
488 papersize = papersizetranslator().find(ppsize);
489 } else if (token == "\\use_geometry") {
491 } else if (token == "\\use_amsmath") {
494 use_amsmath = packagetranslator().find(use_ams);
495 } else if (token == "\\use_esint") {
498 use_esint = packagetranslator().find(useesint);
499 } else if (token == "\\cite_engine") {
502 cite_engine_ = citeenginetranslator().find(engine);
503 } else if (token == "\\use_bibtopic") {
505 } else if (token == "\\tracking_changes") {
507 } else if (token == "\\output_changes") {
508 lex >> outputChanges;
509 } else if (token == "\\branch") {
511 docstring branch = lex.getDocString();
512 branchlist().add(branch);
515 string const tok = lex.getString();
516 if (tok == "\\end_branch")
518 Branch * branch_ptr = branchlist().find(branch);
519 if (tok == "\\selected") {
522 branch_ptr->setSelected(lex.getInteger());
524 // not yet operational
525 if (tok == "\\color") {
527 string color = lex.getString();
529 branch_ptr->setColor(color);
530 // Update also the LColor table:
532 color = lcolor.getX11Name(LColor::background);
534 lcolor.setColor(to_utf8(branch), color);
538 } else if (token == "\\author") {
540 istringstream ss(lex.getString());
543 author_map.push_back(pimpl_->authorlist.record(a));
544 } else if (token == "\\paperorientation") {
547 orientation = paperorientationtranslator().find(orient);
548 } else if (token == "\\paperwidth") {
550 } else if (token == "\\paperheight") {
552 } else if (token == "\\leftmargin") {
554 } else if (token == "\\topmargin") {
556 } else if (token == "\\rightmargin") {
558 } else if (token == "\\bottommargin") {
560 } else if (token == "\\headheight") {
562 } else if (token == "\\headsep") {
564 } else if (token == "\\footskip") {
566 } else if (token == "\\paperfontsize") {
568 } else if (token == "\\papercolumns") {
570 } else if (token == "\\papersides") {
573 sides = sidestranslator().find(psides);
574 } else if (token == "\\paperpagestyle") {
576 } else if (token == "\\bullet") {
578 } else if (token == "\\bulletLaTeX") {
579 readBulletsLaTeX(lex);
580 } else if (token == "\\secnumdepth") {
582 } else if (token == "\\tocdepth") {
584 } else if (token == "\\spacing") {
588 if (nspacing == "other") {
591 spacing().set(spacetranslator().find(nspacing), tmp_val);
592 } else if (token == "\\float_placement") {
593 lex >> float_placement;
602 void BufferParams::writeFile(ostream & os) const
604 // The top of the file is written by the buffer.
605 // Prints out the buffer info into the .lyx file given by file
608 os << "\\textclass " << textclasslist[textclass].name() << '\n';
611 if (!preamble.empty()) {
612 // remove '\n' from the end of preamble
613 string const tmppreamble = rtrim(preamble, "\n");
614 os << "\\begin_preamble\n"
616 << "\n\\end_preamble\n";
620 if (!options.empty()) {
621 os << "\\options " << options << '\n';
624 // then the text parameters
625 if (language != ignore_language)
626 os << "\\language " << language->lang() << '\n';
627 os << "\\inputencoding " << inputenc
628 << "\n\\font_roman " << fontsRoman
629 << "\n\\font_sans " << fontsSans
630 << "\n\\font_typewriter " << fontsTypewriter
631 << "\n\\font_default_family " << fontsDefaultFamily
632 << "\n\\font_sc " << convert<string>(fontsSC)
633 << "\n\\font_osf " << convert<string>(fontsOSF)
634 << "\n\\font_sf_scale " << fontsSansScale
635 << "\n\\font_tt_scale " << fontsTypewriterScale
636 << "\n\\graphics " << graphicsDriver << '\n';
638 if (!float_placement.empty()) {
639 os << "\\float_placement " << float_placement << '\n';
641 os << "\\paperfontsize " << fontsize << '\n';
643 spacing().writeFile(os);
645 os << "\\papersize " << string_papersize[papersize]
646 << "\n\\use_geometry " << convert<string>(use_geometry)
647 << "\n\\use_amsmath " << use_amsmath
648 << "\n\\use_esint " << use_esint
649 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
650 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
651 << "\n\\paperorientation " << string_orientation[orientation]
654 BranchList::const_iterator it = branchlist().begin();
655 BranchList::const_iterator end = branchlist().end();
656 for (; it != end; ++it) {
657 os << "\\branch " << to_utf8(it->getBranch())
658 << "\n\\selected " << it->getSelected()
659 << "\n\\color " << lyx::X11hexname(it->getColor())
664 if (!paperwidth.empty())
665 os << "\\paperwidth "
666 << VSpace(paperwidth).asLyXCommand() << '\n';
667 if (!paperheight.empty())
668 os << "\\paperheight "
669 << VSpace(paperheight).asLyXCommand() << '\n';
670 if (!leftmargin.empty())
671 os << "\\leftmargin "
672 << VSpace(leftmargin).asLyXCommand() << '\n';
673 if (!topmargin.empty())
675 << VSpace(topmargin).asLyXCommand() << '\n';
676 if (!rightmargin.empty())
677 os << "\\rightmargin "
678 << VSpace(rightmargin).asLyXCommand() << '\n';
679 if (!bottommargin.empty())
680 os << "\\bottommargin "
681 << VSpace(bottommargin).asLyXCommand() << '\n';
682 if (!headheight.empty())
683 os << "\\headheight "
684 << VSpace(headheight).asLyXCommand() << '\n';
685 if (!headsep.empty())
687 << VSpace(headsep).asLyXCommand() << '\n';
688 if (!footskip.empty())
690 << VSpace(footskip).asLyXCommand() << '\n';
691 os << "\\secnumdepth " << secnumdepth
692 << "\n\\tocdepth " << tocdepth
693 << "\n\\paragraph_separation "
694 << string_paragraph_separation[paragraph_separation]
695 << "\n\\defskip " << getDefSkip().asLyXCommand()
696 << "\n\\quotes_language "
697 << string_quotes_language[quotes_language]
698 << "\n\\papercolumns " << columns
699 << "\n\\papersides " << sides
700 << "\n\\paperpagestyle " << pagestyle << '\n';
701 for (int i = 0; i < 4; ++i) {
702 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
703 if (user_defined_bullet(i).getFont() != -1) {
704 os << "\\bullet " << i << " "
705 << user_defined_bullet(i).getFont() << " "
706 << user_defined_bullet(i).getCharacter() << " "
707 << user_defined_bullet(i).getSize() << "\n";
711 os << "\\bulletLaTeX " << i << " \""
712 << lyx::to_ascii(user_defined_bullet(i).getText())
718 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
719 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
721 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
722 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
723 for (; a_it != a_end; ++a_it) {
724 os << "\\author " << a_it->second << "\n";
729 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
730 TexRow & texrow) const
732 os << "\\documentclass";
734 LyXTextClass const & tclass = getLyXTextClass();
736 ostringstream clsoptions; // the document class options.
738 if (tokenPos(tclass.opt_fontsize(),
739 '|', fontsize) >= 0) {
740 // only write if existing in list (and not default)
741 clsoptions << fontsize << "pt,";
744 // custom, A3, B3 and B4 paper sizes need geometry
745 bool nonstandard_papersize = papersize == PAPER_B3
746 || papersize == PAPER_B4
747 || papersize == PAPER_A3
748 || papersize == PAPER_CUSTOM;
753 clsoptions << "a4paper,";
756 clsoptions << "letterpaper,";
759 clsoptions << "a5paper,";
762 clsoptions << "b5paper,";
764 case PAPER_USEXECUTIVE:
765 clsoptions << "executivepaper,";
768 clsoptions << "legalpaper,";
780 if (sides != tclass.sides()) {
782 case LyXTextClass::OneSide:
783 clsoptions << "oneside,";
785 case LyXTextClass::TwoSides:
786 clsoptions << "twoside,";
792 if (columns != tclass.columns()) {
794 clsoptions << "twocolumn,";
796 clsoptions << "onecolumn,";
800 && orientation == ORIENTATION_LANDSCAPE)
801 clsoptions << "landscape,";
803 // language should be a parameter to \documentclass
804 if (language->babel() == "hebrew"
805 && default_language->babel() != "hebrew")
806 // This seems necessary
807 features.useLanguage(default_language);
809 ostringstream language_options;
810 bool const use_babel = features.useBabel();
812 language_options << features.getLanguages();
813 language_options << language->babel();
814 if (lyxrc.language_global_options)
815 clsoptions << language_options.str() << ',';
818 // the user-defined options
819 if (!options.empty()) {
820 clsoptions << options << ',';
823 string strOptions(clsoptions.str());
824 if (!strOptions.empty()) {
825 strOptions = rtrim(strOptions, ",");
827 os << '[' << from_utf8(strOptions) << ']';
830 os << '{' << from_ascii(tclass.latexname()) << "}\n";
832 // end of \documentclass defs
834 // font selection must be done before loading fontenc.sty
836 loadFonts(fontsRoman, fontsSans,
837 fontsTypewriter, fontsSC, fontsOSF,
838 fontsSansScale, fontsTypewriterScale);
839 if (!fonts.empty()) {
840 os << from_ascii(fonts);
843 if (fontsDefaultFamily != "default")
844 os << "\\renewcommand{\\familydefault}{\\"
845 << from_ascii(fontsDefaultFamily) << "}\n";
846 // this one is not per buffer
847 if (lyxrc.fontenc != "default") {
848 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
853 if (inputenc == "auto") {
854 string const doc_encoding =
855 language->encoding()->latexName();
857 // Create a list with all the input encodings used
859 std::set<string> encodings =
860 features.getEncodingSet(doc_encoding);
862 // thailatex does not use the inputenc package, but sets up
863 // babel directly for tis620-0 encoding, therefore we must
864 // not request inputenc for tis620-0 encoding
865 if (!encodings.empty() || doc_encoding != "tis620-0") {
866 os << "\\usepackage[";
867 std::set<string>::const_iterator it = encodings.begin();
868 std::set<string>::const_iterator const end = encodings.end();
870 os << from_ascii(*it);
873 for (; it != end; ++it)
874 os << ',' << from_ascii(*it);
875 if (doc_encoding != "tis620-0") {
876 if (!encodings.empty())
878 os << from_ascii(doc_encoding);
880 os << "]{inputenc}\n";
883 } else if (inputenc != "default" && inputenc != "tis620-0" &&
884 inputenc != "ascii") {
885 os << "\\usepackage[" << from_ascii(inputenc)
890 if (use_geometry || nonstandard_papersize) {
891 os << "\\usepackage{geometry}\n";
893 os << "\\geometry{verbose";
894 if (orientation == ORIENTATION_LANDSCAPE)
898 if (!paperwidth.empty())
900 << from_ascii(paperwidth);
901 if (!paperheight.empty())
902 os << ",paperheight="
903 << from_ascii(paperheight);
906 os << ",letterpaper";
911 case PAPER_USEXECUTIVE:
912 os << ",executivepaper";
933 // default papersize ie PAPER_DEFAULT
934 switch (lyxrc.default_papersize) {
935 case PAPER_DEFAULT: // keep compiler happy
937 os << ",letterpaper";
942 case PAPER_USEXECUTIVE:
943 os << ",executivepaper";
963 if (!topmargin.empty())
964 os << ",tmargin=" << from_ascii(LyXLength(topmargin).asLatexString());
965 if (!bottommargin.empty())
966 os << ",bmargin=" << from_ascii(LyXLength(bottommargin).asLatexString());
967 if (!leftmargin.empty())
968 os << ",lmargin=" << from_ascii(LyXLength(leftmargin).asLatexString());
969 if (!rightmargin.empty())
970 os << ",rmargin=" << from_ascii(LyXLength(rightmargin).asLatexString());
971 if (!headheight.empty())
972 os << ",headheight=" << from_ascii(LyXLength(headheight).asLatexString());
973 if (!headsep.empty())
974 os << ",headsep=" << from_ascii(LyXLength(headsep).asLatexString());
975 if (!footskip.empty())
976 os << ",footskip=" << from_ascii(LyXLength(footskip).asLatexString());
981 if (tokenPos(tclass.opt_pagestyle(),
982 '|', pagestyle) >= 0) {
983 if (pagestyle == "fancy") {
984 os << "\\usepackage{fancyhdr}\n";
987 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
991 // Only if class has a ToC hierarchy
992 if (tclass.hasTocLevels()) {
993 if (secnumdepth != tclass.secnumdepth()) {
994 os << "\\setcounter{secnumdepth}{"
999 if (tocdepth != tclass.tocdepth()) {
1000 os << "\\setcounter{tocdepth}{"
1007 if (paragraph_separation) {
1008 switch (getDefSkip().kind()) {
1009 case VSpace::SMALLSKIP:
1010 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1012 case VSpace::MEDSKIP:
1013 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1015 case VSpace::BIGSKIP:
1016 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1018 case VSpace::LENGTH:
1019 os << "\\setlength{\\parskip}{"
1020 << from_utf8(getDefSkip().length().asLatexString())
1023 default: // should never happen // Then delete it.
1024 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1029 os << "\\setlength{\\parindent}{0pt}\n";
1033 // If we use jurabib, we have to call babel here.
1034 if (use_babel && features.isRequired("jurabib")) {
1035 os << from_ascii(babelCall(language_options.str()))
1037 << from_ascii(features.getBabelOptions());
1041 // Now insert the LyX specific LaTeX commands...
1043 // The optional packages;
1044 docstring lyxpreamble(from_ascii(features.getPackages()));
1046 // this might be useful...
1047 lyxpreamble += "\n\\makeatletter\n";
1049 // Some macros LyX will need
1050 docstring tmppreamble(from_ascii(features.getMacros()));
1052 if (!tmppreamble.empty()) {
1053 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1054 "LyX specific LaTeX commands.\n"
1055 + tmppreamble + '\n';
1058 // the text class specific preamble
1059 tmppreamble = features.getTClassPreamble();
1060 if (!tmppreamble.empty()) {
1061 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1062 "Textclass specific LaTeX commands.\n"
1063 + tmppreamble + '\n';
1066 /* the user-defined preamble */
1067 if (!preamble.empty()) {
1069 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1070 "User specified LaTeX commands.\n"
1071 + from_utf8(preamble) + '\n';
1074 // Itemize bullet settings need to be last in case the user
1075 // defines their own bullets that use a package included
1076 // in the user-defined preamble -- ARRae
1077 // Actually it has to be done much later than that
1078 // since some packages like frenchb make modifications
1079 // at \begin{document} time -- JMarc
1080 docstring bullets_def;
1081 for (int i = 0; i < 4; ++i) {
1082 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1083 if (bullets_def.empty())
1084 bullets_def += "\\AtBeginDocument{\n";
1085 bullets_def += " \\def\\labelitemi";
1087 // `i' is one less than the item to modify
1094 bullets_def += "ii";
1100 bullets_def += '{' +
1101 user_defined_bullet(i).getText()
1106 if (!bullets_def.empty())
1107 lyxpreamble += bullets_def + "}\n\n";
1109 // We try to load babel late, in case it interferes
1110 // with other packages.
1111 // Jurabib has to be called after babel, though.
1112 if (use_babel && !features.isRequired("jurabib")) {
1114 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1115 lyxpreamble += from_utf8(features.getBabelOptions());
1118 lyxpreamble += "\\makeatother\n";
1120 // dvipost settings come after everything else
1121 if (features.isAvailable("dvipost") && outputChanges) {
1124 "\\dvipost{osstart color push Red}\n"
1125 "\\dvipost{osend color pop}\n"
1126 "\\dvipost{cbstart color push Blue}\n"
1127 "\\dvipost{cbend color pop}\n";
1131 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1132 for (int j = 0; j != nlines; ++j) {
1141 void BufferParams::useClassDefaults()
1143 LyXTextClass const & tclass = textclasslist[textclass];
1145 sides = tclass.sides();
1146 columns = tclass.columns();
1147 pagestyle = tclass.pagestyle();
1148 options = tclass.options();
1149 // Only if class has a ToC hierarchy
1150 if (tclass.hasTocLevels()) {
1151 secnumdepth = tclass.secnumdepth();
1152 tocdepth = tclass.tocdepth();
1157 bool BufferParams::hasClassDefaults() const
1159 LyXTextClass const & tclass = textclasslist[textclass];
1161 return (sides == tclass.sides()
1162 && columns == tclass.columns()
1163 && pagestyle == tclass.pagestyle()
1164 && options == tclass.options()
1165 && secnumdepth == tclass.secnumdepth()
1166 && tocdepth == tclass.tocdepth());
1170 LyXTextClass const & BufferParams::getLyXTextClass() const
1172 return textclasslist[textclass];
1176 LyXFont const BufferParams::getFont() const
1178 LyXFont f = getLyXTextClass().defaultfont();
1179 f.setLanguage(language);
1180 if (fontsDefaultFamily == "rmdefault")
1181 f.setFamily(LyXFont::ROMAN_FAMILY);
1182 else if (fontsDefaultFamily == "sfdefault")
1183 f.setFamily(LyXFont::SANS_FAMILY);
1184 else if (fontsDefaultFamily == "ttdefault")
1185 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1190 void BufferParams::readPreamble(Lexer & lex)
1192 if (lex.getString() != "\\begin_preamble")
1193 lyxerr << "Error (BufferParams::readPreamble):"
1194 "consistency check failed." << endl;
1196 preamble = lex.getLongString("\\end_preamble");
1200 void BufferParams::readLanguage(Lexer & lex)
1202 if (!lex.next()) return;
1204 string const tmptok = lex.getString();
1206 // check if tmptok is part of tex_babel in tex-defs.h
1207 language = languages.getLanguage(tmptok);
1209 // Language tmptok was not found
1210 language = default_language;
1211 lyxerr << "Warning: Setting language `"
1212 << tmptok << "' to `" << language->lang()
1218 void BufferParams::readGraphicsDriver(Lexer & lex)
1220 if (!lex.next()) return;
1222 string const tmptok = lex.getString();
1223 // check if tmptok is part of tex_graphics in tex_defs.h
1226 string const test = tex_graphics[n++];
1228 if (test == tmptok) {
1229 graphicsDriver = tmptok;
1231 } else if (test == "") {
1233 "Warning: graphics driver `$$Token' not recognized!\n"
1234 " Setting graphics driver to `default'.\n");
1235 graphicsDriver = "default";
1242 void BufferParams::readBullets(Lexer & lex)
1244 if (!lex.next()) return;
1246 int const index = lex.getInteger();
1248 int temp_int = lex.getInteger();
1249 user_defined_bullet(index).setFont(temp_int);
1250 temp_bullet(index).setFont(temp_int);
1252 user_defined_bullet(index).setCharacter(temp_int);
1253 temp_bullet(index).setCharacter(temp_int);
1255 user_defined_bullet(index).setSize(temp_int);
1256 temp_bullet(index).setSize(temp_int);
1260 void BufferParams::readBulletsLaTeX(Lexer & lex)
1262 // The bullet class should be able to read this.
1263 if (!lex.next()) return;
1264 int const index = lex.getInteger();
1266 docstring const temp_str = lex.getDocString();
1268 user_defined_bullet(index).setText(temp_str);
1269 temp_bullet(index).setText(temp_str);
1273 string const BufferParams::paperSizeName() const
1275 char real_papersize = papersize;
1276 if (real_papersize == PAPER_DEFAULT)
1277 real_papersize = lyxrc.default_papersize;
1279 switch (real_papersize) {
1288 case PAPER_USEXECUTIVE:
1292 case PAPER_USLETTER:
1299 string const BufferParams::dvips_options() const
1304 && papersize == PAPER_CUSTOM
1305 && !lyxrc.print_paper_dimension_flag.empty()
1306 && !paperwidth.empty()
1307 && !paperheight.empty()) {
1308 // using a custom papersize
1309 result = lyxrc.print_paper_dimension_flag;
1310 result += ' ' + paperwidth;
1311 result += ',' + paperheight;
1313 string const paper_option = paperSizeName();
1314 if (paper_option != "letter" ||
1315 orientation != ORIENTATION_LANDSCAPE) {
1316 // dvips won't accept -t letter -t landscape.
1317 // In all other cases, include the paper size
1319 result = lyxrc.print_paper_flag;
1320 result += ' ' + paper_option;
1323 if (orientation == ORIENTATION_LANDSCAPE &&
1324 papersize != PAPER_CUSTOM)
1325 result += ' ' + lyxrc.print_landscape_flag;
1330 string const BufferParams::babelCall(string const & lang_opts) const
1332 string tmp = lyxrc.language_package;
1333 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1334 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1339 string const BufferParams::loadFonts(string const & rm,
1340 string const & sf, string const & tt,
1341 bool const & sc, bool const & osf,
1342 int const & sfscale, int const & ttscale) const
1344 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1345 several packages have been replaced by others, that might not
1346 be installed on every system. We have to take care for that
1347 (see psnfss.pdf). We try to support all psnfss fonts as well
1348 as the fonts that have become de facto standard in the LaTeX
1349 world (e.g. Latin Modern). We do not support obsolete fonts
1350 (like PSLatex). In general, it should be possible to mix any
1351 rm font with any sf or tt font, respectively. (JSpitzm)
1353 -- separate math fonts.
1356 if (rm == "default" && sf == "default" && tt == "default")
1363 // Computer Modern (must be explicitely selectable -- there might be classes
1364 // that define a different default font!
1366 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1367 // osf for Computer Modern needs eco.sty
1369 os << "\\usepackage{eco}\n";
1371 // Latin Modern Roman
1372 else if (rm == "lmodern")
1373 os << "\\usepackage{lmodern}\n";
1375 else if (rm == "ae") {
1376 // not needed when using OT1 font encoding.
1377 if (lyxrc.fontenc != "default")
1378 os << "\\usepackage{ae,aecompl}\n";
1381 else if (rm == "times") {
1382 // try to load the best available package
1383 if (LaTeXFeatures::isAvailable("mathptmx"))
1384 os << "\\usepackage{mathptmx}\n";
1385 else if (LaTeXFeatures::isAvailable("mathptm"))
1386 os << "\\usepackage{mathptm}\n";
1388 os << "\\usepackage{times}\n";
1391 else if (rm == "palatino") {
1392 // try to load the best available package
1393 if (LaTeXFeatures::isAvailable("mathpazo")) {
1394 os << "\\usepackage";
1400 // "osf" includes "sc"!
1404 os << "{mathpazo}\n";
1406 else if (LaTeXFeatures::isAvailable("mathpple"))
1407 os << "\\usepackage{mathpple}\n";
1409 os << "\\usepackage{palatino}\n";
1412 else if (rm == "utopia") {
1413 // fourier supersedes utopia.sty, but does
1414 // not work with OT1 encoding.
1415 if (LaTeXFeatures::isAvailable("fourier")
1416 && lyxrc.fontenc != "default") {
1417 os << "\\usepackage";
1428 os << "{fourier}\n";
1431 os << "\\usepackage{utopia}\n";
1433 // Bera (complete fontset)
1434 else if (rm == "bera" && sf == "default" && tt == "default")
1435 os << "\\usepackage{bera}\n";
1437 else if (rm != "default")
1438 os << "\\usepackage" << "{" << rm << "}\n";
1441 // Helvetica, Bera Sans
1442 if (sf == "helvet" || sf == "berasans") {
1444 os << "\\usepackage[scaled=" << float(sfscale) / 100
1445 << "]{" << sf << "}\n";
1447 os << "\\usepackage{" << sf << "}\n";
1450 else if (sf == "avant")
1451 os << "\\usepackage{" << sf << "}\n";
1452 // Computer Modern, Latin Modern, CM Bright
1453 else if (sf != "default")
1454 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1456 // monospaced/typewriter
1457 // Courier, LuxiMono
1458 if (tt == "luximono" || tt == "beramono") {
1460 os << "\\usepackage[scaled=" << float(ttscale) / 100
1461 << "]{" << tt << "}\n";
1463 os << "\\usepackage{" << tt << "}\n";
1466 else if (tt == "courier" )
1467 os << "\\usepackage{" << tt << "}\n";
1468 // Computer Modern, Latin Modern, CM Bright
1469 else if (tt != "default")
1470 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1476 Encoding const & BufferParams::encoding() const
1478 if (inputenc == "auto" || inputenc == "default")
1479 return *(language->encoding());
1480 Encoding const * const enc =
1481 encodings.getFromLaTeXName(inputenc);
1484 lyxerr << "Unknown inputenc value `" << inputenc
1485 << "'. Using `auto' instead." << endl;
1486 return *(language->encoding());
1490 biblio::CiteEngine BufferParams::getEngine() const
1492 // FIXME the class should provide the numerical/
1493 // authoryear choice
1494 if (getLyXTextClass().provides("natbib")
1495 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1496 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1497 return cite_engine_;
1501 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1503 cite_engine_ = cite_engine;