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(LyXLex & 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 document uses a missing "
439 "TeX class \"%1$s\".\n"), from_utf8(classname));
440 Alert::warning(_("Document class not available"),
441 msg + _("LyX will not be able to produce output."));
443 } else if (token == "\\begin_preamble") {
445 } else if (token == "\\options") {
447 options = lex.getString();
448 } else if (token == "\\language") {
450 } else if (token == "\\inputencoding") {
452 } else if (token == "\\graphics") {
453 readGraphicsDriver(lex);
454 } else if (token == "\\font_roman") {
456 } else if (token == "\\font_sans") {
458 } else if (token == "\\font_typewriter") {
459 lex >> fontsTypewriter;
460 } else if (token == "\\font_default_family") {
461 lex >> fontsDefaultFamily;
462 } else if (token == "\\font_sc") {
464 } else if (token == "\\font_osf") {
466 } else if (token == "\\font_sf_scale") {
467 lex >> fontsSansScale;
468 } else if (token == "\\font_tt_scale") {
469 lex >> fontsTypewriterScale;
470 } else if (token == "\\paragraph_separation") {
473 paragraph_separation = parseptranslator().find(parsep);
474 } else if (token == "\\defskip") {
476 pimpl_->defskip = VSpace(lex.getString());
477 } else if (token == "\\quotes_language") {
480 quotes_language = quoteslangtranslator().find(quotes_lang);
481 } else if (token == "\\papersize") {
484 papersize = papersizetranslator().find(ppsize);
485 } else if (token == "\\use_geometry") {
487 } else if (token == "\\use_amsmath") {
490 use_amsmath = packagetranslator().find(use_ams);
491 } else if (token == "\\use_esint") {
494 use_esint = packagetranslator().find(useesint);
495 } else if (token == "\\cite_engine") {
498 cite_engine_ = citeenginetranslator().find(engine);
499 } else if (token == "\\use_bibtopic") {
501 } else if (token == "\\tracking_changes") {
503 } else if (token == "\\output_changes") {
504 lex >> outputChanges;
505 } else if (token == "\\branch") {
507 docstring branch = lex.getDocString();
508 branchlist().add(branch);
511 string const tok = lex.getString();
512 if (tok == "\\end_branch")
514 Branch * branch_ptr = branchlist().find(branch);
515 if (tok == "\\selected") {
518 branch_ptr->setSelected(lex.getInteger());
520 // not yet operational
521 if (tok == "\\color") {
523 string color = lex.getString();
525 branch_ptr->setColor(color);
526 // Update also the LColor table:
528 color = lcolor.getX11Name(LColor::background);
530 lcolor.setColor(to_utf8(branch), color);
534 } else if (token == "\\author") {
536 istringstream ss(lex.getString());
539 author_map.push_back(pimpl_->authorlist.record(a));
540 } else if (token == "\\paperorientation") {
543 orientation = paperorientationtranslator().find(orient);
544 } else if (token == "\\paperwidth") {
546 } else if (token == "\\paperheight") {
548 } else if (token == "\\leftmargin") {
550 } else if (token == "\\topmargin") {
552 } else if (token == "\\rightmargin") {
554 } else if (token == "\\bottommargin") {
556 } else if (token == "\\headheight") {
558 } else if (token == "\\headsep") {
560 } else if (token == "\\footskip") {
562 } else if (token == "\\paperfontsize") {
564 } else if (token == "\\papercolumns") {
566 } else if (token == "\\papersides") {
569 sides = sidestranslator().find(psides);
570 } else if (token == "\\paperpagestyle") {
572 } else if (token == "\\bullet") {
574 } else if (token == "\\bulletLaTeX") {
575 readBulletsLaTeX(lex);
576 } else if (token == "\\secnumdepth") {
578 } else if (token == "\\tocdepth") {
580 } else if (token == "\\spacing") {
584 if (nspacing == "other") {
587 spacing().set(spacetranslator().find(nspacing), tmp_val);
588 } else if (token == "\\float_placement") {
589 lex >> float_placement;
598 void BufferParams::writeFile(ostream & os) const
600 // The top of the file is written by the buffer.
601 // Prints out the buffer info into the .lyx file given by file
604 os << "\\textclass " << textclasslist[textclass].name() << '\n';
607 if (!preamble.empty()) {
608 // remove '\n' from the end of preamble
609 string const tmppreamble = rtrim(preamble, "\n");
610 os << "\\begin_preamble\n"
612 << "\n\\end_preamble\n";
616 if (!options.empty()) {
617 os << "\\options " << options << '\n';
620 // then the text parameters
621 if (language != ignore_language)
622 os << "\\language " << language->lang() << '\n';
623 os << "\\inputencoding " << inputenc
624 << "\n\\font_roman " << fontsRoman
625 << "\n\\font_sans " << fontsSans
626 << "\n\\font_typewriter " << fontsTypewriter
627 << "\n\\font_default_family " << fontsDefaultFamily
628 << "\n\\font_sc " << convert<string>(fontsSC)
629 << "\n\\font_osf " << convert<string>(fontsOSF)
630 << "\n\\font_sf_scale " << fontsSansScale
631 << "\n\\font_tt_scale " << fontsTypewriterScale
632 << "\n\\graphics " << graphicsDriver << '\n';
634 if (!float_placement.empty()) {
635 os << "\\float_placement " << float_placement << '\n';
637 os << "\\paperfontsize " << fontsize << '\n';
639 spacing().writeFile(os);
641 os << "\\papersize " << string_papersize[papersize]
642 << "\n\\use_geometry " << convert<string>(use_geometry)
643 << "\n\\use_amsmath " << use_amsmath
644 << "\n\\use_esint " << use_esint
645 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine_)
646 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
647 << "\n\\paperorientation " << string_orientation[orientation]
650 BranchList::const_iterator it = branchlist().begin();
651 BranchList::const_iterator end = branchlist().end();
652 for (; it != end; ++it) {
653 os << "\\branch " << to_utf8(it->getBranch())
654 << "\n\\selected " << it->getSelected()
655 << "\n\\color " << lyx::X11hexname(it->getColor())
660 if (!paperwidth.empty())
661 os << "\\paperwidth "
662 << VSpace(paperwidth).asLyXCommand() << '\n';
663 if (!paperheight.empty())
664 os << "\\paperheight "
665 << VSpace(paperheight).asLyXCommand() << '\n';
666 if (!leftmargin.empty())
667 os << "\\leftmargin "
668 << VSpace(leftmargin).asLyXCommand() << '\n';
669 if (!topmargin.empty())
671 << VSpace(topmargin).asLyXCommand() << '\n';
672 if (!rightmargin.empty())
673 os << "\\rightmargin "
674 << VSpace(rightmargin).asLyXCommand() << '\n';
675 if (!bottommargin.empty())
676 os << "\\bottommargin "
677 << VSpace(bottommargin).asLyXCommand() << '\n';
678 if (!headheight.empty())
679 os << "\\headheight "
680 << VSpace(headheight).asLyXCommand() << '\n';
681 if (!headsep.empty())
683 << VSpace(headsep).asLyXCommand() << '\n';
684 if (!footskip.empty())
686 << VSpace(footskip).asLyXCommand() << '\n';
687 os << "\\secnumdepth " << secnumdepth
688 << "\n\\tocdepth " << tocdepth
689 << "\n\\paragraph_separation "
690 << string_paragraph_separation[paragraph_separation]
691 << "\n\\defskip " << getDefSkip().asLyXCommand()
692 << "\n\\quotes_language "
693 << string_quotes_language[quotes_language]
694 << "\n\\papercolumns " << columns
695 << "\n\\papersides " << sides
696 << "\n\\paperpagestyle " << pagestyle << '\n';
697 for (int i = 0; i < 4; ++i) {
698 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
699 if (user_defined_bullet(i).getFont() != -1) {
700 os << "\\bullet " << i << " "
701 << user_defined_bullet(i).getFont() << " "
702 << user_defined_bullet(i).getCharacter() << " "
703 << user_defined_bullet(i).getSize() << "\n";
707 os << "\\bulletLaTeX " << i << " \""
708 << lyx::to_ascii(user_defined_bullet(i).getText())
714 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
715 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
717 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
718 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
719 for (; a_it != a_end; ++a_it) {
720 os << "\\author " << a_it->second << "\n";
725 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
726 TexRow & texrow) const
728 os << "\\documentclass";
730 LyXTextClass const & tclass = getLyXTextClass();
732 ostringstream clsoptions; // the document class options.
734 if (tokenPos(tclass.opt_fontsize(),
735 '|', fontsize) >= 0) {
736 // only write if existing in list (and not default)
737 clsoptions << fontsize << "pt,";
740 // custom, A3, B3 and B4 paper sizes need geometry
741 bool nonstandard_papersize = papersize == PAPER_B3
742 || papersize == PAPER_B4
743 || papersize == PAPER_A3
744 || papersize == PAPER_CUSTOM;
749 clsoptions << "a4paper,";
752 clsoptions << "letterpaper,";
755 clsoptions << "a5paper,";
758 clsoptions << "b5paper,";
760 case PAPER_USEXECUTIVE:
761 clsoptions << "executivepaper,";
764 clsoptions << "legalpaper,";
776 if (sides != tclass.sides()) {
778 case LyXTextClass::OneSide:
779 clsoptions << "oneside,";
781 case LyXTextClass::TwoSides:
782 clsoptions << "twoside,";
788 if (columns != tclass.columns()) {
790 clsoptions << "twocolumn,";
792 clsoptions << "onecolumn,";
796 && orientation == ORIENTATION_LANDSCAPE)
797 clsoptions << "landscape,";
799 // language should be a parameter to \documentclass
800 if (language->babel() == "hebrew"
801 && default_language->babel() != "hebrew")
802 // This seems necessary
803 features.useLanguage(default_language);
805 ostringstream language_options;
806 bool const use_babel = features.useBabel();
808 language_options << features.getLanguages();
809 language_options << language->babel();
810 if (lyxrc.language_global_options)
811 clsoptions << language_options.str() << ',';
814 // the user-defined options
815 if (!options.empty()) {
816 clsoptions << options << ',';
819 string strOptions(clsoptions.str());
820 if (!strOptions.empty()) {
821 strOptions = rtrim(strOptions, ",");
823 os << '[' << from_utf8(strOptions) << ']';
826 os << '{' << from_ascii(tclass.latexname()) << "}\n";
828 // end of \documentclass defs
830 // font selection must be done before loading fontenc.sty
832 loadFonts(fontsRoman, fontsSans,
833 fontsTypewriter, fontsSC, fontsOSF,
834 fontsSansScale, fontsTypewriterScale);
835 if (!fonts.empty()) {
836 os << from_ascii(fonts);
839 if (fontsDefaultFamily != "default")
840 os << "\\renewcommand{\\familydefault}{\\"
841 << from_ascii(fontsDefaultFamily) << "}\n";
842 // this one is not per buffer
843 if (lyxrc.fontenc != "default") {
844 os << "\\usepackage[" << from_ascii(lyxrc.fontenc)
849 if (inputenc == "auto") {
850 string const doc_encoding =
851 language->encoding()->latexName();
853 // Create a list with all the input encodings used
855 std::set<string> encodings =
856 features.getEncodingSet(doc_encoding);
858 // thailatex does not use the inputenc package, but sets up
859 // babel directly for tis620-0 encoding, therefore we must
860 // not request inputenc for tis620-0 encoding
861 if (!encodings.empty() || doc_encoding != "tis620-0") {
862 os << "\\usepackage[";
863 std::set<string>::const_iterator it = encodings.begin();
864 std::set<string>::const_iterator const end = encodings.end();
866 os << from_ascii(*it);
869 for (; it != end; ++it)
870 os << ',' << from_ascii(*it);
871 if (doc_encoding != "tis620-0") {
872 if (!encodings.empty())
874 os << from_ascii(doc_encoding);
876 os << "]{inputenc}\n";
879 } else if (inputenc != "default" && inputenc != "tis620-0" &&
880 inputenc != "ascii") {
881 os << "\\usepackage[" << from_ascii(inputenc)
886 if (use_geometry || nonstandard_papersize) {
887 os << "\\usepackage{geometry}\n";
889 os << "\\geometry{verbose";
890 if (orientation == ORIENTATION_LANDSCAPE)
894 if (!paperwidth.empty())
896 << from_ascii(paperwidth);
897 if (!paperheight.empty())
898 os << ",paperheight="
899 << from_ascii(paperheight);
902 os << ",letterpaper";
907 case PAPER_USEXECUTIVE:
908 os << ",executivepaper";
929 // default papersize ie PAPER_DEFAULT
930 switch (lyxrc.default_papersize) {
931 case PAPER_DEFAULT: // keep compiler happy
933 os << ",letterpaper";
938 case PAPER_USEXECUTIVE:
939 os << ",executivepaper";
959 if (!topmargin.empty())
960 os << ",tmargin=" << from_ascii(topmargin);
961 if (!bottommargin.empty())
962 os << ",bmargin=" << from_ascii(bottommargin);
963 if (!leftmargin.empty())
964 os << ",lmargin=" << from_ascii(leftmargin);
965 if (!rightmargin.empty())
966 os << ",rmargin=" << from_ascii(rightmargin);
967 if (!headheight.empty())
968 os << ",headheight=" << from_ascii(headheight);
969 if (!headsep.empty())
970 os << ",headsep=" << from_ascii(headsep);
971 if (!footskip.empty())
972 os << ",footskip=" << from_ascii(footskip);
977 if (tokenPos(tclass.opt_pagestyle(),
978 '|', pagestyle) >= 0) {
979 if (pagestyle == "fancy") {
980 os << "\\usepackage{fancyhdr}\n";
983 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
987 // Only if class has a ToC hierarchy
988 if (tclass.hasTocLevels()) {
989 if (secnumdepth != tclass.secnumdepth()) {
990 os << "\\setcounter{secnumdepth}{"
995 if (tocdepth != tclass.tocdepth()) {
996 os << "\\setcounter{tocdepth}{"
1003 if (paragraph_separation) {
1004 switch (getDefSkip().kind()) {
1005 case VSpace::SMALLSKIP:
1006 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1008 case VSpace::MEDSKIP:
1009 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1011 case VSpace::BIGSKIP:
1012 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1014 case VSpace::LENGTH:
1015 os << "\\setlength{\\parskip}{"
1016 << from_utf8(getDefSkip().length().asLatexString())
1019 default: // should never happen // Then delete it.
1020 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1025 os << "\\setlength{\\parindent}{0pt}\n";
1029 // If we use jurabib, we have to call babel here.
1030 if (use_babel && features.isRequired("jurabib")) {
1031 os << from_ascii(babelCall(language_options.str()))
1033 << from_ascii(features.getBabelOptions());
1037 // Now insert the LyX specific LaTeX commands...
1039 // The optional packages;
1040 docstring lyxpreamble(from_ascii(features.getPackages()));
1042 // this might be useful...
1043 lyxpreamble += "\n\\makeatletter\n";
1045 // Some macros LyX will need
1046 docstring tmppreamble(from_ascii(features.getMacros()));
1048 if (!tmppreamble.empty()) {
1049 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1050 "LyX specific LaTeX commands.\n"
1051 + tmppreamble + '\n';
1054 // the text class specific preamble
1055 tmppreamble = features.getTClassPreamble();
1056 if (!tmppreamble.empty()) {
1057 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1058 "Textclass specific LaTeX commands.\n"
1059 + tmppreamble + '\n';
1062 /* the user-defined preamble */
1063 if (!preamble.empty()) {
1065 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1066 "User specified LaTeX commands.\n"
1067 + from_utf8(preamble) + '\n';
1070 // Itemize bullet settings need to be last in case the user
1071 // defines their own bullets that use a package included
1072 // in the user-defined preamble -- ARRae
1073 // Actually it has to be done much later than that
1074 // since some packages like frenchb make modifications
1075 // at \begin{document} time -- JMarc
1076 docstring bullets_def;
1077 for (int i = 0; i < 4; ++i) {
1078 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1079 if (bullets_def.empty())
1080 bullets_def += "\\AtBeginDocument{\n";
1081 bullets_def += " \\def\\labelitemi";
1083 // `i' is one less than the item to modify
1090 bullets_def += "ii";
1096 bullets_def += '{' +
1097 user_defined_bullet(i).getText()
1102 if (!bullets_def.empty())
1103 lyxpreamble += bullets_def + "}\n\n";
1105 // We try to load babel late, in case it interferes
1106 // with other packages.
1107 // Jurabib has to be called after babel, though.
1108 if (use_babel && !features.isRequired("jurabib")) {
1110 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1111 lyxpreamble += from_utf8(features.getBabelOptions());
1114 lyxpreamble += "\\makeatother\n";
1116 // dvipost settings come after everything else
1117 if (features.isAvailable("dvipost") && outputChanges) {
1120 "\\dvipost{osstart color push Red}\n"
1121 "\\dvipost{osend color pop}\n"
1122 "\\dvipost{cbstart color push Blue}\n"
1123 "\\dvipost{cbend color pop}\n";
1127 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1128 for (int j = 0; j != nlines; ++j) {
1137 void BufferParams::useClassDefaults()
1139 LyXTextClass const & tclass = textclasslist[textclass];
1141 sides = tclass.sides();
1142 columns = tclass.columns();
1143 pagestyle = tclass.pagestyle();
1144 options = tclass.options();
1145 // Only if class has a ToC hierarchy
1146 if (tclass.hasTocLevels()) {
1147 secnumdepth = tclass.secnumdepth();
1148 tocdepth = tclass.tocdepth();
1153 bool BufferParams::hasClassDefaults() const
1155 LyXTextClass const & tclass = textclasslist[textclass];
1157 return (sides == tclass.sides()
1158 && columns == tclass.columns()
1159 && pagestyle == tclass.pagestyle()
1160 && options == tclass.options()
1161 && secnumdepth == tclass.secnumdepth()
1162 && tocdepth == tclass.tocdepth());
1166 LyXTextClass const & BufferParams::getLyXTextClass() const
1168 return textclasslist[textclass];
1172 LyXFont const BufferParams::getFont() const
1174 LyXFont f = getLyXTextClass().defaultfont();
1175 f.setLanguage(language);
1176 if (fontsDefaultFamily == "rmdefault")
1177 f.setFamily(LyXFont::ROMAN_FAMILY);
1178 else if (fontsDefaultFamily == "sfdefault")
1179 f.setFamily(LyXFont::SANS_FAMILY);
1180 else if (fontsDefaultFamily == "ttdefault")
1181 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1186 void BufferParams::readPreamble(LyXLex & lex)
1188 if (lex.getString() != "\\begin_preamble")
1189 lyxerr << "Error (BufferParams::readPreamble):"
1190 "consistency check failed." << endl;
1192 preamble = lex.getLongString("\\end_preamble");
1196 void BufferParams::readLanguage(LyXLex & lex)
1198 if (!lex.next()) return;
1200 string const tmptok = lex.getString();
1202 // check if tmptok is part of tex_babel in tex-defs.h
1203 language = languages.getLanguage(tmptok);
1205 // Language tmptok was not found
1206 language = default_language;
1207 lyxerr << "Warning: Setting language `"
1208 << tmptok << "' to `" << language->lang()
1214 void BufferParams::readGraphicsDriver(LyXLex & lex)
1216 if (!lex.next()) return;
1218 string const tmptok = lex.getString();
1219 // check if tmptok is part of tex_graphics in tex_defs.h
1222 string const test = tex_graphics[n++];
1224 if (test == tmptok) {
1225 graphicsDriver = tmptok;
1227 } else if (test == "") {
1229 "Warning: graphics driver `$$Token' not recognized!\n"
1230 " Setting graphics driver to `default'.\n");
1231 graphicsDriver = "default";
1238 void BufferParams::readBullets(LyXLex & lex)
1240 if (!lex.next()) return;
1242 int const index = lex.getInteger();
1244 int temp_int = lex.getInteger();
1245 user_defined_bullet(index).setFont(temp_int);
1246 temp_bullet(index).setFont(temp_int);
1248 user_defined_bullet(index).setCharacter(temp_int);
1249 temp_bullet(index).setCharacter(temp_int);
1251 user_defined_bullet(index).setSize(temp_int);
1252 temp_bullet(index).setSize(temp_int);
1256 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1258 // The bullet class should be able to read this.
1259 if (!lex.next()) return;
1260 int const index = lex.getInteger();
1262 docstring const temp_str = lex.getDocString();
1264 user_defined_bullet(index).setText(temp_str);
1265 temp_bullet(index).setText(temp_str);
1269 string const BufferParams::paperSizeName() const
1271 char real_papersize = papersize;
1272 if (real_papersize == PAPER_DEFAULT)
1273 real_papersize = lyxrc.default_papersize;
1275 switch (real_papersize) {
1284 case PAPER_USEXECUTIVE:
1288 case PAPER_USLETTER:
1295 string const BufferParams::dvips_options() const
1300 && papersize == PAPER_CUSTOM
1301 && !lyxrc.print_paper_dimension_flag.empty()
1302 && !paperwidth.empty()
1303 && !paperheight.empty()) {
1304 // using a custom papersize
1305 result = lyxrc.print_paper_dimension_flag;
1306 result += ' ' + paperwidth;
1307 result += ',' + paperheight;
1309 string const paper_option = paperSizeName();
1310 if (paper_option != "letter" ||
1311 orientation != ORIENTATION_LANDSCAPE) {
1312 // dvips won't accept -t letter -t landscape.
1313 // In all other cases, include the paper size
1315 result = lyxrc.print_paper_flag;
1316 result += ' ' + paper_option;
1319 if (orientation == ORIENTATION_LANDSCAPE &&
1320 papersize != PAPER_CUSTOM)
1321 result += ' ' + lyxrc.print_landscape_flag;
1326 string const BufferParams::babelCall(string const & lang_opts) const
1328 string tmp = lyxrc.language_package;
1329 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1330 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1335 string const BufferParams::loadFonts(string const & rm,
1336 string const & sf, string const & tt,
1337 bool const & sc, bool const & osf,
1338 int const & sfscale, int const & ttscale) const
1340 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1341 several packages have been replaced by others, that might not
1342 be installed on every system. We have to take care for that
1343 (see psnfss.pdf). We try to support all psnfss fonts as well
1344 as the fonts that have become de facto standard in the LaTeX
1345 world (e.g. Latin Modern). We do not support obsolete fonts
1346 (like PSLatex). In general, it should be possible to mix any
1347 rm font with any sf or tt font, respectively. (JSpitzm)
1349 -- separate math fonts.
1352 if (rm == "default" && sf == "default" && tt == "default")
1359 // Computer Modern (must be explicitely selectable -- there might be classes
1360 // that define a different default font!
1362 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1363 // osf for Computer Modern needs eco.sty
1365 os << "\\usepackage{eco}\n";
1367 // Latin Modern Roman
1368 else if (rm == "lmodern")
1369 os << "\\usepackage{lmodern}\n";
1371 else if (rm == "ae") {
1372 // not needed when using OT1 font encoding.
1373 if (lyxrc.fontenc != "default")
1374 os << "\\usepackage{ae,aecompl}\n";
1377 else if (rm == "times") {
1378 // try to load the best available package
1379 if (LaTeXFeatures::isAvailable("mathptmx"))
1380 os << "\\usepackage{mathptmx}\n";
1381 else if (LaTeXFeatures::isAvailable("mathptm"))
1382 os << "\\usepackage{mathptm}\n";
1384 os << "\\usepackage{times}\n";
1387 else if (rm == "palatino") {
1388 // try to load the best available package
1389 if (LaTeXFeatures::isAvailable("mathpazo")) {
1390 os << "\\usepackage";
1396 // "osf" includes "sc"!
1400 os << "{mathpazo}\n";
1402 else if (LaTeXFeatures::isAvailable("mathpple"))
1403 os << "\\usepackage{mathpple}\n";
1405 os << "\\usepackage{palatino}\n";
1408 else if (rm == "utopia") {
1409 // fourier supersedes utopia.sty, but does
1410 // not work with OT1 encoding.
1411 if (LaTeXFeatures::isAvailable("fourier")
1412 && lyxrc.fontenc != "default") {
1413 os << "\\usepackage";
1424 os << "{fourier}\n";
1427 os << "\\usepackage{utopia}\n";
1429 // Bera (complete fontset)
1430 else if (rm == "bera" && sf == "default" && tt == "default")
1431 os << "\\usepackage{bera}\n";
1433 else if (rm != "default")
1434 os << "\\usepackage" << "{" << rm << "}\n";
1437 // Helvetica, Bera Sans
1438 if (sf == "helvet" || sf == "berasans") {
1440 os << "\\usepackage[scaled=" << float(sfscale) / 100
1441 << "]{" << sf << "}\n";
1443 os << "\\usepackage{" << sf << "}\n";
1446 else if (sf == "avant")
1447 os << "\\usepackage{" << sf << "}\n";
1448 // Computer Modern, Latin Modern, CM Bright
1449 else if (sf != "default")
1450 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1452 // monospaced/typewriter
1453 // Courier, LuxiMono
1454 if (tt == "luximono" || tt == "beramono") {
1456 os << "\\usepackage[scaled=" << float(ttscale) / 100
1457 << "]{" << tt << "}\n";
1459 os << "\\usepackage{" << tt << "}\n";
1462 else if (tt == "courier" )
1463 os << "\\usepackage{" << tt << "}\n";
1464 // Computer Modern, Latin Modern, CM Bright
1465 else if (tt != "default")
1466 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1472 Encoding const & BufferParams::encoding() const
1474 if (inputenc == "auto" || inputenc == "default")
1475 return *(language->encoding());
1476 Encoding const * const enc =
1477 encodings.getFromLaTeXName(inputenc);
1480 lyxerr << "Unknown inputenc value `" << inputenc
1481 << "'. Using `auto' instead." << endl;
1482 return *(language->encoding());
1486 biblio::CiteEngine BufferParams::getEngine() const
1488 // FIXME the class should provide the numerical/
1489 // authoryear choice
1490 if (getLyXTextClass().provides(LyXTextClass::natbib)
1491 && cite_engine_ != biblio::ENGINE_NATBIB_NUMERICAL)
1492 return biblio::ENGINE_NATBIB_AUTHORYEAR;
1493 return cite_engine_;
1497 void BufferParams::setCiteEngine(biblio::CiteEngine const cite_engine)
1499 cite_engine_ = cite_engine;