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>
49 namespace support = lyx::support;
52 using lyx::odocstream;
53 using lyx::support::bformat;
54 using lyx::support::rtrim;
55 using lyx::support::tokenPos;
59 using std::istringstream;
61 using std::ostringstream;
64 namespace Alert = lyx::frontend::Alert;
65 namespace biblio = lyx::biblio;
71 // Paragraph separation
72 typedef Translator<string, BufferParams::PARSEP> ParSepTranslator;
75 ParSepTranslator const init_parseptranslator()
77 ParSepTranslator translator(string_paragraph_separation[0], BufferParams::PARSEP_INDENT);
78 translator.addPair(string_paragraph_separation[1], BufferParams::PARSEP_SKIP);
83 ParSepTranslator const & parseptranslator()
85 static ParSepTranslator translator = init_parseptranslator();
91 typedef Translator<string, InsetQuotes::quote_language> QuotesLangTranslator;
94 QuotesLangTranslator const init_quoteslangtranslator()
96 QuotesLangTranslator translator(string_quotes_language[0], InsetQuotes::EnglishQ);
97 translator.addPair(string_quotes_language[1], InsetQuotes::SwedishQ);
98 translator.addPair(string_quotes_language[2], InsetQuotes::GermanQ);
99 translator.addPair(string_quotes_language[3], InsetQuotes::PolishQ);
100 translator.addPair(string_quotes_language[4], InsetQuotes::FrenchQ);
101 translator.addPair(string_quotes_language[5], InsetQuotes::DanishQ);
106 QuotesLangTranslator const & quoteslangtranslator()
108 static QuotesLangTranslator translator = init_quoteslangtranslator();
114 typedef Translator<std::string, PAPER_SIZE> PaperSizeTranslator;
117 PaperSizeTranslator const init_papersizetranslator()
119 PaperSizeTranslator translator(string_papersize[0], PAPER_DEFAULT);
120 translator.addPair(string_papersize[1], PAPER_CUSTOM);
121 translator.addPair(string_papersize[2], PAPER_USLETTER);
122 translator.addPair(string_papersize[3], PAPER_USLEGAL);
123 translator.addPair(string_papersize[4], PAPER_USEXECUTIVE);
124 translator.addPair(string_papersize[5], PAPER_A3);
125 translator.addPair(string_papersize[6], PAPER_A4);
126 translator.addPair(string_papersize[7], PAPER_A5);
127 translator.addPair(string_papersize[8], PAPER_B3);
128 translator.addPair(string_papersize[9], PAPER_B4);
129 translator.addPair(string_papersize[10], PAPER_B5);
134 PaperSizeTranslator const & papersizetranslator()
136 static PaperSizeTranslator translator = init_papersizetranslator();
142 typedef Translator<string, PAPER_ORIENTATION> PaperOrientationTranslator;
145 PaperOrientationTranslator const init_paperorientationtranslator()
147 PaperOrientationTranslator translator(string_orientation[0], ORIENTATION_PORTRAIT);
148 translator.addPair(string_orientation[1], ORIENTATION_LANDSCAPE);
153 PaperOrientationTranslator const & paperorientationtranslator()
155 static PaperOrientationTranslator translator = init_paperorientationtranslator();
161 typedef Translator<int, LyXTextClass::PageSides> SidesTranslator;
164 SidesTranslator const init_sidestranslator()
166 SidesTranslator translator(1, LyXTextClass::OneSide);
167 translator.addPair(2, LyXTextClass::TwoSides);
172 SidesTranslator const & sidestranslator()
174 static SidesTranslator translator = init_sidestranslator();
181 typedef Translator<int, BufferParams::AMS> AMSTranslator;
184 AMSTranslator const init_amstranslator()
186 AMSTranslator translator(0, BufferParams::AMS_OFF);
187 translator.addPair(1, BufferParams::AMS_AUTO);
188 translator.addPair(2, BufferParams::AMS_ON);
193 AMSTranslator const & amstranslator()
195 static AMSTranslator translator = init_amstranslator();
201 typedef Translator<string, biblio::CiteEngine> CiteEngineTranslator;
204 CiteEngineTranslator const init_citeenginetranslator()
206 CiteEngineTranslator translator("basic", biblio::ENGINE_BASIC);
207 translator.addPair("natbib_numerical", biblio::ENGINE_NATBIB_NUMERICAL);
208 translator.addPair("natbib_authoryear", biblio::ENGINE_NATBIB_AUTHORYEAR);
209 translator.addPair("jurabib", biblio::ENGINE_JURABIB);
214 CiteEngineTranslator const & citeenginetranslator()
216 static CiteEngineTranslator translator = init_citeenginetranslator();
222 typedef Translator<string, Spacing::Space> SpaceTranslator;
225 SpaceTranslator const init_spacetranslator()
227 SpaceTranslator translator("default", Spacing::Default);
228 translator.addPair("single", Spacing::Single);
229 translator.addPair("onehalf", Spacing::Onehalf);
230 translator.addPair("double", Spacing::Double);
231 translator.addPair("other", Spacing::Other);
236 SpaceTranslator const & spacetranslator()
238 static SpaceTranslator translator = init_spacetranslator();
242 // ends annonym namespace
246 class BufferParams::Impl
251 AuthorList authorlist;
252 BranchList branchlist;
253 boost::array<Bullet, 4> temp_bullets;
254 boost::array<Bullet, 4> user_defined_bullets;
256 /** This is the amount of space used for paragraph_separation "skip",
257 * and for detached paragraphs in "indented" documents.
263 BufferParams::Impl::Impl()
264 : defskip(VSpace::MEDSKIP)
266 // set initial author
267 authorlist.record(Author(lyxrc.user_name, lyxrc.user_email));
272 BufferParams::MemoryTraits::clone(BufferParams::Impl const * ptr)
276 return new BufferParams::Impl(*ptr);
280 void BufferParams::MemoryTraits::destroy(BufferParams::Impl * ptr)
286 BufferParams::BufferParams()
287 : // Initialize textclass to point to article. if `first' is
288 // true in the returned pair, then `second' is the textclass
289 // number; if it is false, second is 0. In both cases, second
291 textclass(textclasslist.numberOfClass("article").second),
294 paragraph_separation = PARSEP_INDENT;
295 quotes_language = InsetQuotes::EnglishQ;
296 fontsize = "default";
299 papersize = PAPER_DEFAULT;
300 orientation = ORIENTATION_PORTRAIT;
301 use_geometry = false;
302 use_amsmath = AMS_AUTO;
303 cite_engine = biblio::ENGINE_BASIC;
304 use_bibtopic = false;
305 trackChanges = false;
306 outputChanges = false;
309 language = default_language;
310 fontsRoman = "default";
311 fontsSans = "default";
312 fontsTypewriter = "default";
313 fontsDefaultFamily = "default";
316 fontsSansScale = 100;
317 fontsTypewriterScale = 100;
319 graphicsDriver = "default";
320 sides = LyXTextClass::OneSide;
322 pagestyle = "default";
324 for (int iter = 0; iter < 4; ++iter) {
325 user_defined_bullet(iter) = ITEMIZE_DEFAULTS[iter];
326 temp_bullet(iter) = ITEMIZE_DEFAULTS[iter];
331 BufferParams::~BufferParams()
335 AuthorList & BufferParams::authors()
337 return pimpl_->authorlist;
341 AuthorList const & BufferParams::authors() const
343 return pimpl_->authorlist;
347 BranchList & BufferParams::branchlist()
349 return pimpl_->branchlist;
353 BranchList const & BufferParams::branchlist() const
355 return pimpl_->branchlist;
359 Bullet & BufferParams::temp_bullet(lyx::size_type const index)
361 BOOST_ASSERT(index < 4);
362 return pimpl_->temp_bullets[index];
366 Bullet const & BufferParams::temp_bullet(lyx::size_type const index) const
368 BOOST_ASSERT(index < 4);
369 return pimpl_->temp_bullets[index];
373 Bullet & BufferParams::user_defined_bullet(lyx::size_type const index)
375 BOOST_ASSERT(index < 4);
376 return pimpl_->user_defined_bullets[index];
380 Bullet const & BufferParams::user_defined_bullet(lyx::size_type const index) const
382 BOOST_ASSERT(index < 4);
383 return pimpl_->user_defined_bullets[index];
387 Spacing & BufferParams::spacing()
389 return pimpl_->spacing;
393 Spacing const & BufferParams::spacing() const
395 return pimpl_->spacing;
399 VSpace const & BufferParams::getDefSkip() const
401 return pimpl_->defskip;
405 void BufferParams::setDefSkip(VSpace const & vs)
407 pimpl_->defskip = vs;
411 string const BufferParams::readToken(LyXLex & lex, string const & token)
413 if (token == "\\textclass") {
415 string const classname = lex.getString();
416 pair<bool, lyx::textclass_type> pp =
417 textclasslist.numberOfClass(classname);
419 textclass = pp.second;
421 // if text class does not exist, try to load it from filepath
422 pp = textclasslist.addTextClass(classname, filepath);
424 textclass = pp.second;
430 // FIXME: isTeXClassAvailable will try to load the layout file, but will
431 // fail because of the lack of path info. Warnings will be given although
432 // the layout file will be correctly loaded later.
433 if (!getLyXTextClass().isTeXClassAvailable()) {
434 docstring const msg =
435 bformat(_("The document uses a missing "
436 "TeX class \"%1$s\".\n"), lyx::from_utf8(classname));
437 Alert::warning(_("Document class not available"),
438 msg + _("LyX will not be able to produce output."));
440 } else if (token == "\\begin_preamble") {
442 } else if (token == "\\options") {
444 options = lex.getString();
445 } else if (token == "\\language") {
447 } else if (token == "\\inputencoding") {
449 } else if (token == "\\graphics") {
450 readGraphicsDriver(lex);
451 } else if (token == "\\font_roman") {
453 } else if (token == "\\font_sans") {
455 } else if (token == "\\font_typewriter") {
456 lex >> fontsTypewriter;
457 } else if (token == "\\font_default_family") {
458 lex >> fontsDefaultFamily;
459 } else if (token == "\\font_sc") {
461 } else if (token == "\\font_osf") {
463 } else if (token == "\\font_sf_scale") {
464 lex >> fontsSansScale;
465 } else if (token == "\\font_tt_scale") {
466 lex >> fontsTypewriterScale;
467 } else if (token == "\\paragraph_separation") {
470 paragraph_separation = parseptranslator().find(parsep);
471 } else if (token == "\\defskip") {
473 pimpl_->defskip = VSpace(lex.getString());
474 } else if (token == "\\quotes_language") {
477 quotes_language = quoteslangtranslator().find(quotes_lang);
478 } else if (token == "\\papersize") {
481 papersize = papersizetranslator().find(ppsize);
482 } else if (token == "\\use_geometry") {
484 } else if (token == "\\use_amsmath") {
487 use_amsmath = amstranslator().find(use_ams);
488 } else if (token == "\\cite_engine") {
491 cite_engine = citeenginetranslator().find(engine);
492 } else if (token == "\\use_bibtopic") {
494 } else if (token == "\\tracking_changes") {
496 } else if (token == "\\output_changes") {
497 lex >> outputChanges;
498 } else if (token == "\\branch") {
500 string branch = lex.getString();
501 branchlist().add(branch);
504 string const tok = lex.getString();
505 if (tok == "\\end_branch")
507 Branch * branch_ptr = branchlist().find(branch);
508 if (tok == "\\selected") {
511 branch_ptr->setSelected(lex.getInteger());
513 // not yet operational
514 if (tok == "\\color") {
516 string color = lex.getString();
518 branch_ptr->setColor(color);
519 // Update also the LColor table:
521 color = lcolor.getX11Name(LColor::background);
522 lcolor.setColor(branch, color);
526 } else if (token == "\\author") {
528 istringstream ss(lex.getString());
531 author_map.push_back(pimpl_->authorlist.record(a));
532 } else if (token == "\\paperorientation") {
535 orientation = paperorientationtranslator().find(orient);
536 } else if (token == "\\paperwidth") {
538 } else if (token == "\\paperheight") {
540 } else if (token == "\\leftmargin") {
542 } else if (token == "\\topmargin") {
544 } else if (token == "\\rightmargin") {
546 } else if (token == "\\bottommargin") {
548 } else if (token == "\\headheight") {
550 } else if (token == "\\headsep") {
552 } else if (token == "\\footskip") {
554 } else if (token == "\\paperfontsize") {
556 } else if (token == "\\papercolumns") {
558 } else if (token == "\\papersides") {
561 sides = sidestranslator().find(psides);
562 } else if (token == "\\paperpagestyle") {
564 } else if (token == "\\bullet") {
566 } else if (token == "\\bulletLaTeX") {
567 readBulletsLaTeX(lex);
568 } else if (token == "\\secnumdepth") {
570 } else if (token == "\\tocdepth") {
572 } else if (token == "\\spacing") {
576 if (nspacing == "other") {
579 spacing().set(spacetranslator().find(nspacing), tmp_val);
580 } else if (token == "\\float_placement") {
581 lex >> float_placement;
590 void BufferParams::writeFile(ostream & os) const
592 // The top of the file is written by the buffer.
593 // Prints out the buffer info into the .lyx file given by file
596 os << "\\textclass " << textclasslist[textclass].name() << '\n';
598 // then the the preamble
599 if (!preamble.empty()) {
600 // remove '\n' from the end of preamble
601 string const tmppreamble = rtrim(preamble, "\n");
602 os << "\\begin_preamble\n"
604 << "\n\\end_preamble\n";
608 if (!options.empty()) {
609 os << "\\options " << options << '\n';
612 // then the text parameters
613 if (language != ignore_language)
614 os << "\\language " << language->lang() << '\n';
615 os << "\\inputencoding " << inputenc
616 << "\n\\font_roman " << fontsRoman
617 << "\n\\font_sans " << fontsSans
618 << "\n\\font_typewriter " << fontsTypewriter
619 << "\n\\font_default_family " << fontsDefaultFamily
620 << "\n\\font_sc " << convert<string>(fontsSC)
621 << "\n\\font_osf " << convert<string>(fontsOSF)
622 << "\n\\font_sf_scale " << fontsSansScale
623 << "\n\\font_tt_scale " << fontsTypewriterScale
624 << "\n\\graphics " << graphicsDriver << '\n';
626 if (!float_placement.empty()) {
627 os << "\\float_placement " << float_placement << '\n';
629 os << "\\paperfontsize " << fontsize << '\n';
631 spacing().writeFile(os);
633 os << "\\papersize " << string_papersize[papersize]
634 << "\n\\use_geometry " << convert<string>(use_geometry)
635 << "\n\\use_amsmath " << use_amsmath
636 << "\n\\cite_engine " << citeenginetranslator().find(cite_engine)
637 << "\n\\use_bibtopic " << convert<string>(use_bibtopic)
638 << "\n\\paperorientation " << string_orientation[orientation]
641 BranchList::const_iterator it = branchlist().begin();
642 BranchList::const_iterator end = branchlist().end();
643 for (; it != end; ++it) {
644 os << "\\branch " << it->getBranch()
645 << "\n\\selected " << it->getSelected()
646 << "\n\\color " << lyx::X11hexname(it->getColor())
651 if (!paperwidth.empty())
652 os << "\\paperwidth "
653 << VSpace(paperwidth).asLyXCommand() << '\n';
654 if (!paperheight.empty())
655 os << "\\paperheight "
656 << VSpace(paperheight).asLyXCommand() << '\n';
657 if (!leftmargin.empty())
658 os << "\\leftmargin "
659 << VSpace(leftmargin).asLyXCommand() << '\n';
660 if (!topmargin.empty())
662 << VSpace(topmargin).asLyXCommand() << '\n';
663 if (!rightmargin.empty())
664 os << "\\rightmargin "
665 << VSpace(rightmargin).asLyXCommand() << '\n';
666 if (!bottommargin.empty())
667 os << "\\bottommargin "
668 << VSpace(bottommargin).asLyXCommand() << '\n';
669 if (!headheight.empty())
670 os << "\\headheight "
671 << VSpace(headheight).asLyXCommand() << '\n';
672 if (!headsep.empty())
674 << VSpace(headsep).asLyXCommand() << '\n';
675 if (!footskip.empty())
677 << VSpace(footskip).asLyXCommand() << '\n';
678 os << "\\secnumdepth " << secnumdepth
679 << "\n\\tocdepth " << tocdepth
680 << "\n\\paragraph_separation "
681 << string_paragraph_separation[paragraph_separation]
682 << "\n\\defskip " << getDefSkip().asLyXCommand()
683 << "\n\\quotes_language "
684 << string_quotes_language[quotes_language]
685 << "\n\\papercolumns " << columns
686 << "\n\\papersides " << sides
687 << "\n\\paperpagestyle " << pagestyle << '\n';
688 for (int i = 0; i < 4; ++i) {
689 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
690 if (user_defined_bullet(i).getFont() != -1) {
691 os << "\\bullet " << i << " "
692 << user_defined_bullet(i).getFont() << " "
693 << user_defined_bullet(i).getCharacter() << " "
694 << user_defined_bullet(i).getSize() << "\n";
698 os << "\\bulletLaTeX " << i << " \""
699 << lyx::to_ascii(user_defined_bullet(i).getText())
705 os << "\\tracking_changes " << convert<string>(trackChanges) << "\n";
706 os << "\\output_changes " << convert<string>(outputChanges) << "\n";
708 AuthorList::Authors::const_iterator a_it = pimpl_->authorlist.begin();
709 AuthorList::Authors::const_iterator a_end = pimpl_->authorlist.end();
710 for (; a_it != a_end; ++a_it) {
711 os << "\\author " << a_it->second << "\n";
716 bool BufferParams::writeLaTeX(odocstream & os, LaTeXFeatures & features,
717 TexRow & texrow) const
719 os << "\\documentclass";
721 LyXTextClass const & tclass = getLyXTextClass();
723 ostringstream clsoptions; // the document class options.
725 if (tokenPos(tclass.opt_fontsize(),
726 '|', fontsize) >= 0) {
727 // only write if existing in list (and not default)
728 clsoptions << fontsize << "pt,";
731 // custom, A3, B3 and B4 paper sizes need geometry
732 bool nonstandard_papersize = (papersize == PAPER_B3) ||
733 (papersize == PAPER_B4) ||
734 (papersize == PAPER_A3) ||
735 (papersize == PAPER_CUSTOM);
740 clsoptions << "a4paper,";
743 clsoptions << "letterpaper,";
746 clsoptions << "a5paper,";
749 clsoptions << "b5paper,";
751 case PAPER_USEXECUTIVE:
752 clsoptions << "executivepaper,";
755 clsoptions << "legalpaper,";
767 if (sides != tclass.sides()) {
769 case LyXTextClass::OneSide:
770 clsoptions << "oneside,";
772 case LyXTextClass::TwoSides:
773 clsoptions << "twoside,";
779 if (columns != tclass.columns()) {
781 clsoptions << "twocolumn,";
783 clsoptions << "onecolumn,";
787 && orientation == ORIENTATION_LANDSCAPE)
788 clsoptions << "landscape,";
790 // language should be a parameter to \documentclass
791 if (language->babel() == "hebrew"
792 && default_language->babel() != "hebrew")
793 // This seems necessary
794 features.useLanguage(default_language);
796 ostringstream language_options;
797 bool const use_babel = features.useBabel();
799 language_options << features.getLanguages();
800 language_options << language->babel();
801 if (lyxrc.language_global_options)
802 clsoptions << language_options.str() << ',';
805 // the user-defined options
806 if (!options.empty()) {
807 clsoptions << options << ',';
810 string strOptions(clsoptions.str());
811 if (!strOptions.empty()) {
812 strOptions = rtrim(strOptions, ",");
814 os << '[' << lyx::from_utf8(strOptions) << ']';
817 os << '{' << lyx::from_ascii(tclass.latexname()) << "}\n";
819 // end of \documentclass defs
821 // font selection must be done before loading fontenc.sty
823 loadFonts(features, fontsRoman, fontsSans,
824 fontsTypewriter, fontsSC, fontsOSF,
825 fontsSansScale, fontsTypewriterScale);
826 if (!fonts.empty()) {
827 os << lyx::from_ascii(fonts);
830 if (fontsDefaultFamily != "default")
831 os << "\\renewcommand{\\familydefault}{\\"
832 << lyx::from_ascii(fontsDefaultFamily) << "}\n";
833 // this one is not per buffer
834 if (lyxrc.fontenc != "default") {
835 os << "\\usepackage[" << lyx::from_ascii(lyxrc.fontenc)
840 // TODO: Some people want to support more encodings than UTF-8. They can have a field day around here
842 os << "\\usepackage[utf8]{inputenc}\n";
845 if (inputenc == "auto") {
846 string const doc_encoding =
847 language->encoding()->latexName();
849 // Create a list with all the input encodings used
851 std::set<string> encodings =
852 features.getEncodingSet(doc_encoding);
854 os << "\\usepackage[";
855 std::set<string>::const_iterator it = encodings.begin();
856 std::set<string>::const_iterator const end = encodings.end();
857 for (; it != end; ++it)
858 os << lyx::from_ascii(*it) << ',';
859 os << lyx::from_ascii(doc_encoding) << "]{inputenc}\n";
861 } else if (inputenc != "default") {
862 os << "\\usepackage[" << lyx::from_ascii(inputenc)
868 if (use_geometry || nonstandard_papersize) {
869 os << "\\usepackage{geometry}\n";
871 os << "\\geometry{verbose";
872 if (orientation == ORIENTATION_LANDSCAPE)
876 if (!paperwidth.empty())
878 << lyx::from_ascii(paperwidth);
879 if (!paperheight.empty())
880 os << ",paperheight="
881 << lyx::from_ascii(paperheight);
884 os << ",letterpaper";
889 case PAPER_USEXECUTIVE:
890 os << ",executivepaper";
911 // default papersize ie PAPER_DEFAULT
912 switch (lyxrc.default_papersize) {
913 case PAPER_DEFAULT: // keep compiler happy
915 os << ",letterpaper";
920 case PAPER_USEXECUTIVE:
921 os << ",executivepaper";
941 if (!topmargin.empty())
942 os << ",tmargin=" << lyx::from_ascii(topmargin);
943 if (!bottommargin.empty())
944 os << ",bmargin=" << lyx::from_ascii(bottommargin);
945 if (!leftmargin.empty())
946 os << ",lmargin=" << lyx::from_ascii(leftmargin);
947 if (!rightmargin.empty())
948 os << ",rmargin=" << lyx::from_ascii(rightmargin);
949 if (!headheight.empty())
950 os << ",headheight=" << lyx::from_ascii(headheight);
951 if (!headsep.empty())
952 os << ",headsep=" << lyx::from_ascii(headsep);
953 if (!footskip.empty())
954 os << ",footskip=" << lyx::from_ascii(footskip);
959 if (tokenPos(tclass.opt_pagestyle(),
960 '|', pagestyle) >= 0) {
961 if (pagestyle == "fancy") {
962 os << "\\usepackage{fancyhdr}\n";
965 os << "\\pagestyle{" << lyx::from_ascii(pagestyle) << "}\n";
969 // Only if class has a ToC hierarchy
970 if (tclass.hasTocLevels()) {
971 if (secnumdepth != tclass.secnumdepth()) {
972 os << "\\setcounter{secnumdepth}{"
977 if (tocdepth != tclass.tocdepth()) {
978 os << "\\setcounter{tocdepth}{"
985 if (paragraph_separation) {
986 switch (getDefSkip().kind()) {
987 case VSpace::SMALLSKIP:
988 os << "\\setlength\\parskip{\\smallskipamount}\n";
990 case VSpace::MEDSKIP:
991 os << "\\setlength\\parskip{\\medskipamount}\n";
993 case VSpace::BIGSKIP:
994 os << "\\setlength\\parskip{\\bigskipamount}\n";
997 os << "\\setlength\\parskip{"
998 << lyx::from_ascii(getDefSkip().length().asLatexString())
1001 default: // should never happen // Then delete it.
1002 os << "\\setlength\\parskip{\\medskipamount}\n";
1007 os << "\\setlength\\parindent{0pt}\n";
1011 // If we use jurabib, we have to call babel here.
1012 if (use_babel && features.isRequired("jurabib")) {
1013 os << lyx::from_ascii(babelCall(language_options.str()))
1015 << lyx::from_ascii(features.getBabelOptions());
1019 // Now insert the LyX specific LaTeX commands...
1021 // The optional packages;
1022 string lyxpreamble(features.getPackages());
1024 // this might be useful...
1025 lyxpreamble += "\n\\makeatletter\n";
1027 // Some macros LyX will need
1028 string tmppreamble(features.getMacros());
1030 if (!tmppreamble.empty()) {
1031 lyxpreamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1032 "LyX specific LaTeX commands.\n"
1033 + tmppreamble + '\n';
1036 // the text class specific preamble
1037 tmppreamble = features.getTClassPreamble();
1038 if (!tmppreamble.empty()) {
1039 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1040 "Textclass specific LaTeX commands.\n"
1041 + tmppreamble + '\n';
1044 /* the user-defined preamble */
1045 if (!preamble.empty()) {
1046 lyxpreamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
1047 "User specified LaTeX commands.\n"
1051 // Itemize bullet settings need to be last in case the user
1052 // defines their own bullets that use a package included
1053 // in the user-defined preamble -- ARRae
1054 // Actually it has to be done much later than that
1055 // since some packages like frenchb make modifications
1056 // at \begin{document} time -- JMarc
1058 for (int i = 0; i < 4; ++i) {
1059 if (user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
1060 if (bullets_def.empty())
1061 bullets_def="\\AtBeginDocument{\n";
1062 bullets_def += " \\def\\labelitemi";
1064 // `i' is one less than the item to modify
1071 bullets_def += "ii";
1078 bullets_def += '{' +
1079 lyx::to_ascii(user_defined_bullet(i).getText())
1084 if (!bullets_def.empty())
1085 lyxpreamble += bullets_def + "}\n\n";
1087 // We try to load babel late, in case it interferes
1088 // with other packages.
1089 // Jurabib has to be called after babel, though.
1090 if (use_babel && !features.isRequired("jurabib")) {
1091 lyxpreamble += babelCall(language_options.str()) + '\n';
1092 lyxpreamble += features.getBabelOptions();
1095 lyxpreamble += "\\makeatother\n";
1097 // dvipost settings come after everything else
1098 if (features.isAvailable("dvipost") && outputChanges) {
1101 "\\dvipost{osstart color push Red}\n"
1102 "\\dvipost{osend color pop}\n"
1103 "\\dvipost{cbstart color push Blue}\n"
1104 "\\dvipost{cbend color pop}\n";
1108 int(lyx::count(lyxpreamble.begin(), lyxpreamble.end(), '\n'));
1109 for (int j = 0; j != nlines; ++j) {
1114 os << lyx::from_utf8(lyxpreamble);
1119 void BufferParams::useClassDefaults()
1121 LyXTextClass const & tclass = textclasslist[textclass];
1123 sides = tclass.sides();
1124 columns = tclass.columns();
1125 pagestyle = tclass.pagestyle();
1126 options = tclass.options();
1127 // Only if class has a ToC hierarchy
1128 if (tclass.hasTocLevels()) {
1129 secnumdepth = tclass.secnumdepth();
1130 tocdepth = tclass.tocdepth();
1135 bool BufferParams::hasClassDefaults() const
1137 LyXTextClass const & tclass = textclasslist[textclass];
1139 return (sides == tclass.sides()
1140 && columns == tclass.columns()
1141 && pagestyle == tclass.pagestyle()
1142 && options == tclass.options()
1143 && secnumdepth == tclass.secnumdepth()
1144 && tocdepth == tclass.tocdepth());
1148 LyXTextClass const & BufferParams::getLyXTextClass() const
1150 return textclasslist[textclass];
1154 LyXFont const BufferParams::getFont() const
1156 LyXFont f = getLyXTextClass().defaultfont();
1157 f.setLanguage(language);
1158 if (fontsDefaultFamily == "rmdefault")
1159 f.setFamily(LyXFont::ROMAN_FAMILY);
1160 else if (fontsDefaultFamily == "sfdefault")
1161 f.setFamily(LyXFont::SANS_FAMILY);
1162 else if (fontsDefaultFamily == "ttdefault")
1163 f.setFamily(LyXFont::TYPEWRITER_FAMILY);
1168 void BufferParams::readPreamble(LyXLex & lex)
1170 if (lex.getString() != "\\begin_preamble")
1171 lyxerr << "Error (BufferParams::readPreamble):"
1172 "consistency check failed." << endl;
1174 preamble = lex.getLongString("\\end_preamble");
1178 void BufferParams::readLanguage(LyXLex & lex)
1180 if (!lex.next()) return;
1182 string const tmptok = lex.getString();
1184 // check if tmptok is part of tex_babel in tex-defs.h
1185 language = languages.getLanguage(tmptok);
1187 // Language tmptok was not found
1188 language = default_language;
1189 lyxerr << "Warning: Setting language `"
1190 << tmptok << "' to `" << language->lang()
1196 void BufferParams::readGraphicsDriver(LyXLex & lex)
1198 if (!lex.next()) return;
1200 string const tmptok = lex.getString();
1201 // check if tmptok is part of tex_graphics in tex_defs.h
1204 string const test = tex_graphics[n++];
1206 if (test == tmptok) {
1207 graphicsDriver = tmptok;
1209 } else if (test == "") {
1211 "Warning: graphics driver `$$Token' not recognized!\n"
1212 " Setting graphics driver to `default'.\n");
1213 graphicsDriver = "default";
1220 void BufferParams::readBullets(LyXLex & lex)
1222 if (!lex.next()) return;
1224 int const index = lex.getInteger();
1226 int temp_int = lex.getInteger();
1227 user_defined_bullet(index).setFont(temp_int);
1228 temp_bullet(index).setFont(temp_int);
1230 user_defined_bullet(index).setCharacter(temp_int);
1231 temp_bullet(index).setCharacter(temp_int);
1233 user_defined_bullet(index).setSize(temp_int);
1234 temp_bullet(index).setSize(temp_int);
1238 void BufferParams::readBulletsLaTeX(LyXLex & lex)
1240 // The bullet class should be able to read this.
1241 if (!lex.next()) return;
1242 int const index = lex.getInteger();
1244 docstring const temp_str = lex.getDocString();
1246 user_defined_bullet(index).setText(temp_str);
1247 temp_bullet(index).setText(temp_str);
1251 string const BufferParams::paperSizeName() const
1253 char real_papersize = papersize;
1254 if (real_papersize == PAPER_DEFAULT)
1255 real_papersize = lyxrc.default_papersize;
1257 switch (real_papersize) {
1266 case PAPER_USEXECUTIVE:
1270 case PAPER_USLETTER:
1277 string const BufferParams::dvips_options() const
1282 && papersize == PAPER_CUSTOM
1283 && !lyxrc.print_paper_dimension_flag.empty()
1284 && !paperwidth.empty()
1285 && !paperheight.empty()) {
1286 // using a custom papersize
1287 result = lyxrc.print_paper_dimension_flag;
1288 result += ' ' + paperwidth;
1289 result += ',' + paperheight;
1291 string const paper_option = paperSizeName();
1292 if (paper_option != "letter" ||
1293 orientation != ORIENTATION_LANDSCAPE) {
1294 // dvips won't accept -t letter -t landscape.
1295 // In all other cases, include the paper size
1297 result = lyxrc.print_paper_flag;
1298 result += ' ' + paper_option;
1301 if (orientation == ORIENTATION_LANDSCAPE &&
1302 papersize != PAPER_CUSTOM)
1303 result += ' ' + lyxrc.print_landscape_flag;
1308 string const BufferParams::babelCall(string const & lang_opts) const
1310 string tmp = lyxrc.language_package;
1311 if (!lyxrc.language_global_options && tmp == "\\usepackage{babel}")
1312 tmp = string("\\usepackage[") + lang_opts + "]{babel}";
1317 string const BufferParams::loadFonts(LaTeXFeatures & features, string const & rm,
1318 string const & sf, string const & tt,
1319 bool const & sc, bool const & osf,
1320 int const & sfscale, int const & ttscale) const
1322 /* The LaTeX font world is in a flux. In the PSNFSS font interface,
1323 several packages have been replaced by others, that might not
1324 be installed on every system. We have to take care for that
1325 (see psnfss.pdf). We try to support all psnfss fonts as well
1326 as the fonts that have become de facto standard in the LaTeX
1327 world (e.g. Latin Modern). We do not support obsolete fonts
1328 (like PSLatex). In general, it should be possible to mix any
1329 rm font with any sf or tt font, respectively. (JSpitzm)
1331 -- separate math fonts.
1334 if (rm == "default" && sf == "default" && tt == "default")
1341 // Computer Modern (must be explicitely selectable -- there might be classes
1342 // that define a different default font!
1344 os << "\\renewcommand{\\rmdefault}{cmr}\n";
1345 // osf for Computer Modern needs eco.sty
1347 os << "\\usepackage{eco}\n";
1349 // Latin Modern Roman
1350 else if (rm == "lmodern")
1351 os << "\\usepackage{lmodern}\n";
1353 else if (rm == "ae") {
1354 // not needed when using OT1 font encoding.
1355 if (lyxrc.fontenc != "default")
1356 os << "\\usepackage{ae,aecompl}\n";
1359 else if (rm == "times") {
1360 // try to load the best available package
1361 if (features.isAvailable("mathptmx"))
1362 os << "\\usepackage{mathptmx}\n";
1363 else if (features.isAvailable("mathptm"))
1364 os << "\\usepackage{mathptm}\n";
1366 os << "\\usepackage{times}\n";
1369 else if (rm == "palatino") {
1370 // try to load the best available package
1371 if (features.isAvailable("mathpazo")) {
1372 os << "\\usepackage";
1378 // "osf" includes "sc"!
1382 os << "{mathpazo}\n";
1384 else if (features.isAvailable("mathpple"))
1385 os << "\\usepackage{mathpple}\n";
1387 os << "\\usepackage{palatino}\n";
1390 else if (rm == "utopia") {
1391 // fourier supersedes utopia.sty, but does
1392 // not work with OT1 encoding.
1393 if (features.isAvailable("fourier")
1394 && lyxrc.fontenc != "default") {
1395 os << "\\usepackage";
1406 os << "{fourier}\n";
1409 os << "\\usepackage{utopia}\n";
1411 // Bera (complete fontset)
1412 else if (rm == "bera" && sf == "default" && tt == "default")
1413 os << "\\usepackage{bera}\n";
1415 else if (rm != "default")
1416 os << "\\usepackage" << "{" << rm << "}\n";
1419 // Helvetica, Bera Sans
1420 if (sf == "helvet" || sf == "berasans") {
1422 os << "\\usepackage[scaled=" << float(sfscale) / 100
1423 << "]{" << sf << "}\n";
1425 os << "\\usepackage{" << sf << "}\n";
1428 else if (sf == "avant")
1429 os << "\\usepackage{" << sf << "}\n";
1430 // Computer Modern, Latin Modern, CM Bright
1431 else if (sf != "default")
1432 os << "\\renewcommand{\\sfdefault}{" << sf << "}\n";
1434 // monospaced/typewriter
1435 // Courier, LuxiMono
1436 if (tt == "luximono" || tt == "beramono") {
1438 os << "\\usepackage[scaled=" << float(ttscale) / 100
1439 << "]{" << tt << "}\n";
1441 os << "\\usepackage{" << tt << "}\n";
1444 else if (tt == "courier" )
1445 os << "\\usepackage{" << tt << "}\n";
1446 // Computer Modern, Latin Modern, CM Bright
1447 else if (tt != "default")
1448 os << "\\renewcommand{\\ttdefault}{" << tt << "}\n";