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';
606 // then the the preamble
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 os << "\\usepackage[" << from_ascii(inputenc)
885 if (use_geometry || nonstandard_papersize) {
886 os << "\\usepackage{geometry}\n";
888 os << "\\geometry{verbose";
889 if (orientation == ORIENTATION_LANDSCAPE)
893 if (!paperwidth.empty())
895 << from_ascii(paperwidth);
896 if (!paperheight.empty())
897 os << ",paperheight="
898 << from_ascii(paperheight);
901 os << ",letterpaper";
906 case PAPER_USEXECUTIVE:
907 os << ",executivepaper";
928 // default papersize ie PAPER_DEFAULT
929 switch (lyxrc.default_papersize) {
930 case PAPER_DEFAULT: // keep compiler happy
932 os << ",letterpaper";
937 case PAPER_USEXECUTIVE:
938 os << ",executivepaper";
958 if (!topmargin.empty())
959 os << ",tmargin=" << from_ascii(topmargin);
960 if (!bottommargin.empty())
961 os << ",bmargin=" << from_ascii(bottommargin);
962 if (!leftmargin.empty())
963 os << ",lmargin=" << from_ascii(leftmargin);
964 if (!rightmargin.empty())
965 os << ",rmargin=" << from_ascii(rightmargin);
966 if (!headheight.empty())
967 os << ",headheight=" << from_ascii(headheight);
968 if (!headsep.empty())
969 os << ",headsep=" << from_ascii(headsep);
970 if (!footskip.empty())
971 os << ",footskip=" << from_ascii(footskip);
976 if (tokenPos(tclass.opt_pagestyle(),
977 '|', pagestyle) >= 0) {
978 if (pagestyle == "fancy") {
979 os << "\\usepackage{fancyhdr}\n";
982 os << "\\pagestyle{" << from_ascii(pagestyle) << "}\n";
986 // Only if class has a ToC hierarchy
987 if (tclass.hasTocLevels()) {
988 if (secnumdepth != tclass.secnumdepth()) {
989 os << "\\setcounter{secnumdepth}{"
994 if (tocdepth != tclass.tocdepth()) {
995 os << "\\setcounter{tocdepth}{"
1002 if (paragraph_separation) {
1003 switch (getDefSkip().kind()) {
1004 case VSpace::SMALLSKIP:
1005 os << "\\setlength{\\parskip}{\\smallskipamount}\n";
1007 case VSpace::MEDSKIP:
1008 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1010 case VSpace::BIGSKIP:
1011 os << "\\setlength{\\parskip}{\\bigskipamount}\n";
1013 case VSpace::LENGTH:
1014 os << "\\setlength{\\parskip}{"
1015 << from_utf8(getDefSkip().length().asLatexString())
1018 default: // should never happen // Then delete it.
1019 os << "\\setlength{\\parskip}{\\medskipamount}\n";
1024 os << "\\setlength{\\parindent}{0pt}\n";
1028 // If we use jurabib, we have to call babel here.
1029 if (use_babel && features.isRequired("jurabib")) {
1030 os << from_ascii(babelCall(language_options.str()))
1032 << from_ascii(features.getBabelOptions());
1036 // Now insert the LyX specific LaTeX commands...
1038 // The optional packages;
1039 docstring lyxpreamble(from_ascii(features.getPackages()));
1041 // this might be useful...
1042 lyxpreamble += "\n\\makeatletter\n";
1044 // Some macros LyX will need
1045 docstring tmppreamble(from_ascii(features.getMacros()));
1047 if (!tmppreamble.empty()) {
1048 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1049 "LyX specific LaTeX commands.\n"
1050 + tmppreamble + '\n';
1053 // the text class specific preamble
1054 tmppreamble = features.getTClassPreamble();
1055 if (!tmppreamble.empty()) {
1056 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1057 "Textclass specific LaTeX commands.\n"
1058 + tmppreamble + '\n';
1061 /* the user-defined preamble */
1062 if (!preamble.empty()) {
1064 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1065 "User specified LaTeX commands.\n"
1066 + from_utf8(preamble) + '\n';
1069 // Itemize bullet settings need to be last in case the user
1070 // defines their own bullets that use a package included
1071 // in the user-defined preamble -- ARRae
1072 // Actually it has to be done much later than that
1073 // since some packages like frenchb make modifications
1074 // at \begin{document} time -- JMarc
1075 docstring bullets_def;
1076 for (int i = 0; i < 4; ++i) {
1077 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1078 if (bullets_def.empty())
1079 bullets_def += "\\AtBeginDocument{\n";
1080 bullets_def += " \\def\\labelitemi";
1082 // `i' is one less than the item to modify
1089 bullets_def += "ii";
1095 bullets_def += '{' +
1096 user_defined_bullet(i).getText()
1101 if (!bullets_def.empty())
1102 lyxpreamble += bullets_def + "}\n\n";
1104 // We try to load babel late, in case it interferes
1105 // with other packages.
1106 // Jurabib has to be called after babel, though.
1107 if (use_babel && !features.isRequired("jurabib")) {
1109 lyxpreamble += from_utf8(babelCall(language_options.str())) + '\n';
1110 lyxpreamble += from_utf8(features.getBabelOptions());
1113 lyxpreamble += "\\makeatother\n";
1115 // dvipost settings come after everything else
1116 if (features.isAvailable("dvipost") && outputChanges) {
1119 "\\dvipost{osstart color push Red}\n"
1120 "\\dvipost{osend color pop}\n"
1121 "\\dvipost{cbstart color push Blue}\n"
1122 "\\dvipost{cbend color pop}\n";
1126 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1127 for (int j = 0; j != nlines; ++j) {
1136 void BufferParams::useClassDefaults()
1138 LyXTextClass const & tclass = textclasslist[textclass];
1140 sides = tclass.sides();
1141 columns = tclass.columns();
1142 pagestyle = tclass.pagestyle();
1143 options = tclass.options();
1144 // Only if class has a ToC hierarchy
1145 if (tclass.hasTocLevels()) {
1146 secnumdepth = tclass.secnumdepth();
1147 tocdepth = tclass.tocdepth();
1152 bool BufferParams::hasClassDefaults() const
1154 LyXTextClass const & tclass = textclasslist[textclass];
1156 return (sides == tclass.sides()
1157 && columns == tclass.columns()
1158 && pagestyle == tclass.pagestyle()
1159 && options == tclass.options()
1160 && secnumdepth == tclass.secnumdepth()
1161 && tocdepth == tclass.tocdepth());
1165 LyXTextClass const & BufferParams::getLyXTextClass() const
1167 return textclasslist[textclass];
1171 LyXFont const BufferParams::getFont() const
1173 LyXFont f = getLyXTextClass().defaultfont();
1174 f.setLanguage(language);
1175 if (fontsDefaultFamily == "rmdefault")
1176 f.setFamily(LyXFont::ROMAN_FAMILY);
1177 else if (fontsDefaultFamily == "sfdefault")
1178 f.setFamily(LyXFont::SANS_FAMILY);
1179 else if (fontsDefaultFamily == "ttdefault")
1180 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1185 void BufferParams::readPreamble(LyXLex & lex)
1187 if (lex.getString() != "\\begin_preamble")
1188 lyxerr << "Error (BufferParams::readPreamble):"
1189 "consistency check failed." << endl;
1191 preamble = lex.getLongString("\\end_preamble");
1195 void BufferParams::readLanguage(LyXLex & lex)
1197 if (!lex.next()) return;
1199 string const tmptok = lex.getString();
1201 // check if tmptok is part of tex_babel in tex-defs.h
1202 language = languages.getLanguage(tmptok);
1204 // Language tmptok was not found
1205 language = default_language;
1206 lyxerr << "Warning: Setting language `"
1207 << tmptok << "' to `" << language->lang()
1213 void BufferParams::readGraphicsDriver(LyXLex & lex)
1215 if (!lex.next()) return;
1217 string const tmptok = lex.getString();
1218 // check if tmptok is part of tex_graphics in tex_defs.h
1221 string const test = tex_graphics[n++];
1223 if (test == tmptok) {
1224 graphicsDriver = tmptok;
1226 } else if (test == "") {
1228 "Warning: graphics driver `$$Token' not recognized!\n"
1229 " Setting graphics driver to `default'.\n");
1230 graphicsDriver = "default";
1237 void BufferParams::readBullets(LyXLex & lex)
1239 if (!lex.next()) return;
1241 int const index = lex.getInteger();
1243 int temp_int = lex.getInteger();
1244 user_defined_bullet(index).setFont(temp_int);
1245 temp_bullet(index).setFont(temp_int);
1247 user_defined_bullet(index).setCharacter(temp_int);
1248 temp_bullet(index).setCharacter(temp_int);
1250 user_defined_bullet(index).setSize(temp_int);
1251 temp_bullet(index).setSize(temp_int);
1255 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1257 // The bullet class should be able to read this.
1258 if (!lex.next()) return;
1259 int const index = lex.getInteger();
1261 docstring const temp_str = lex.getDocString();
1263 user_defined_bullet(index).setText(temp_str);
1264 temp_bullet(index).setText(temp_str);
1268 string const BufferParams::paperSizeName() const
1270 char real_papersize = papersize;
1271 if (real_papersize == PAPER_DEFAULT)
1272 real_papersize = lyxrc.default_papersize;
1274 switch (real_papersize) {
1283 case PAPER_USEXECUTIVE:
1287 case PAPER_USLETTER:
1294 string const BufferParams::dvips_options() const
1299 && papersize == PAPER_CUSTOM
1300 && !lyxrc.print_paper_dimension_flag.empty()
1301 && !paperwidth.empty()
1302 && !paperheight.empty()) {
1303 // using a custom papersize
1304 result = lyxrc.print_paper_dimension_flag;
1305 result += ' ' + paperwidth;
1306 result += ',' + paperheight;
1308 string const paper_option = paperSizeName();
1309 if (paper_option != "letter" ||
1310 orientation != ORIENTATION_LANDSCAPE) {
1311 // dvips won't accept -t letter -t landscape.
1312 // In all other cases, include the paper size
1314 result = lyxrc.print_paper_flag;
1315 result += ' ' + paper_option;
1318 if (orientation == ORIENTATION_LANDSCAPE &&
1319 papersize != PAPER_CUSTOM)
1320 result += ' ' + lyxrc.print_landscape_flag;
1325 string const BufferParams::babelCall(string const & lang_opts) const
1327 string tmp = lyxrc.language_package;
1328 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1329 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1334 string const BufferParams::loadFonts(string const & rm,
1335 string const & sf, string const & tt,
1336 bool const & sc, bool const & osf,
1337 int const & sfscale, int const & ttscale) const
1339 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1340 several packages have been replaced by others, that might not
1341 be installed on every system. We have to take care for that
1342 (see psnfss.pdf). We try to support all psnfss fonts as well
1343 as the fonts that have become de facto standard in the LaTeX
1344 world (e.g. Latin Modern). We do not support obsolete fonts
1345 (like PSLatex). In general, it should be possible to mix any
1346 rm font with any sf or tt font, respectively. (JSpitzm)
1348 -- separate math fonts.
1351 if (rm == "default" && sf == "default" && tt == "default")
1358 // Computer Modern (must be explicitely selectable -- there might be classes
1359 // that define a different default font!
1361 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1362 // osf for Computer Modern needs eco.sty
1364 os << "\\usepackage{eco}\n";
1366 // Latin Modern Roman
1367 else if (rm == "lmodern")
1368 os << "\\usepackage{lmodern}\n";
1370 else if (rm == "ae") {
1371 // not needed when using OT1 font encoding.
1372 if (lyxrc.fontenc != "default")
1373 os << "\\usepackage{ae,aecompl}\n";
1376 else if (rm == "times") {
1377 // try to load the best available package
1378 if (LaTeXFeatures::isAvailable("mathptmx"))
1379 os << "\\usepackage{mathptmx}\n";
1380 else if (LaTeXFeatures::isAvailable("mathptm"))
1381 os << "\\usepackage{mathptm}\n";
1383 os << "\\usepackage{times}\n";
1386 else if (rm == "palatino") {
1387 // try to load the best available package
1388 if (LaTeXFeatures::isAvailable("mathpazo")) {
1389 os << "\\usepackage";
1395 // "osf" includes "sc"!
1399 os << "{mathpazo}\n";
1401 else if (LaTeXFeatures::isAvailable("mathpple"))
1402 os << "\\usepackage{mathpple}\n";
1404 os << "\\usepackage{palatino}\n";
1407 else if (rm == "utopia") {
1408 // fourier supersedes utopia.sty, but does
1409 // not work with OT1 encoding.
1410 if (LaTeXFeatures::isAvailable("fourier")
1411 && lyxrc.fontenc != "default") {
1412 os << "\\usepackage";
1423 os << "{fourier}\n";
1426 os << "\\usepackage{utopia}\n";
1428 // Bera (complete fontset)
1429 else if (rm == "bera" && sf == "default" && tt == "default")
1430 os << "\\usepackage{bera}\n";
1432 else if (rm != "default")
1433 os << "\\usepackage" << "{" << rm << "}\n";
1436 // Helvetica, Bera Sans
1437 if (sf == "helvet" || sf == "berasans") {
1439 os << "\\usepackage[scaled=" << float(sfscale) / 100
1440 << "]{" << sf << "}\n";
1442 os << "\\usepackage{" << sf << "}\n";
1445 else if (sf == "avant")
1446 os << "\\usepackage{" << sf << "}\n";
1447 // Computer Modern, Latin Modern, CM Bright
1448 else if (sf != "default")
1449 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1451 // monospaced/typewriter
1452 // Courier, LuxiMono
1453 if (tt == "luximono" || tt == "beramono") {
1455 os << "\\usepackage[scaled=" << float(ttscale) / 100
1456 << "]{" << tt << "}\n";
1458 os << "\\usepackage{" << tt << "}\n";
1461 else if (tt == "courier" )
1462 os << "\\usepackage{" << tt << "}\n";
1463 // Computer Modern, Latin Modern, CM Bright
1464 else if (tt != "default")
1465 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";
1471 Encoding const & BufferParams::encoding() const
1473 if (inputenc == "auto" || inputenc == "default")
1474 return *(language->encoding());
1475 Encoding const * const enc =
1476 encodings.getFromLaTeXName(inputenc);
1479 lyxerr << "Unknown inputenc value `" << inputenc
1480 << "'. Using `auto' instead." << endl;
1481 return *(language->encoding());